use of io.pravega.client.state.Update in project pravega by pravega.
the class ReaderGroupImplTest method testAsyncResetReaderGroup.
@Test(timeout = 10000L)
@SuppressWarnings("unchecked")
public void testAsyncResetReaderGroup() {
UUID rgId = UUID.randomUUID();
ReaderGroupConfig config1 = ReaderGroupConfig.builder().startFromStreamCuts(ImmutableMap.<Stream, StreamCut>builder().put(createStream("s1"), createStreamCut("s1", 2)).build()).build();
config1 = ReaderGroupConfig.cloneConfig(config1, rgId, 0L);
ReaderGroupConfig config2 = ReaderGroupConfig.builder().startFromStreamCuts(ImmutableMap.<Stream, StreamCut>builder().put(createStream("s2"), createStreamCut("s2", 2)).build()).build();
config2 = ReaderGroupConfig.cloneConfig(config2, rgId, 0L);
ReaderGroupConfig config3 = ReaderGroupConfig.builder().startFromStreamCuts(ImmutableMap.<Stream, StreamCut>builder().put(createStream("s3"), createStreamCut("s3", 2)).build()).build();
config3 = ReaderGroupConfig.cloneConfig(config3, rgId, 0L);
AtomicInteger x = new AtomicInteger(0);
CompletableFuture<Void> wait = new CompletableFuture<>();
CompletableFuture<Void> signal = new CompletableFuture<>();
// The client's config.
AtomicReference<ReaderGroupConfig> atomicConfig = new AtomicReference<>(config1);
// The controller's config.
AtomicReference<ReaderGroupConfig> atomicConfigController = new AtomicReference<>(config1);
// return the client's config when calling state.getConfig.
doAnswer(a -> atomicConfig.get()).when(state).getConfig();
when(synchronizer.getState()).thenReturn(state);
// return controllerConfig when calling getReaderGroupConfig.
doAnswer(a -> CompletableFuture.completedFuture(atomicConfigController.get())).when(controller).getReaderGroupConfig(anyString(), anyString());
// update the client config to the controller config whenever we update the StateSync.
doAnswer(a -> {
atomicConfig.set(atomicConfigController.get());
return null;
}).when(synchronizer).updateState(any(StateSynchronizer.UpdateGenerator.class));
// update the controller config with the incremented generation if the generations match.
doAnswer(a -> {
ReaderGroupConfig c = a.getArgument(2);
// the first one to call needs to wait until the second call has been completed.
if (x.getAndIncrement() == 0) {
signal.complete(null);
wait.join();
}
if (c.getGeneration() == atomicConfigController.get().getGeneration()) {
long incGen = c.getGeneration() + 1;
atomicConfigController.set(ReaderGroupConfig.cloneConfig(c, c.getReaderGroupId(), incGen));
return CompletableFuture.completedFuture(incGen);
} else {
CompletableFuture<Long> badFuture = new CompletableFuture<>();
badFuture.completeExceptionally(new ReaderGroupConfigRejectedException("handle"));
return badFuture;
}
}).when(controller).updateReaderGroup(anyString(), anyString(), any(ReaderGroupConfig.class));
// run the first call async.
final ReaderGroupConfig newConf = config2;
CompletableFuture<Void> future = CompletableFuture.runAsync(() -> readerGroup.resetReaderGroup(newConf));
// Once the first call has reached the controller.updateReaderGroup step then signal so he waits.
signal.join();
// start the second call.
readerGroup.resetReaderGroup(config3);
// Once the second is completed stop the wait so the first call can go ahead.
wait.complete(null);
// wait for the first call to complete.
assertTrue(Futures.await(future));
// assert the generation was incremented twice due to two updates.
assertEquals(2L, atomicConfig.get().getGeneration());
assertEquals(2L, atomicConfigController.get().getGeneration());
// assert the first call happened last and the streams are s2.
assertTrue(atomicConfig.get().getStartingStreamCuts().keySet().stream().anyMatch(s -> s.getStreamName().equals("s2")));
assertTrue(atomicConfigController.get().getStartingStreamCuts().keySet().stream().anyMatch(s -> s.getStreamName().equals("s2")));
}
Aggregations