All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.hubspot.singularity.data.history.SingularityDbModule Maven / Gradle / Ivy

package com.hubspot.singularity.data.history;

import static com.google.common.base.Preconditions.checkNotNull;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.collect.ImmutableSet;
import com.google.inject.AbstractModule;
import com.google.inject.Inject;
import com.google.inject.Provider;
import com.google.inject.ProvisionException;
import com.google.inject.Scopes;
import com.hubspot.singularity.Singularity;
import com.hubspot.singularity.config.SingularityConfiguration;
import com.hubspot.singularity.data.usage.JDBITaskUsageManager;
import com.hubspot.singularity.data.usage.MySQLTaskUsageJDBI;
import com.hubspot.singularity.data.usage.PostgresTaskUsageJDBI;
import com.hubspot.singularity.data.usage.TaskUsageJDBI;
import com.hubspot.singularity.data.usage.TaskUsageManager;
import com.hubspot.singularity.data.usage.ZkTaskUsageManager;
import io.dropwizard.db.DataSourceFactory;
import io.dropwizard.jdbi3.JdbiFactory;
import io.dropwizard.setup.Environment;
import java.util.Optional;
import java.util.Set;
import org.jdbi.v3.core.Jdbi;
import org.jdbi.v3.core.mapper.ColumnMapper;
import org.jdbi.v3.core.mapper.RowMapper;
import org.jdbi.v3.jackson2.Jackson2Config;
import org.jdbi.v3.jackson2.Jackson2Plugin;

public class SingularityDbModule extends AbstractModule {
  private final Optional configuration;

  public SingularityDbModule(SingularityConfiguration configuration) {
    checkNotNull(configuration, "configuration is null");
    this.configuration = configuration.getDatabaseConfiguration();
  }

  @Override
  protected void configure() {
    // Setup database support
    if (configuration.isPresent()) {
      bind(Jdbi.class).toProvider(DBIProvider.class).in(Scopes.SINGLETON);
      bindSpecificDatabase();
      bind(HistoryManager.class).to(JDBIHistoryManager.class).in(Scopes.SINGLETON);
      bind(TaskUsageManager.class).to(JDBITaskUsageManager.class).in(Scopes.SINGLETON);
    } else {
      bind(HistoryManager.class).to(NoopHistoryManager.class).in(Scopes.SINGLETON);
      bind(TaskUsageManager.class).to(ZkTaskUsageManager.class).in(Scopes.SINGLETON);
    }
  }

  private void bindSpecificDatabase() {
    if (isPostgres(configuration)) {
      bind(HistoryJDBI.class)
        .toProvider(PostgresHistoryJDBIProvider.class)
        .in(Scopes.SINGLETON);
      bind(TaskUsageJDBI.class)
        .toProvider(PostgresTaskUsageJDBIProvider.class)
        .in(Scopes.SINGLETON);
      // Currently many unit tests use h2
    } else if (isMySQL(configuration) || isH2(configuration)) {
      bind(HistoryJDBI.class)
        .toProvider(MySQLHistoryJDBIProvider.class)
        .in(Scopes.SINGLETON);
      bind(TaskUsageJDBI.class)
        .toProvider(MySQLTaskUsageJDBIProvider.class)
        .in(Scopes.SINGLETON);
    } else {
      throw new IllegalStateException(
        "Unknown driver class present " + configuration.get().getDriverClass()
      );
    }
  }

  static class DBIProvider implements Provider {
    private final JdbiFactory factory = new JdbiFactory();
    private final Environment environment;
    private final DataSourceFactory dataSourceFactory;

    private Set> rowMappers = ImmutableSet.of();
    private Set> columnMappers = ImmutableSet.of();
    private ObjectMapper objectMapper;

    @Inject
    DBIProvider(
      final Environment environment,
      final SingularityConfiguration singularityConfiguration
    )
      throws ClassNotFoundException {
      this.environment = environment;
      this.dataSourceFactory =
        checkNotNull(singularityConfiguration, "singularityConfiguration is null")
          .getDatabaseConfiguration()
          .get();
    }

    @Inject(optional = true)
    void setMappers(
      Set> rowMappers,
      Set> columnMappers,
      @Singularity ObjectMapper objectMapper
    ) {
      checkNotNull(rowMappers, "resultSetMappers is null");
      this.rowMappers = ImmutableSet.copyOf(rowMappers);
      this.columnMappers = ImmutableSet.copyOf(columnMappers);
      this.objectMapper = objectMapper;
    }

    @Override
    public Jdbi get() {
      try {
        Jdbi jdbi = factory.build(environment, dataSourceFactory, "db");
        for (RowMapper resultSetMapper : rowMappers) {
          jdbi.registerRowMapper(resultSetMapper);
        }
        for (ColumnMapper resultSetMapper : columnMappers) {
          jdbi.registerColumnMapper(resultSetMapper);
        }
        jdbi.installPlugin(new Jackson2Plugin());
        jdbi.getConfig(Jackson2Config.class).setMapper(objectMapper);

        return jdbi;
      } catch (Exception e) {
        throw new ProvisionException("while instantiating DBI", e);
      }
    }
  }

  static class MySQLHistoryJDBIProvider implements Provider {
    private final Jdbi dbi;

    @Inject
    public MySQLHistoryJDBIProvider(Jdbi dbi) {
      this.dbi = dbi;
    }

    @Override
    public MySQLHistoryJDBI get() {
      return dbi.onDemand(MySQLHistoryJDBI.class);
    }
  }

  static class PostgresHistoryJDBIProvider implements Provider {
    private final Jdbi dbi;

    @Inject
    public PostgresHistoryJDBIProvider(Jdbi dbi) {
      this.dbi = dbi;
    }

    @Override
    public PostgresHistoryJDBI get() {
      return dbi.onDemand(PostgresHistoryJDBI.class);
    }
  }

  static class MySQLTaskUsageJDBIProvider implements Provider {
    private final Jdbi dbi;

    @Inject
    public MySQLTaskUsageJDBIProvider(Jdbi dbi) {
      this.dbi = dbi;
    }

    @Override
    public MySQLTaskUsageJDBI get() {
      return dbi.onDemand(MySQLTaskUsageJDBI.class);
    }
  }

  static class PostgresTaskUsageJDBIProvider implements Provider {
    private final Jdbi dbi;

    @Inject
    public PostgresTaskUsageJDBIProvider(Jdbi dbi) {
      this.dbi = dbi;
    }

    @Override
    public PostgresTaskUsageJDBI get() {
      return dbi.onDemand(PostgresTaskUsageJDBI.class);
    }
  }

  // Convenience methods for determining which database is configured
  static boolean isH2(Optional dataSourceFactoryOptional) {
    return driverConfigured(dataSourceFactoryOptional, "org.h2.Driver");
  }

  static boolean isMySQL(Optional dataSourceFactoryOptional) {
    return driverConfigured(dataSourceFactoryOptional, "com.mysql.jdbc.Driver");
  }

  static boolean isPostgres(Optional dataSourceFactoryOptional) {
    return driverConfigured(dataSourceFactoryOptional, "org.postgresql.Driver");
  }

  private static boolean driverConfigured(
    Optional dataSourceFactoryOptional,
    String jdbcDriverclass
  ) {
    return (
      dataSourceFactoryOptional != null &&
      dataSourceFactoryOptional.isPresent() &&
      jdbcDriverclass.equals(dataSourceFactoryOptional.get().getDriverClass())
    );
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy