| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you 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 org.apache.druid.cli; |
| |
| import com.fasterxml.jackson.core.type.TypeReference; |
| import com.fasterxml.jackson.databind.ObjectMapper; |
| import com.github.rvesse.airline.annotations.Command; |
| import com.google.common.base.Strings; |
| import com.google.common.base.Supplier; |
| import com.google.common.collect.ImmutableSet; |
| import com.google.inject.Binder; |
| import com.google.inject.Inject; |
| import com.google.inject.Key; |
| import com.google.inject.Module; |
| import com.google.inject.Provider; |
| import com.google.inject.Provides; |
| import com.google.inject.TypeLiteral; |
| import com.google.inject.multibindings.MapBinder; |
| import com.google.inject.name.Names; |
| import com.google.inject.util.Providers; |
| import org.apache.druid.client.CoordinatorSegmentWatcherConfig; |
| import org.apache.druid.client.CoordinatorServerView; |
| import org.apache.druid.client.DirectDruidClientFactory; |
| import org.apache.druid.client.HttpServerInventoryViewResource; |
| import org.apache.druid.client.InternalQueryConfig; |
| import org.apache.druid.client.coordinator.Coordinator; |
| import org.apache.druid.discovery.DruidLeaderSelector; |
| import org.apache.druid.discovery.NodeRole; |
| import org.apache.druid.guice.DruidBinders; |
| import org.apache.druid.guice.Jerseys; |
| import org.apache.druid.guice.JsonConfigProvider; |
| import org.apache.druid.guice.JsonConfigurator; |
| import org.apache.druid.guice.LazySingleton; |
| import org.apache.druid.guice.LifecycleModule; |
| import org.apache.druid.guice.ManageLifecycle; |
| import org.apache.druid.guice.QueryableModule; |
| import org.apache.druid.guice.annotations.EscalatedGlobal; |
| import org.apache.druid.guice.annotations.Global; |
| import org.apache.druid.guice.http.JettyHttpClientModule; |
| import org.apache.druid.indexing.overlord.TaskMaster; |
| import org.apache.druid.indexing.overlord.TaskStorage; |
| import org.apache.druid.java.util.common.IAE; |
| import org.apache.druid.java.util.common.ISE; |
| import org.apache.druid.java.util.common.StringUtils; |
| import org.apache.druid.java.util.common.concurrent.Execs; |
| import org.apache.druid.java.util.common.concurrent.ExecutorServices; |
| import org.apache.druid.java.util.common.concurrent.ScheduledExecutorFactory; |
| import org.apache.druid.java.util.common.lifecycle.Lifecycle; |
| import org.apache.druid.java.util.common.logger.Logger; |
| import org.apache.druid.java.util.http.client.HttpClient; |
| import org.apache.druid.metadata.MetadataRuleManager; |
| import org.apache.druid.metadata.MetadataRuleManagerConfig; |
| import org.apache.druid.metadata.MetadataRuleManagerProvider; |
| import org.apache.druid.metadata.MetadataStorage; |
| import org.apache.druid.metadata.MetadataStorageProvider; |
| import org.apache.druid.metadata.SegmentsMetadataManager; |
| import org.apache.druid.metadata.SegmentsMetadataManagerConfig; |
| import org.apache.druid.metadata.SegmentsMetadataManagerProvider; |
| import org.apache.druid.query.DefaultGenericQueryMetricsFactory; |
| import org.apache.druid.query.DefaultQueryConfig; |
| import org.apache.druid.query.GenericQueryMetricsFactory; |
| import org.apache.druid.query.MapQueryToolChestWarehouse; |
| import org.apache.druid.query.Query; |
| import org.apache.druid.query.QueryRunnerFactory; |
| import org.apache.druid.query.QuerySegmentWalker; |
| import org.apache.druid.query.QueryToolChest; |
| import org.apache.druid.query.QueryToolChestWarehouse; |
| import org.apache.druid.query.QueryWatcher; |
| import org.apache.druid.query.RetryQueryRunnerConfig; |
| import org.apache.druid.query.lookup.LookupSerdeModule; |
| import org.apache.druid.query.metadata.SegmentMetadataQueryConfig; |
| import org.apache.druid.query.metadata.SegmentMetadataQueryQueryToolChest; |
| import org.apache.druid.query.metadata.SegmentMetadataQueryRunnerFactory; |
| import org.apache.druid.query.metadata.metadata.SegmentMetadataQuery; |
| import org.apache.druid.segment.incremental.RowIngestionMetersFactory; |
| import org.apache.druid.segment.metadata.CentralizedDatasourceSchemaConfig; |
| import org.apache.druid.segment.metadata.CoordinatorSegmentMetadataCache; |
| import org.apache.druid.segment.metadata.SegmentMetadataCacheConfig; |
| import org.apache.druid.segment.metadata.SegmentMetadataQuerySegmentWalker; |
| import org.apache.druid.segment.metadata.SegmentSchemaCache; |
| import org.apache.druid.server.QueryScheduler; |
| import org.apache.druid.server.QuerySchedulerProvider; |
| import org.apache.druid.server.coordinator.CoordinatorConfigManager; |
| import org.apache.druid.server.coordinator.DruidCoordinator; |
| import org.apache.druid.server.coordinator.MetadataManager; |
| import org.apache.druid.server.coordinator.balancer.BalancerStrategyFactory; |
| import org.apache.druid.server.coordinator.balancer.CachingCostBalancerStrategyConfig; |
| import org.apache.druid.server.coordinator.compact.CompactionSegmentSearchPolicy; |
| import org.apache.druid.server.coordinator.compact.NewestSegmentFirstPolicy; |
| import org.apache.druid.server.coordinator.config.CoordinatorKillConfigs; |
| import org.apache.druid.server.coordinator.config.CoordinatorPeriodConfig; |
| import org.apache.druid.server.coordinator.config.CoordinatorRunConfig; |
| import org.apache.druid.server.coordinator.config.DruidCoordinatorConfig; |
| import org.apache.druid.server.coordinator.config.HttpLoadQueuePeonConfig; |
| import org.apache.druid.server.coordinator.duty.CoordinatorCustomDuty; |
| import org.apache.druid.server.coordinator.duty.CoordinatorCustomDutyGroup; |
| import org.apache.druid.server.coordinator.duty.CoordinatorCustomDutyGroups; |
| import org.apache.druid.server.coordinator.loading.LoadQueueTaskMaster; |
| import org.apache.druid.server.http.ClusterResource; |
| import org.apache.druid.server.http.CompactionResource; |
| import org.apache.druid.server.http.CoordinatorCompactionConfigsResource; |
| import org.apache.druid.server.http.CoordinatorDynamicConfigsResource; |
| import org.apache.druid.server.http.CoordinatorRedirectInfo; |
| import org.apache.druid.server.http.CoordinatorResource; |
| import org.apache.druid.server.http.DataSourcesResource; |
| import org.apache.druid.server.http.IntervalsResource; |
| import org.apache.druid.server.http.LookupCoordinatorResource; |
| import org.apache.druid.server.http.MetadataResource; |
| import org.apache.druid.server.http.RedirectFilter; |
| import org.apache.druid.server.http.RedirectInfo; |
| import org.apache.druid.server.http.RulesResource; |
| import org.apache.druid.server.http.SelfDiscoveryResource; |
| import org.apache.druid.server.http.ServersResource; |
| import org.apache.druid.server.http.TiersResource; |
| import org.apache.druid.server.initialization.jetty.JettyServerInitializer; |
| import org.apache.druid.server.lookup.cache.LookupCoordinatorManager; |
| import org.apache.druid.server.lookup.cache.LookupCoordinatorManagerConfig; |
| import org.apache.druid.server.metrics.ServiceStatusMonitor; |
| import org.apache.druid.server.router.TieredBrokerConfig; |
| import org.eclipse.jetty.server.Server; |
| import org.joda.time.Duration; |
| |
| import java.util.ArrayList; |
| import java.util.HashMap; |
| import java.util.HashSet; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.Properties; |
| import java.util.Set; |
| import java.util.concurrent.ExecutorService; |
| |
| /** |
| * |
| */ |
| @Command( |
| name = "coordinator", |
| description = "Runs the Coordinator, see https://druid.apache.org/docs/latest/Coordinator.html for a description." |
| ) |
| public class CliCoordinator extends ServerRunnable |
| { |
| private static final Logger log = new Logger(CliCoordinator.class); |
| private static final String AS_OVERLORD_PROPERTY = "druid.coordinator.asOverlord.enabled"; |
| private Properties properties; |
| private boolean beOverlord; |
| private boolean isSegmentMetadataCacheEnabled; |
| |
| public CliCoordinator() |
| { |
| super(log); |
| } |
| |
| @Inject |
| public void configure(Properties properties) |
| { |
| this.properties = properties; |
| beOverlord = isOverlord(properties); |
| isSegmentMetadataCacheEnabled = isSegmentMetadataCacheEnabled(properties); |
| |
| if (beOverlord) { |
| log.info("Coordinator is configured to act as Overlord as well (%s = true).", AS_OVERLORD_PROPERTY); |
| } |
| } |
| |
| @Override |
| protected Set<NodeRole> getNodeRoles(Properties properties) |
| { |
| return isOverlord(properties) |
| ? ImmutableSet.of(NodeRole.COORDINATOR, NodeRole.OVERLORD) |
| : ImmutableSet.of(NodeRole.COORDINATOR); |
| } |
| |
| |
| @Override |
| protected List<? extends Module> getModules() |
| { |
| List<Module> modules = new ArrayList<>(); |
| |
| modules.add(JettyHttpClientModule.global()); |
| |
| if (isSegmentMetadataCacheEnabled) { |
| validateCentralizedDatasourceSchemaConfig(properties); |
| modules.add(new CoordinatorSegmentMetadataCacheModule()); |
| modules.add(new QueryableModule()); |
| } |
| |
| modules.add( |
| new Module() |
| { |
| @Override |
| public void configure(Binder binder) |
| { |
| binder.bindConstant() |
| .annotatedWith(Names.named("serviceName")) |
| .to(TieredBrokerConfig.DEFAULT_COORDINATOR_SERVICE_NAME); |
| binder.bindConstant().annotatedWith(Names.named("servicePort")).to(8081); |
| binder.bindConstant().annotatedWith(Names.named("tlsServicePort")).to(8281); |
| |
| binder.bind(MetadataStorage.class).toProvider(MetadataStorageProvider.class); |
| |
| JsonConfigProvider.bind(binder, SegmentsMetadataManagerConfig.CONFIG_PREFIX, SegmentsMetadataManagerConfig.class); |
| JsonConfigProvider.bind(binder, "druid.manager.rules", MetadataRuleManagerConfig.class); |
| JsonConfigProvider.bind(binder, "druid.manager.lookups", LookupCoordinatorManagerConfig.class); |
| JsonConfigProvider.bind(binder, "druid.coordinator", CoordinatorRunConfig.class); |
| JsonConfigProvider.bind(binder, "druid.coordinator.kill", CoordinatorKillConfigs.class); |
| JsonConfigProvider.bind(binder, "druid.coordinator.period", CoordinatorPeriodConfig.class); |
| JsonConfigProvider.bind(binder, "druid.coordinator.loadqueuepeon.http", HttpLoadQueuePeonConfig.class); |
| JsonConfigProvider.bind(binder, "druid.coordinator.balancer", BalancerStrategyFactory.class); |
| JsonConfigProvider.bind(binder, "druid.coordinator.segment", CoordinatorSegmentWatcherConfig.class); |
| JsonConfigProvider.bind( |
| binder, |
| "druid.coordinator.balancer.cachingCost", |
| CachingCostBalancerStrategyConfig.class |
| ); |
| JsonConfigProvider.bind(binder, "druid.coordinator.segmentMetadataCache", SegmentMetadataCacheConfig.class); |
| binder.bind(DruidCoordinatorConfig.class); |
| |
| binder.bind(RedirectFilter.class).in(LazySingleton.class); |
| if (beOverlord) { |
| binder.bind(RedirectInfo.class).to(CoordinatorOverlordRedirectInfo.class).in(LazySingleton.class); |
| } else { |
| binder.bind(RedirectInfo.class).to(CoordinatorRedirectInfo.class).in(LazySingleton.class); |
| } |
| |
| LifecycleModule.register(binder, CoordinatorServerView.class); |
| |
| if (!isSegmentMetadataCacheEnabled) { |
| binder.bind(CoordinatorSegmentMetadataCache.class).toProvider(Providers.of(null)); |
| binder.bind(DirectDruidClientFactory.class).toProvider(Providers.of(null)); |
| } |
| |
| binder.bind(SegmentsMetadataManager.class) |
| .toProvider(SegmentsMetadataManagerProvider.class) |
| .in(ManageLifecycle.class); |
| |
| binder.bind(MetadataRuleManager.class) |
| .toProvider(MetadataRuleManagerProvider.class) |
| .in(ManageLifecycle.class); |
| |
| binder.bind(LookupCoordinatorManager.class).in(LazySingleton.class); |
| |
| binder.bind(CoordinatorConfigManager.class); |
| binder.bind(MetadataManager.class); |
| binder.bind(DruidCoordinator.class); |
| |
| LifecycleModule.register(binder, MetadataStorage.class); |
| LifecycleModule.register(binder, DruidCoordinator.class); |
| |
| binder.bind(JettyServerInitializer.class) |
| .to(CoordinatorJettyServerInitializer.class); |
| |
| Jerseys.addResource(binder, CoordinatorResource.class); |
| Jerseys.addResource(binder, CompactionResource.class); |
| Jerseys.addResource(binder, CoordinatorDynamicConfigsResource.class); |
| Jerseys.addResource(binder, CoordinatorCompactionConfigsResource.class); |
| Jerseys.addResource(binder, TiersResource.class); |
| Jerseys.addResource(binder, RulesResource.class); |
| Jerseys.addResource(binder, ServersResource.class); |
| Jerseys.addResource(binder, DataSourcesResource.class); |
| Jerseys.addResource(binder, MetadataResource.class); |
| Jerseys.addResource(binder, IntervalsResource.class); |
| Jerseys.addResource(binder, LookupCoordinatorResource.class); |
| Jerseys.addResource(binder, ClusterResource.class); |
| Jerseys.addResource(binder, HttpServerInventoryViewResource.class); |
| |
| LifecycleModule.register(binder, Server.class); |
| LifecycleModule.register(binder, DataSourcesResource.class); |
| |
| if (properties.containsKey("druid.coordinator.merge.on")) { |
| throw new UnsupportedOperationException( |
| "'druid.coordinator.merge.on' is not supported anymore. " |
| + "Please consider using Coordinator's automatic compaction instead. " |
| + "See https://druid.apache.org/docs/latest/operations/segment-optimization.html and " |
| + "https://druid.apache.org/docs/latest/api-reference/api-reference.html#compaction-configuration " |
| + "for more details about compaction." |
| ); |
| } |
| |
| //TODO: make this configurable when there are multiple search policies |
| binder.bind(CompactionSegmentSearchPolicy.class).to(NewestSegmentFirstPolicy.class); |
| |
| bindAnnouncer( |
| binder, |
| Coordinator.class, |
| DiscoverySideEffectsProvider.create() |
| ); |
| |
| Jerseys.addResource(binder, SelfDiscoveryResource.class); |
| LifecycleModule.registerKey(binder, Key.get(SelfDiscoveryResource.class)); |
| |
| if (!beOverlord) { |
| // These are needed to deserialize SupervisorSpec for Supervisor Auto Cleanup |
| binder.bind(TaskStorage.class).toProvider(Providers.of(null)); |
| binder.bind(TaskMaster.class).toProvider(Providers.of(null)); |
| binder.bind(RowIngestionMetersFactory.class).toProvider(Providers.of(null)); |
| // Bind HeartbeatSupplier only when the service operates independently of Overlord. |
| binder.bind(new TypeLiteral<Supplier<Map<String, Object>>>() {}) |
| .annotatedWith(Names.named(ServiceStatusMonitor.HEARTBEAT_TAGS_BINDING)) |
| .toProvider(HeartbeatSupplier.class); |
| } |
| |
| binder.bind(CoordinatorCustomDutyGroups.class) |
| .toProvider(new CoordinatorCustomDutyGroupsProvider()) |
| .in(LazySingleton.class); |
| } |
| |
| @Provides |
| @LazySingleton |
| public LoadQueueTaskMaster getLoadQueueTaskMaster( |
| ObjectMapper jsonMapper, |
| ScheduledExecutorFactory factory, |
| DruidCoordinatorConfig config, |
| @EscalatedGlobal HttpClient httpClient, |
| Lifecycle lifecycle |
| ) |
| { |
| final ExecutorService callBackExec = Execs.singleThreaded("LoadQueuePeon-callbackexec--%d"); |
| ExecutorServices.manageLifecycle(lifecycle, callBackExec); |
| return new LoadQueueTaskMaster( |
| jsonMapper, |
| factory.create(1, "Master-PeonExec--%d"), |
| callBackExec, |
| config.getHttpLoadQueuePeonConfig(), |
| httpClient |
| ); |
| } |
| } |
| ); |
| |
| if (beOverlord) { |
| CliOverlord cliOverlord = new CliOverlord(); |
| cliOverlord.configure(properties); |
| modules.addAll(cliOverlord.getModules(false)); |
| } else { |
| // Only add LookupSerdeModule if !beOverlord, since CliOverlord includes it, and having two copies causes |
| // the injector to get confused due to having multiple bindings for the same classes. |
| modules.add(new LookupSerdeModule()); |
| } |
| |
| return modules; |
| } |
| |
| public static boolean isOverlord(Properties properties) |
| { |
| return Boolean.parseBoolean(properties.getProperty(AS_OVERLORD_PROPERTY)); |
| } |
| |
| |
| private static class CoordinatorCustomDutyGroupsProvider implements Provider<CoordinatorCustomDutyGroups> |
| { |
| private Properties props; |
| private JsonConfigurator configurator; |
| private ObjectMapper jsonMapper; |
| |
| @Inject |
| public void inject(Properties props, JsonConfigurator configurator, ObjectMapper jsonMapper) |
| { |
| this.props = props; |
| this.configurator = configurator; |
| this.jsonMapper = jsonMapper; |
| } |
| |
| @Override |
| public CoordinatorCustomDutyGroups get() |
| { |
| try { |
| Set<CoordinatorCustomDutyGroup> coordinatorCustomDutyGroups = new HashSet<>(); |
| if (Strings.isNullOrEmpty(props.getProperty("druid.coordinator.dutyGroups"))) { |
| return new CoordinatorCustomDutyGroups(coordinatorCustomDutyGroups); |
| } |
| List<String> coordinatorCustomDutyGroupNames = jsonMapper.readValue(props.getProperty( |
| "druid.coordinator.dutyGroups"), new TypeReference<List<String>>() {}); |
| for (String coordinatorCustomDutyGroupName : coordinatorCustomDutyGroupNames) { |
| String dutyListProperty = StringUtils.format("druid.coordinator.%s.duties", coordinatorCustomDutyGroupName); |
| if (Strings.isNullOrEmpty(props.getProperty(dutyListProperty))) { |
| throw new IAE("Coordinator custom duty group given without any duty for group %s", coordinatorCustomDutyGroupName); |
| } |
| List<String> dutyForGroup = jsonMapper.readValue(props.getProperty(dutyListProperty), new TypeReference<List<String>>() {}); |
| List<CoordinatorCustomDuty> coordinatorCustomDuties = new ArrayList<>(); |
| for (String dutyName : dutyForGroup) { |
| final String dutyPropertyBase = StringUtils.format( |
| "druid.coordinator.%s.duty.%s", |
| coordinatorCustomDutyGroupName, |
| dutyName |
| ); |
| final JsonConfigProvider<CoordinatorCustomDuty> coordinatorCustomDutyProvider = JsonConfigProvider.of( |
| dutyPropertyBase, |
| CoordinatorCustomDuty.class |
| ); |
| |
| String typeProperty = StringUtils.format("%s.type", dutyPropertyBase); |
| Properties adjustedProps = new Properties(props); |
| if (adjustedProps.containsKey(typeProperty)) { |
| throw new IAE("'type' property [%s] is reserved.", typeProperty); |
| } else { |
| adjustedProps.put(typeProperty, dutyName); |
| } |
| coordinatorCustomDutyProvider.inject(adjustedProps, configurator); |
| CoordinatorCustomDuty coordinatorCustomDuty = coordinatorCustomDutyProvider.get(); |
| if (coordinatorCustomDuty == null) { |
| throw new ISE("Could not create CoordinatorCustomDuty with name: %s for group: %s", dutyName, coordinatorCustomDutyGroupName); |
| } |
| coordinatorCustomDuties.add(coordinatorCustomDuty); |
| } |
| String groupPeriodPropKey = StringUtils.format("druid.coordinator.%s.period", coordinatorCustomDutyGroupName); |
| if (Strings.isNullOrEmpty(props.getProperty(groupPeriodPropKey))) { |
| throw new IAE("Run period for coordinator custom duty group must be set for group %s", coordinatorCustomDutyGroupName); |
| } |
| Duration groupPeriod = new Duration(props.getProperty(groupPeriodPropKey)); |
| coordinatorCustomDutyGroups.add(new CoordinatorCustomDutyGroup(coordinatorCustomDutyGroupName, groupPeriod, coordinatorCustomDuties)); |
| } |
| return new CoordinatorCustomDutyGroups(coordinatorCustomDutyGroups); |
| } |
| catch (Exception e) { |
| throw new RuntimeException(e); |
| } |
| } |
| } |
| |
| private static class HeartbeatSupplier implements Provider<Supplier<Map<String, Object>>> |
| { |
| private final DruidLeaderSelector leaderSelector; |
| |
| @Inject |
| public HeartbeatSupplier(@Coordinator DruidLeaderSelector leaderSelector) |
| { |
| this.leaderSelector = leaderSelector; |
| } |
| |
| @Override |
| public Supplier<Map<String, Object>> get() |
| { |
| return () -> { |
| Map<String, Object> heartbeatTags = new HashMap<>(); |
| heartbeatTags.put("leader", leaderSelector.isLeader() ? 1 : 0); |
| |
| return heartbeatTags; |
| }; |
| } |
| } |
| |
| private static class CoordinatorSegmentMetadataCacheModule implements Module |
| { |
| @Override |
| public void configure(Binder binder) |
| { |
| JsonConfigProvider.bind(binder, "druid.coordinator.segmentMetadata", SegmentMetadataQueryConfig.class); |
| JsonConfigProvider.bind(binder, "druid.coordinator.query.scheduler", QuerySchedulerProvider.class, Global.class); |
| JsonConfigProvider.bind(binder, "druid.coordinator.query.default", DefaultQueryConfig.class); |
| JsonConfigProvider.bind(binder, "druid.coordinator.query.retryPolicy", RetryQueryRunnerConfig.class); |
| JsonConfigProvider.bind(binder, "druid.coordinator.internal.query.config", InternalQueryConfig.class); |
| JsonConfigProvider.bind(binder, CentralizedDatasourceSchemaConfig.PROPERTY_PREFIX, CentralizedDatasourceSchemaConfig.class); |
| |
| MapBinder<Class<? extends Query>, QueryToolChest> toolChests = DruidBinders.queryToolChestBinder(binder); |
| toolChests.addBinding(SegmentMetadataQuery.class).to(SegmentMetadataQueryQueryToolChest.class); |
| binder.bind(SegmentMetadataQueryQueryToolChest.class).in(LazySingleton.class); |
| binder.bind(QueryToolChestWarehouse.class).to(MapQueryToolChestWarehouse.class); |
| |
| final MapBinder<Class<? extends Query>, QueryRunnerFactory> queryFactoryBinder = |
| DruidBinders.queryRunnerFactoryBinder(binder); |
| queryFactoryBinder.addBinding(SegmentMetadataQuery.class).to(SegmentMetadataQueryRunnerFactory.class); |
| binder.bind(SegmentMetadataQueryRunnerFactory.class).in(LazySingleton.class); |
| |
| binder.bind(GenericQueryMetricsFactory.class).to(DefaultGenericQueryMetricsFactory.class); |
| |
| binder.bind(QueryScheduler.class) |
| .toProvider(Key.get(QuerySchedulerProvider.class, Global.class)) |
| .in(LazySingleton.class); |
| binder.bind(QuerySchedulerProvider.class).in(LazySingleton.class); |
| binder.bind(SegmentSchemaCache.class).in(LazySingleton.class); |
| binder.bind(QuerySegmentWalker.class).to(SegmentMetadataQuerySegmentWalker.class).in(LazySingleton.class); |
| |
| LifecycleModule.register(binder, CoordinatorSegmentMetadataCache.class); |
| } |
| |
| @LazySingleton |
| @Provides |
| public QueryWatcher getWatcher(QueryScheduler scheduler) |
| { |
| return scheduler; |
| } |
| } |
| } |