@Override protected void startUp() { LOG.info("Starting {}", getClass().getSimpleName()); config = bootstrapConfigProvider.getConfig(); executorService = Executors.newSingleThreadExecutor(Threads.createDaemonThreadFactory("bootstrap-service")); executorService.execute(() -> { try { if (isBootstrappedWithRetries()) { // if the system is already bootstrapped, skip any bootstrap step that is supposed to only run once bootstrap(step -> step.getRunCondition() == BootstrapStep.RunCondition.ONCE); } else { bootstrap(); } } catch (InterruptedException e) { LOG.info("Bootstrapping could not complete due to interruption. It will be re-run the next time CDAP starts."); } }); LOG.info("Started {}", getClass().getSimpleName()); }
private boolean isBootstrappedWithRetries() { return Retries.callWithRetries(this::isBootstrapped, RetryStrategies.fixDelay(6, TimeUnit.SECONDS), t -> { // don't retry if we were interrupted, or if the service is not running // normally this is only called when the service is starting, but it can be running in unit test State serviceState = state(); if (serviceState != State.STARTING && serviceState != State.RUNNING) { return false; } if (t instanceof InterruptedException) { return false; } // Otherwise always retry, but log unexpected types of failures // We expect things like SocketTimeoutException or ConnectException // when talking to Dataset Service during startup Throwable rootCause = Throwables.getRootCause(t); if (!(rootCause instanceof SocketTimeoutException || rootCause instanceof ConnectException)) { SAMPLING_LOG.warn("Error checking bootstrap state. " + "Bootstrap steps will not be run until state can be checked.", t); } return true; }); } }
/** * Execute all steps in the loaded bootstrap config without skipping any of them. * * @return the result of executing the bootstrap steps. * @throws IllegalStateException if bootstrapping is already in progress * @throws InterruptedException if bootstrapping was interrupted */ public BootstrapResult bootstrap() throws InterruptedException { return bootstrap(x -> false); }
Thread t = new Thread(() -> { try { bootstrapService.bootstrap(); } catch (InterruptedException e) { Assert.assertFalse(bootstrapService.isBootstrapped()); Assert.assertTrue(wasInterrupted.get());
@BeforeClass public static void setupClass() { Map<BootstrapStep.Type, BootstrapStepExecutor> executors = new HashMap<>(); executors.put(STEP1.getType(), EXECUTOR1); executors.put(STEP2.getType(), EXECUTOR2); executors.put(STEP3.getType(), EXECUTOR3); List<BootstrapStep> steps = new ArrayList<>(3); steps.add(STEP1); steps.add(STEP2); steps.add(STEP3); bootstrapConfig = new BootstrapConfig(steps); BootstrapConfigProvider bootstrapConfigProvider = new InMemoryBootstrapConfigProvider(bootstrapConfig); bootstrapStore = AppFabricTestHelper.getInjector().getInstance(BootstrapStore.class); bootstrapService = new BootstrapService(bootstrapConfigProvider, bootstrapStore, executors); bootstrapService.reload(); }
@Override protected void shutDown() throws Exception { coreSchedulerService.stopAndWait(); routeStore.close(); bootstrapService.stopAndWait(); cancelHttpService.cancel(); programRuntimeService.stopAndWait(); applicationLifecycleService.stopAndWait(); programNotificationSubscriberService.stopAndWait(); runRecordCorrectorService.stopAndWait(); pluginService.stopAndWait(); provisioningService.stopAndWait(); if (runCountUpgradeService != null && runCountUpgradeService.isRunning()) { runCountUpgradeService.stopAndWait(); } }
/** * Execute the steps in the loaded bootstrap config. * * @param shouldSkip predicate that determines whether to skip a step * @return the result of executing the bootstrap steps. * @throws IllegalStateException if bootstrapping is already in progress * @throws InterruptedException if bootstrapping was interrupted */ public BootstrapResult bootstrap(Predicate<BootstrapStep> shouldSkip) throws InterruptedException { List<BootstrapStepResult> results = new ArrayList<>(config.getSteps().size()); if (!bootstrapping.compareAndSet(false, true)) { throw new IllegalStateException("Bootstrap already in progress."); } try { for (BootstrapStep step : config.getSteps()) { results.add(executeStep(step, shouldSkip)); } if (!config.getSteps().isEmpty()) { bootstrapStore.bootstrapped(); } return new BootstrapResult(results); } finally { bootstrapping.set(false); } }
provisioningService.start(), applicationLifecycleService.start(), bootstrapService.start(), programRuntimeService.start(), programNotificationSubscriberService.start(),
/** * Execute all steps in the loaded bootstrap config without skipping any of them. * * @return the result of executing the bootstrap steps. * @throws IllegalStateException if bootstrapping is already in progress * @throws InterruptedException if bootstrapping was interrupted */ public BootstrapResult bootstrap() throws InterruptedException { return bootstrap(x -> false); }
@Test public void testAllSuccess() throws Exception { BootstrapResult result = bootstrapService.bootstrap(); List<BootstrapStepResult> expectedStepResults = new ArrayList<>(); for (BootstrapStep step : bootstrapConfig.getSteps()) { expectedStepResults.add(new BootstrapStepResult(step.getLabel(), BootstrapStepResult.Status.SUCCEEDED)); } BootstrapResult expected = new BootstrapResult(expectedStepResults); Assert.assertEquals(expected, result); Assert.assertTrue(bootstrapService.isBootstrapped()); }
@Override protected void shutDown() throws Exception { coreSchedulerService.stopAndWait(); routeStore.close(); bootstrapService.stopAndWait(); cancelHttpService.cancel(); programRuntimeService.stopAndWait(); applicationLifecycleService.stopAndWait(); notificationService.stopAndWait(); programNotificationSubscriberService.stopAndWait(); runRecordCorrectorService.stopAndWait(); pluginService.stopAndWait(); provisioningService.stopAndWait(); if (runCountUpgradeService != null && runCountUpgradeService.isRunning()) { runCountUpgradeService.stopAndWait(); } }
/** * Execute the steps in the loaded bootstrap config. * * @param shouldSkip predicate that determines whether to skip a step * @return the result of executing the bootstrap steps. * @throws IllegalStateException if bootstrapping is already in progress * @throws InterruptedException if bootstrapping was interrupted */ public BootstrapResult bootstrap(Predicate<BootstrapStep> shouldSkip) throws InterruptedException { List<BootstrapStepResult> results = new ArrayList<>(config.getSteps().size()); if (!bootstrapping.compareAndSet(false, true)) { throw new IllegalStateException("Bootstrap already in progress."); } try { for (BootstrapStep step : config.getSteps()) { results.add(executeStep(step, shouldSkip)); } if (!config.getSteps().isEmpty()) { bootstrapStore.bootstrapped(); } return new BootstrapResult(results); } finally { bootstrapping.set(false); } }
provisioningService.start(), applicationLifecycleService.start(), bootstrapService.start(), programRuntimeService.start(), streamCoordinatorClient.start(),
@Test public void testNoConcurrentBootstrap() throws Exception { CountDownLatch runningLatch = new CountDownLatch(1); CountDownLatch waitingLatch = new CountDownLatch(1); EXECUTOR1.setLatches(runningLatch, waitingLatch); Thread t = new Thread(() -> { try { bootstrapService.bootstrap(); } catch (InterruptedException e) { runningLatch.countDown(); } }); t.start(); runningLatch.await(); try { bootstrapService.bootstrap(); Assert.fail("BootstrapService should not allow concurrent bootstrap operations"); } catch (IllegalStateException e) { // expected } finally { waitingLatch.countDown(); } }
@Override protected void startUp() { LOG.info("Starting {}", getClass().getSimpleName()); config = bootstrapConfigProvider.getConfig(); executorService = Executors.newSingleThreadExecutor(Threads.createDaemonThreadFactory("bootstrap-service")); executorService.execute(() -> { try { if (isBootstrappedWithRetries()) { // if the system is already bootstrapped, skip any bootstrap step that is supposed to only run once bootstrap(step -> step.getRunCondition() == BootstrapStep.RunCondition.ONCE); } else { bootstrap(); } } catch (InterruptedException e) { LOG.info("Bootstrapping could not complete due to interruption. It will be re-run the next time CDAP starts."); } }); LOG.info("Started {}", getClass().getSimpleName()); }
private boolean isBootstrappedWithRetries() { return Retries.callWithRetries(this::isBootstrapped, RetryStrategies.fixDelay(6, TimeUnit.SECONDS), t -> { // don't retry if we were interrupted, or if the service is not running // normally this is only called when the service is starting, but it can be running in unit test State serviceState = state(); if (serviceState != State.STARTING && serviceState != State.RUNNING) { return false; } if (t instanceof InterruptedException) { return false; } // Otherwise always retry, but log unexpected types of failures // We expect things like SocketTimeoutException or ConnectException // when talking to Dataset Service during startup Throwable rootCause = Throwables.getRootCause(t); if (!(rootCause instanceof SocketTimeoutException || rootCause instanceof ConnectException)) { SAMPLING_LOG.warn("Error checking bootstrap state. " + "Bootstrap steps will not be run until state can be checked.", t); } return true; }); } }
@Test public void testRetries() throws Exception { EXECUTOR1.setNumRetryableFailures(3); BootstrapResult result = bootstrapService.bootstrap(); List<BootstrapStepResult> expectedStepResults = new ArrayList<>(); for (BootstrapStep step : bootstrapConfig.getSteps()) { expectedStepResults.add(new BootstrapStepResult(step.getLabel(), BootstrapStepResult.Status.SUCCEEDED)); } BootstrapResult expected = new BootstrapResult(expectedStepResults); Assert.assertEquals(expected, result); }
@Test public void testContinuesAfterFailures() throws Exception { EXECUTOR1.shouldFail(); BootstrapResult result = bootstrapService.bootstrap(); List<BootstrapStepResult> stepResults = new ArrayList<>(3); stepResults.add(new BootstrapStepResult(STEP1.getLabel(), BootstrapStepResult.Status.FAILED)); stepResults.add(new BootstrapStepResult(STEP2.getLabel(), BootstrapStepResult.Status.SUCCEEDED)); stepResults.add(new BootstrapStepResult(STEP3.getLabel(), BootstrapStepResult.Status.SUCCEEDED)); BootstrapResult expected = new BootstrapResult(stepResults); Assert.assertEquals(expected, result); }