container1.fail(new IntentionalException()); val startContainer2 = registry.startContainer(containerId, TIMEOUT); Assert.assertFalse("startContainer() completed before previous container shut down (with failure).", startContainer2.isDone()); TestContainer container2 = (TestContainer) registry.getContainer(containerId); Assert.assertEquals("Container1 was not shut down (with failure).", Service.State.FAILED, container1.state()); Assert.assertEquals("Container2 was not started properly.", Service.State.RUNNING, container2.state()); container2.stopAsync(); val startContainer3 = registry.startContainer(containerId, TIMEOUT); Assert.assertFalse("startContainer() completed before previous container shut down (normally).", startContainer3.isDone()); TestContainer container3 = (TestContainer) registry.getContainer(containerId); Assert.assertEquals("Container2 was not shut down (normally).", Service.State.TERMINATED, container2.state()); Assert.assertEquals("Container3 was not started properly.", Service.State.RUNNING, container3.state());
/** * Tests the ability to stop the container via the stopContainer() method. */ @Test public void testStopContainer() throws Exception { final int containerId = 123; TestContainerFactory factory = new TestContainerFactory(); @Cleanup StreamSegmentContainerRegistry registry = new StreamSegmentContainerRegistry(factory, executorService()); ContainerHandle handle = registry.startContainer(containerId, TIMEOUT).join(); // Register a Listener for the Container.Stop event. Make this a Future since these callbacks are invoked async // so they may finish executing after stop() finished. CompletableFuture<Integer> stopListenerCallback = new CompletableFuture<>(); handle.setContainerStoppedListener(stopListenerCallback::complete); TestContainer container = (TestContainer) registry.getContainer(handle.getContainerId()); Assert.assertFalse("Container is closed before being shut down.", container.isClosed()); registry.stopContainer(handle, TIMEOUT).join(); Assert.assertEquals("Unexpected value passed to Handle.stopListenerCallback or callback was not invoked.", containerId, (int) stopListenerCallback.join()); Assert.assertTrue("Container is not closed after being shut down.", container.isClosed()); AssertExtensions.assertThrows( "Container is still registered after being shut down.", () -> registry.getContainer(handle.getContainerId()), ex -> ex instanceof ContainerNotFoundException); }
@Override protected void doStop() { executorService().execute(() -> { ReusableLatch signal = this.stopSignal; if (signal != null) { // Wait until we are told to stop. signal.awaitUninterruptibly(); } if (state() != State.FAILED && state() != State.TERMINATED && this.stopException != null) { notifyFailed(this.stopException); } else { notifyStopped(); } }); }
/** * Tests the ability to detect a container failure and unregister the container in case the container fails while running. */ @Test public void testContainerFailureWhileRunning() throws Exception { final int containerId = 123; TestContainerFactory factory = new TestContainerFactory(); @Cleanup StreamSegmentContainerRegistry registry = new StreamSegmentContainerRegistry(factory, executorService()); ContainerHandle handle = registry.startContainer(containerId, TIMEOUT).join(); // Register a Listener for the Container.Stop event. Make this a Future since these callbacks are invoked async // so they may finish executing after stop() finished. CompletableFuture<Integer> stopListenerCallback = new CompletableFuture<>(); handle.setContainerStoppedListener(stopListenerCallback::complete); TestContainer container = (TestContainer) registry.getContainer(handle.getContainerId()); // Fail the container and wait for it to properly terminate. container.fail(new IntentionalException()); ServiceListeners.awaitShutdown(container, false); Assert.assertEquals("Unexpected value passed to Handle.stopListenerCallback or callback was not invoked.", containerId, (int) stopListenerCallback.join()); AssertExtensions.assertThrows( "Container is still registered after failure.", () -> registry.getContainer(containerId), ex -> ex instanceof ContainerNotFoundException); }
public void fail(Exception ex) { this.stopException = ex; stopAsync(); }
@Override public SegmentContainer createStreamSegmentContainer(int containerId) { return new TestContainer(containerId, this.startException, this.startReleaseSignal); } }
@Override protected void doStart() { executorService().execute(() -> { if (this.startException != null) { notifyFailed(this.startException); } else { notifyStarted(); } }); }