@Test public void testStateTransition() throws InterruptedException, ExecutionException, TimeoutException { InMemoryZKServer zkServer = InMemoryZKServer.builder().build(); zkServer.startAndWait(); try { final String namespace = Joiner.on('/').join("/twill", RunIds.generate(), "runnables", "Runner1"); final ZKClientService zkClient = ZKClientService.Builder.of(zkServer.getConnectionStr()).build(); zkClient.startAndWait(); zkClient.create(namespace, null, CreateMode.PERSISTENT).get(); try { JsonObject content = new JsonObject(); content.addProperty("containerId", "container-123"); content.addProperty("host", "localhost"); RunId runId = RunIds.generate(); final Semaphore semaphore = new Semaphore(0); ZKServiceDecorator service = new ZKServiceDecorator( ZKClients.namespace(zkClient, namespace), runId, Suppliers.ofInstance(content), new AbstractIdleService() { @Override protected void startUp() throws Exception { Preconditions.checkArgument( semaphore.tryAcquire(5, TimeUnit.SECONDS), "Fail to start"); } @Override protected void shutDown() throws Exception { Preconditions.checkArgument( semaphore.tryAcquire(5, TimeUnit.SECONDS), "Fail to stop"); } }); final String runnablePath = namespace + "/" + runId.getId(); final AtomicReference<String> stateMatch = new AtomicReference<String>("STARTING"); watchDataChange(zkClient, runnablePath + "/state", semaphore, stateMatch); Assert.assertEquals(Service.State.RUNNING, service.start().get(5, TimeUnit.SECONDS)); stateMatch.set("STOPPING"); Assert.assertEquals(Service.State.TERMINATED, service.stop().get(5, TimeUnit.SECONDS)); } finally { zkClient.stopAndWait(); } } finally { zkServer.stopAndWait(); } }
private static ZKClient getContainerZKClient( ZKClient zkClient, RunId appRunId, String runnableName) { return ZKClients.namespace(zkClient, String.format("/%s/runnables/%s", appRunId, runnableName)); }
/** Returns a {@link ZKClient} that namespaced under the given run id. */ private static ZKClient getAppRunZKClient(ZKClient zkClient, RunId appRunId) { return ZKClients.namespace(zkClient, String.format("/%s", appRunId)); }