package com.jivesoftware.os.amzabot.deployable; import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.ObjectMapper; import com.jivesoftware.os.amza.api.partition.Consistency; import com.jivesoftware.os.amza.api.partition.Durability; import com.jivesoftware.os.amza.client.http.AmzaClientProvider; import com.jivesoftware.os.amza.client.http.HttpPartitionClientFactory; import com.jivesoftware.os.amza.client.http.HttpPartitionHostsProvider; import com.jivesoftware.os.amza.client.http.RingHostHttpClientProvider; import com.jivesoftware.os.amzabot.deployable.AmzaBotHealthCheck.AmzaBotHealthCheckConfig; import com.jivesoftware.os.amzabot.deployable.bot.AmzaBotCoalmineConfig; import com.jivesoftware.os.amzabot.deployable.bot.AmzaBotCoalmineService; import com.jivesoftware.os.amzabot.deployable.bot.AmzaBotRandomOpConfig; import com.jivesoftware.os.amzabot.deployable.bot.AmzaBotRandomOpService; import com.jivesoftware.os.amzabot.deployable.endpoint.AmzaBotCoalmineEndpoints; import com.jivesoftware.os.amzabot.deployable.endpoint.AmzaBotEndpoints; import com.jivesoftware.os.amzabot.deployable.endpoint.AmzaBotRandomOpEndpoints; import com.jivesoftware.os.amzabot.deployable.ui.amzabot.AmzaBotUIEndpoints; import com.jivesoftware.os.amzabot.deployable.ui.amzabot.AmzaBotUIInitializer; import com.jivesoftware.os.amzabot.deployable.ui.amzabot.AmzaBotUIInitializer.AmzaBotUIServiceConfig; import com.jivesoftware.os.amzabot.deployable.ui.amzabot.AmzaBotUIService; import com.jivesoftware.os.amzabot.deployable.ui.health.UiEndpoints; import com.jivesoftware.os.amzabot.deployable.ui.health.UiService; import com.jivesoftware.os.amzabot.deployable.ui.health.UiServiceInitializer; import com.jivesoftware.os.amzabot.deployable.ui.health.UiServiceInitializer.UiServiceConfig; import com.jivesoftware.os.jive.utils.ordered.id.ConstantWriterIdProvider; import com.jivesoftware.os.jive.utils.ordered.id.OrderIdProvider; import com.jivesoftware.os.jive.utils.ordered.id.OrderIdProviderImpl; import com.jivesoftware.os.routing.bird.deployable.Deployable; import com.jivesoftware.os.routing.bird.deployable.DeployableHealthCheckRegistry; import com.jivesoftware.os.routing.bird.deployable.ErrorHealthCheckConfig; import com.jivesoftware.os.routing.bird.deployable.InstanceConfig; import com.jivesoftware.os.routing.bird.deployable.config.extractor.ConfigBinder; import com.jivesoftware.os.routing.bird.endpoints.base.FullyOnlineVersion; import com.jivesoftware.os.routing.bird.endpoints.base.HasUI; import com.jivesoftware.os.routing.bird.endpoints.base.HasUI.UI; import com.jivesoftware.os.routing.bird.health.api.HealthFactory; import com.jivesoftware.os.routing.bird.health.checkers.FileDescriptorCountHealthChecker; import com.jivesoftware.os.routing.bird.health.checkers.GCLoadHealthChecker; import com.jivesoftware.os.routing.bird.health.checkers.GCPauseHealthChecker; import com.jivesoftware.os.routing.bird.health.checkers.LoadAverageHealthChecker; import com.jivesoftware.os.routing.bird.health.checkers.ServiceStartupHealthCheck; import com.jivesoftware.os.routing.bird.health.checkers.SystemCpuHealthChecker; import com.jivesoftware.os.routing.bird.http.client.HttpClient; import com.jivesoftware.os.routing.bird.http.client.HttpDeliveryClientHealthProvider; import com.jivesoftware.os.routing.bird.http.client.HttpRequestHelperUtils; import com.jivesoftware.os.routing.bird.http.client.TailAtScaleStrategy; import com.jivesoftware.os.routing.bird.http.client.TenantAwareHttpClient; import com.jivesoftware.os.routing.bird.server.util.Resource; import com.jivesoftware.os.routing.bird.shared.HttpClientException; import java.io.File; import java.util.Arrays; import java.util.UUID; import java.util.concurrent.Executors; public class AmzaBotMain { public static void main(String[] args) throws Exception { new AmzaBotMain().run(args); } private void run(String[] args) throws Exception { ServiceStartupHealthCheck serviceStartupHealthCheck = new ServiceStartupHealthCheck(); try { ConfigBinder configBinder = new ConfigBinder(args); InstanceConfig instanceConfig = configBinder.bind(InstanceConfig.class); final Deployable deployable = new Deployable(args, configBinder, instanceConfig, null); HealthFactory.initialize(deployable::config, new DeployableHealthCheckRegistry(deployable)); deployable.addManageInjectables(HasUI.class, new HasUI(Arrays.asList(new UI("AmzaBot", "main", "/")))); AmzaKeyClearingHousePool amzaKeyClearingHousePool = new AmzaKeyClearingHousePool(); AmzaBotHealthCheck amzaBotHealthCheck = new AmzaBotHealthCheck(instanceConfig, deployable.config(AmzaBotHealthCheckConfig.class), amzaKeyClearingHousePool); deployable.addHealthCheck( new GCPauseHealthChecker(deployable.config(GCPauseHealthChecker.GCPauseHealthCheckerConfig.class)), new GCLoadHealthChecker(deployable.config(GCLoadHealthChecker.GCLoadHealthCheckerConfig.class)), new SystemCpuHealthChecker(deployable.config(SystemCpuHealthChecker.SystemCpuHealthCheckerConfig.class)), new LoadAverageHealthChecker(deployable.config(LoadAverageHealthChecker.LoadAverageHealthCheckerConfig.class)), new FileDescriptorCountHealthChecker(deployable.config(FileDescriptorCountHealthChecker.FileDescriptorCountHealthCheckerConfig.class)), amzaBotHealthCheck, serviceStartupHealthCheck); deployable.addErrorHealthChecks(deployable.config(ErrorHealthCheckConfig.class)); deployable.addManageInjectables(FullyOnlineVersion.class, (FullyOnlineVersion) () -> { if (serviceStartupHealthCheck.startupHasSucceeded()) { return instanceConfig.getVersion(); } else { return null; } }); deployable.buildManageServer().start(); HttpDeliveryClientHealthProvider clientHealthProvider = new HttpDeliveryClientHealthProvider(instanceConfig.getInstanceKey(), HttpRequestHelperUtils.buildRequestHelper(false, false, null, instanceConfig.getRoutesHost(), instanceConfig.getRoutesPort()), instanceConfig.getConnectionsHealth(), 5_000, 100); @SuppressWarnings("unchecked") TenantAwareHttpClient<String> amzaClient = deployable.getTenantRoutingHttpClientInitializer().builder( deployable.getTenantRoutingProvider().getConnections("amza", "main", 10_000), // TODO config clientHealthProvider) .deadAfterNErrors(10) .checkDeadEveryNMillis(10_000) .socketTimeoutInMillis(60_000) .build(); // TODO expose to conf ObjectMapper objectMapper = new ObjectMapper(); objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); AmzaBotConfig amzaBotConfig = configBinder.bind(AmzaBotConfig.class); AmzaBotCoalmineConfig amzaBotCoalmineConfig = configBinder.bind(AmzaBotCoalmineConfig.class); AmzaBotRandomOpConfig amzaBotRandomOpConfig = configBinder.bind(AmzaBotRandomOpConfig.class); TailAtScaleStrategy tailAtScaleStrategy = new TailAtScaleStrategy( deployable.newBoundedExecutor(1024, "tas"), 100, // TODO config 95, // TODO config 1000 // TODO config ); AmzaClientProvider<HttpClient, HttpClientException> amzaClientProvider = new AmzaClientProvider<>( new HttpPartitionClientFactory(), new HttpPartitionHostsProvider(amzaClient, tailAtScaleStrategy, objectMapper), new RingHostHttpClientProvider(amzaClient), Executors.newFixedThreadPool(amzaBotConfig.getAmzaCallerThreadPoolSize()), amzaBotConfig.getAmzaAwaitLeaderElectionForNMillis(), -1, -1); AmzaBotService amzaBotService = new AmzaBotService( amzaBotConfig, amzaClientProvider, () -> -1L, Durability.fsync_async, Consistency.leader_quorum, "amzabot-rest", amzaBotConfig.getRingSize(), 0, 0); OrderIdProvider orderIdProviderRandomOp = () -> -1L; if (amzaBotRandomOpConfig.getClientOrdering()) { orderIdProviderRandomOp = new OrderIdProviderImpl( new ConstantWriterIdProvider(instanceConfig.getInstanceName())); } AmzaBotRandomOpService amzaBotRandomOpService = new AmzaBotRandomOpService( amzaBotRandomOpConfig, new AmzaBotService( amzaBotConfig, amzaClientProvider, orderIdProviderRandomOp, Durability.valueOf(amzaBotRandomOpConfig.getDurability()), Consistency.valueOf(amzaBotRandomOpConfig.getConsistency()), "amzabot-randomops-" + UUID.randomUUID().toString(), amzaBotRandomOpConfig.getRingSize(), amzaBotRandomOpConfig.getTombstoneTimestampAgeInMillis(), amzaBotRandomOpConfig.getTombstoneTimestampIntervalMillis()), amzaKeyClearingHousePool.genAmzaKeyClearingHouse()); amzaBotRandomOpService.start(); AmzaBotCoalmineService amzaBotCoalmineService = new AmzaBotCoalmineService( instanceConfig, amzaBotConfig, amzaBotCoalmineConfig, amzaClientProvider, amzaKeyClearingHousePool); amzaBotCoalmineService.start(); String cacheToken = String.valueOf(System.currentTimeMillis()); AmzaBotUIServiceConfig amzabotUIServiceConfig = deployable.config(AmzaBotUIServiceConfig.class); AmzaBotUIService amzabotUIService = new AmzaBotUIInitializer() .initialize(cacheToken, amzabotUIServiceConfig); UiServiceConfig uiServiceConfig = deployable.config(UiServiceConfig.class); UiService uiService = new UiServiceInitializer().initialize(cacheToken, uiServiceConfig); File staticResourceDir = new File(System.getProperty("user.dir")); Resource sourceTree = new Resource(staticResourceDir) .addResourcePath(amzabotUIServiceConfig.getPathToStaticResources()) .setDirectoryListingAllowed(false) .setContext("/amzabot/static"); deployable.addInjectables(AmzaBotService.class, amzaBotService); deployable.addInjectables(AmzaBotRandomOpService.class, amzaBotRandomOpService); deployable.addInjectables(AmzaBotCoalmineService.class, amzaBotCoalmineService); deployable.addEndpoints(AmzaBotEndpoints.class); deployable.addEndpoints(AmzaBotRandomOpEndpoints.class); deployable.addEndpoints(AmzaBotCoalmineEndpoints.class); deployable.addEndpoints(AmzaBotUIEndpoints.class); deployable.addInjectables(AmzaBotUIService.class, amzabotUIService); deployable.addEndpoints(UiEndpoints.class); deployable.addInjectables(UiService.class, uiService); deployable.addResource(sourceTree); deployable.enableSwagger("com.jivesoftware.os.amzabot.deployable"); deployable.buildServer().start(); clientHealthProvider.start(); serviceStartupHealthCheck.success(); } catch (Throwable t) { serviceStartupHealthCheck.info("Failure encountered during startup.", t); } } }