blob: 24ceba96b661d98b98a9f090740327280ea64ad3 [file] [log] [blame]
// Copyright (C) 2017 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package com.ericsson.gerrit.plugins.gcconductor.postgresqueue;
import static com.ericsson.gerrit.plugins.gcconductor.postgresqueue.DatabaseConstants.DRIVER;
import static com.ericsson.gerrit.plugins.gcconductor.postgresqueue.DatabaseConstants.INITIAL_DATABASE;
import static com.ericsson.gerrit.plugins.gcconductor.postgresqueue.DatabaseConstants.createDatabase;
import static com.ericsson.gerrit.plugins.gcconductor.postgresqueue.DatabaseConstants.databaseExists;
import static com.ericsson.gerrit.plugins.gcconductor.postgresqueue.DatabaseConstants.executeStatement;
import com.ericsson.gerrit.plugins.gcconductor.CommonConfig;
import com.ericsson.gerrit.plugins.gcconductor.GcQueue;
import com.ericsson.gerrit.plugins.gcconductor.ShutdownListener;
import com.google.common.annotations.VisibleForTesting;
import com.google.inject.AbstractModule;
import com.google.inject.Inject;
import com.google.inject.Provides;
import com.google.inject.Singleton;
import com.google.inject.internal.UniqueAnnotations;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import org.apache.commons.dbcp.BasicDataSource;
/** Configures bindings of the Postgres queue implementation. */
public class PostgresModule extends AbstractModule {
private static final long EVICT_IDLE_TIME_MS = 1000L * 60;
private Class<? extends CommonConfig> commonConfig;
public PostgresModule(Class<? extends CommonConfig> commonConfig) {
this.commonConfig = commonConfig;
}
@Override
protected void configure() {
bind(CommonConfig.class).to(commonConfig);
bind(GcQueue.class).to(PostgresQueue.class);
bind(ShutdownListener.class)
.annotatedWith(UniqueAnnotations.create())
.to(DatabaseAccessCleanUp.class);
}
/**
* Provide access to the gc database. Database will be created if it does not exist.
*
* @param cfg The database configuration
* @return BasicDataSource to access gc database.
* @throws SQLException If an error occur while creating the database.
*/
@Provides
@Singleton
BasicDataSource provideGcDatabaseAccess(CommonConfig cfg) throws SQLException {
BasicDataSource adminDataSource = createDataSource(cfg, INITIAL_DATABASE);
try (Connection conn = adminDataSource.getConnection();
Statement stat = conn.createStatement();
ResultSet resultSet = stat.executeQuery(databaseExists(cfg.getDatabaseName()))) {
if (!resultSet.next()) {
executeStatement(adminDataSource, createDatabase(cfg.getDatabaseName()));
}
} finally {
adminDataSource.close();
}
return createDataSource(cfg, cfg.getDatabaseName());
}
private static BasicDataSource createDataSource(CommonConfig cfg, String database) {
BasicDataSource ds = new BasicDataSource();
ds.setDriverClassName(DRIVER);
ds.setUrl(cfg.getDatabaseUrl() + database + cfg.getDatabaseUrlOptions());
ds.setUsername(cfg.getUsername());
ds.setPassword(cfg.getPassword());
ds.setMinEvictableIdleTimeMillis(EVICT_IDLE_TIME_MS);
ds.setTimeBetweenEvictionRunsMillis(EVICT_IDLE_TIME_MS / 2);
return ds;
}
/** Close the database access when plugin is unloaded */
@VisibleForTesting
static class DatabaseAccessCleanUp implements ShutdownListener {
private final BasicDataSource dataSource;
@Inject
public DatabaseAccessCleanUp(BasicDataSource dataSource) {
this.dataSource = dataSource;
}
@Override
public void onShutdown() {
try {
dataSource.close();
} catch (SQLException e) {
throw new RuntimeException("Failed to close database connection: " + e.getMessage(), e);
}
}
}
}