package org.rakam.clickhouse; import com.google.auto.service.AutoService; import com.google.common.collect.ImmutableList; import com.google.inject.Binder; import com.google.inject.Scopes; import com.google.inject.TypeLiteral; import com.google.inject.multibindings.Multibinder; import com.google.inject.name.Names; import org.rakam.analysis.ApiKeyService; import org.rakam.analysis.ConfigManager; import org.rakam.analysis.ContinuousQueryService; import org.rakam.analysis.EscapeIdentifier; import org.rakam.analysis.EventExplorer; import org.rakam.analysis.FunnelQueryExecutor; import org.rakam.analysis.JDBCPoolDataSource; import org.rakam.analysis.MaterializedViewService; import org.rakam.analysis.RealtimeService.RealtimeAggregations; import org.rakam.analysis.RetentionQueryExecutor; import org.rakam.analysis.TimestampToEpochFunction; import org.rakam.analysis.metadata.JDBCQueryMetadata; import org.rakam.analysis.metadata.Metastore; import org.rakam.analysis.metadata.QueryMetadataStore; import org.rakam.aws.dynamodb.metastore.DynamodbMetastore; import org.rakam.clickhouse.analysis.ClickHouseEventExplorer; import org.rakam.clickhouse.analysis.ClickHouseFunnelQueryExecutor; import org.rakam.clickhouse.analysis.ClickHouseMetastore; import org.rakam.clickhouse.analysis.ClickHouseRetentionQueryExecutor; import org.rakam.clickhouse.collection.AWSKinesisClickhouseEventStore; import org.rakam.clickhouse.collection.ClickHouseEventStore; import org.rakam.config.MetadataConfig; import org.rakam.plugin.EventMapper; import org.rakam.plugin.EventStore; import org.rakam.plugin.RakamModule; import org.rakam.plugin.TimestampEventMapper; import org.rakam.plugin.user.AbstractUserService; import org.rakam.plugin.user.UserPluginConfig; import org.rakam.plugin.user.UserStorage; import org.rakam.report.QueryExecutor; import org.rakam.report.eventexplorer.EventExplorerConfig; import org.rakam.report.realtime.AggregationType; import org.rakam.util.ConditionalModule; import java.util.List; import static io.airlift.configuration.ConfigBinder.configBinder; import static org.rakam.report.realtime.AggregationType.APPROXIMATE_UNIQUE; import static org.rakam.report.realtime.AggregationType.COUNT; import static org.rakam.report.realtime.AggregationType.COUNT_UNIQUE; import static org.rakam.report.realtime.AggregationType.MAXIMUM; import static org.rakam.report.realtime.AggregationType.MINIMUM; import static org.rakam.report.realtime.AggregationType.SUM; @AutoService(RakamModule.class) @ConditionalModule(config = "store.adapter", value = "clickhouse") public class ClickHouseModule extends RakamModule { @Override protected void setup(Binder binder) { configBinder(binder).bindConfig(MetadataConfig.class); configBinder(binder).bindConfig(ClickHouseConfig.class); binder.bind(char.class).annotatedWith(EscapeIdentifier.class).toInstance('`'); binder.bind(QueryExecutor.class).to(ClickHouseQueryExecutor.class); binder.bind(EventStore.class).to(AWSKinesisClickhouseEventStore.class); binder.bind(ContinuousQueryService.class).to(ClickHouseContinuousQueryService.class); binder.bind(MaterializedViewService.class).to(ClickHouseMaterializedViewService.class); binder.bind(String.class).annotatedWith(TimestampToEpochFunction.class) .toInstance("toUnixTimestamp"); binder.bind(new TypeLiteral<List<AggregationType>>() {}) .annotatedWith(RealtimeAggregations.class) .toInstance(ImmutableList.of( COUNT, SUM, MINIMUM, MAXIMUM, APPROXIMATE_UNIQUE, COUNT_UNIQUE)); binder.bind(AbstractUserService.class).to(ClickHouseUserService.class) .in(Scopes.SINGLETON); if (buildConfigObject(EventExplorerConfig.class).isEventExplorerEnabled()) { binder.bind(EventExplorer.class).to(ClickHouseEventExplorer.class); } UserPluginConfig userPluginConfig = buildConfigObject(UserPluginConfig.class); if (userPluginConfig.getEnableUserMapping()) { throw new IllegalStateException("Clickhouse module doesn't support user mapping."); } if (userPluginConfig.isFunnelAnalysisEnabled()) { binder.bind(FunnelQueryExecutor.class).to(ClickHouseFunnelQueryExecutor.class); } if (userPluginConfig.isRetentionAnalysisEnabled()) { binder.bind(RetentionQueryExecutor.class).to(ClickHouseRetentionQueryExecutor.class); } Multibinder<EventMapper> timeMapper = Multibinder.newSetBinder(binder, EventMapper.class); timeMapper.addBinding().to(TimestampEventMapper.class).in(Scopes.SINGLETON); } @Override public String name() { return "ClickHouse backend for Rakam"; } @Override public String description() { return "Rakam backend for big-data."; } }