use of io.pravega.controller.store.kvtable.KVTableMetadataStore in project pravega by pravega.
the class ZKBackedControllerServiceStarterTest method testStallEventProcStartupWithSessionExpiration.
@Test(timeout = 30000L)
public void testStallEventProcStartupWithSessionExpiration() throws Exception {
// mock createStream call to throw an exception so that we can keep failing create stream and retrying indefinitely
// controller event processor will be stuck at this point.
// now expire the session. basically call notify on starter
CompletableFuture<Void> latch = new CompletableFuture<>();
CompletableFuture<Void> signal = new CompletableFuture<>();
@Cleanup StreamMetadataStore store = spy(getStore(storeClient));
KVTableMetadataStore kvtStore = spy(getKVTStore(storeClient));
doAnswer(x -> {
signal.complete(null);
latch.join();
throw new RuntimeException();
}).when(store).createScope(anyString(), any(), any());
ControllerServiceStarter starter = new ControllerServiceStarter(createControllerServiceConfigWithEventProcessors(), storeClient, SegmentHelperMock.getSegmentHelperMockForTables(executor), new MockConnectionFactory(), store, kvtStore);
starter.startAsync();
// this will block until createScope is called from event processors.
signal.join();
latch.complete(null);
starter.notifySessionExpiration();
AssertExtensions.assertThrows(IllegalStateException.class, starter::awaitRunning);
assertTrue(Exceptions.unwrap(starter.failureCause()) instanceof ZkSessionExpirationException);
assertEquals(starter.state(), Service.State.FAILED);
Callbacks.invokeSafely(starter::shutDown, null);
}
use of io.pravega.controller.store.kvtable.KVTableMetadataStore in project pravega by pravega.
the class ControllerEventProcessorsTest method testTruncate.
@Test(timeout = 10000L)
public void testTruncate() throws CheckpointStoreException, InterruptedException {
LocalController controller = mock(LocalController.class);
CheckpointStore checkpointStore = mock(CheckpointStore.class);
StreamMetadataStore streamStore = mock(StreamMetadataStore.class);
BucketStore bucketStore = mock(BucketStore.class);
ConnectionPool connectionPool = mock(ConnectionPool.class);
StreamMetadataTasks streamMetadataTasks = mock(StreamMetadataTasks.class);
StreamTransactionMetadataTasks streamTransactionMetadataTasks = mock(StreamTransactionMetadataTasks.class);
KVTableMetadataStore kvtStore = mock(KVTableMetadataStore.class);
TableMetadataTasks kvtTasks = mock(TableMetadataTasks.class);
ControllerEventProcessorConfig config = ControllerEventProcessorConfigImpl.withDefault();
EventProcessorSystem system = mock(EventProcessorSystem.class);
Map<SegmentWithRange, Long> map1 = new HashMap<>();
map1.put(new SegmentWithRange(new Segment("scope", "stream", 0L), 0.0, 0.33), 10L);
map1.put(new SegmentWithRange(new Segment("scope", "stream", 1L), 0.33, 0.66), 10L);
map1.put(new SegmentWithRange(new Segment("scope", "stream", 2L), 0.66, 1.0), 20L);
Map<SegmentWithRange, Long> map2 = new HashMap<>();
map2.put(new SegmentWithRange(new Segment("scope", "stream", 0L), 0.0, 0.33), 20L);
map2.put(new SegmentWithRange(new Segment("scope", "stream", 2L), 0.66, 1.0), 10L);
Map<SegmentWithRange, Long> map3 = new HashMap<>();
map3.put(new SegmentWithRange(new Segment("scope", "stream", 3L), 0.0, 0.33), 0L);
map3.put(new SegmentWithRange(new Segment("scope", "stream", 4L), 0.33, 0.66), 10L);
map3.put(new SegmentWithRange(new Segment("scope", "stream", 5L), 0.66, 1.0), 20L);
PositionImpl position1 = new PositionImpl(map1);
PositionImpl position2 = new PositionImpl(map2);
PositionImpl position3 = new PositionImpl(map3);
doReturn(getProcessor()).when(system).createEventProcessorGroup(any(), any(), any());
doReturn(CompletableFuture.completedFuture(null)).when(controller).createScope(anyString());
doReturn(CompletableFuture.completedFuture(null)).when(controller).createInternalStream(anyString(), anyString(), any());
doNothing().when(streamMetadataTasks).initializeStreamWriters(any(), anyString());
doNothing().when(streamTransactionMetadataTasks).initializeStreamWriters(any(EventStreamClientFactory.class), any(ControllerEventProcessorConfig.class));
AtomicBoolean requestCalled = new AtomicBoolean(false);
AtomicBoolean commitCalled = new AtomicBoolean(false);
CompletableFuture<Void> requestStreamTruncationFuture = new CompletableFuture<>();
CompletableFuture<Void> kvtStreamTruncationFuture = new CompletableFuture<>();
CompletableFuture<Void> abortStreamTruncationFuture = new CompletableFuture<>();
CompletableFuture<Void> commitStreamTruncationFuture = new CompletableFuture<>();
doAnswer(x -> {
String argument = x.getArgument(1);
if (argument.equals(config.getRequestStreamName())) {
// let one of the processors throw the exception. this should still be retried in the next cycle.
if (!requestCalled.get()) {
requestCalled.set(true);
throw new RuntimeException("inducing sporadic failure");
} else {
requestStreamTruncationFuture.complete(null);
}
} else if (argument.equals(config.getCommitStreamName())) {
// let one of the processors throw the exception. this should still be retried in the next cycle.
if (commitCalled.get()) {
commitStreamTruncationFuture.complete(null);
} else {
commitCalled.set(true);
return CompletableFuture.completedFuture(false);
}
} else if (argument.equals(config.getAbortStreamName())) {
abortStreamTruncationFuture.complete(null);
} else if (argument.equals(config.getKvtStreamName())) {
kvtStreamTruncationFuture.complete(null);
}
return CompletableFuture.completedFuture(true);
}).when(streamMetadataTasks).startTruncation(anyString(), anyString(), any(), any());
Set<String> processes = Sets.newHashSet("p1", "p2", "p3");
// first throw checkpoint store exception
AtomicBoolean signal = new AtomicBoolean(false);
CountDownLatch cd = new CountDownLatch(4);
doAnswer(x -> {
// this ensures that the call to truncate has been invoked for all 4 internal streams.
cd.countDown();
cd.await();
if (!signal.get()) {
throw new CheckpointStoreException("CheckpointStoreException");
} else {
return processes;
}
}).when(checkpointStore).getProcesses();
Map<String, PositionImpl> r1 = Collections.singletonMap("r1", position1);
doReturn(r1).when(checkpointStore).getPositions(eq("p1"), anyString());
Map<String, PositionImpl> r2 = Collections.singletonMap("r2", position1);
doReturn(r2).when(checkpointStore).getPositions(eq("p2"), anyString());
Map<String, PositionImpl> r3 = Collections.singletonMap("r3", position1);
doReturn(r3).when(checkpointStore).getPositions(eq("p3"), anyString());
@Cleanup ControllerEventProcessors processors = new ControllerEventProcessors("host1", config, controller, checkpointStore, streamStore, bucketStore, connectionPool, streamMetadataTasks, streamTransactionMetadataTasks, kvtStore, kvtTasks, system, executorService());
// set truncation interval
processors.setTruncationInterval(100L);
processors.startAsync();
processors.awaitRunning();
ControllerEventProcessors processorsSpied = spy(processors);
processorsSpied.bootstrap(streamTransactionMetadataTasks, streamMetadataTasks, kvtTasks);
// wait for all 4 countdown exceptions to have been thrown.
cd.await();
verify(processorsSpied, atLeast(4)).truncate(any(), any(), any());
verify(checkpointStore, atLeast(4)).getProcesses();
verify(checkpointStore, never()).getPositions(anyString(), anyString());
verify(streamMetadataTasks, never()).startTruncation(anyString(), anyString(), any(), any());
signal.set(true);
CompletableFuture.allOf(requestStreamTruncationFuture, commitStreamTruncationFuture, abortStreamTruncationFuture, kvtStreamTruncationFuture).join();
// verify that truncate method is being called periodically.
verify(processorsSpied, atLeastOnce()).truncate(config.getRequestStreamName(), config.getRequestReaderGroupName(), streamMetadataTasks);
verify(processorsSpied, atLeastOnce()).truncate(config.getCommitStreamName(), config.getCommitReaderGroupName(), streamMetadataTasks);
verify(processorsSpied, atLeastOnce()).truncate(config.getAbortStreamName(), config.getAbortReaderGroupName(), streamMetadataTasks);
verify(processorsSpied, atLeastOnce()).truncate(config.getKvtStreamName(), config.getKvtReaderGroupName(), streamMetadataTasks);
for (int i = 1; i <= 3; i++) {
verify(checkpointStore, atLeastOnce()).getPositions("p" + i, config.getRequestReaderGroupName());
verify(checkpointStore, atLeastOnce()).getPositions("p" + i, config.getCommitReaderGroupName());
verify(checkpointStore, atLeastOnce()).getPositions("p" + i, config.getAbortReaderGroupName());
verify(checkpointStore, atLeastOnce()).getPositions("p" + i, config.getKvtReaderGroupName());
}
}
use of io.pravega.controller.store.kvtable.KVTableMetadataStore in project pravega by pravega.
the class RequestHandlersTest method testDeleteScopeRecursive.
@Test
public void testDeleteScopeRecursive() {
StreamMetadataStore streamStoreSpied = spy(getStore());
KVTableMetadataStore kvtStoreSpied = spy(getKvtStore());
OperationContext ctx = new OperationContext() {
@Override
public long getOperationStartTime() {
return 0;
}
@Override
public long getRequestId() {
return 0;
}
};
UUID scopeId = streamStoreSpied.getScopeId(scope, ctx, executor).join();
doAnswer(x -> {
CompletableFuture<UUID> cf = new CompletableFuture<>();
cf.complete(scopeId);
return cf;
}).when(streamStoreSpied).getScopeId(eq(scope), eq(ctx), eq(executor));
doAnswer(invocation -> {
CompletableFuture<Boolean> cf = new CompletableFuture<>();
cf.complete(false);
return cf;
}).when(streamStoreSpied).isScopeSealed(eq(scope), any(), any());
DeleteScopeTask requestHandler = new DeleteScopeTask(streamMetadataTasks, streamStoreSpied, kvtStoreSpied, kvtTasks, executor);
DeleteScopeEvent event = new DeleteScopeEvent(scope, System.currentTimeMillis(), scopeId);
CompletableFuture<Void> future = CompletableFuture.completedFuture(null).thenComposeAsync(v -> requestHandler.execute(event), executor);
future.join();
}
use of io.pravega.controller.store.kvtable.KVTableMetadataStore in project pravega by pravega.
the class ControllerEventProcessorsTest method testBootstrap.
@Test(timeout = 30000L)
public void testBootstrap() throws Exception {
LocalController controller = mock(LocalController.class);
CheckpointStore checkpointStore = mock(CheckpointStore.class);
StreamMetadataStore streamStore = mock(StreamMetadataStore.class);
BucketStore bucketStore = mock(BucketStore.class);
ConnectionPool connectionPool = mock(ConnectionPool.class);
StreamMetadataTasks streamMetadataTasks = mock(StreamMetadataTasks.class);
StreamTransactionMetadataTasks streamTransactionMetadataTasks = mock(StreamTransactionMetadataTasks.class);
KVTableMetadataStore kvtStore = mock(KVTableMetadataStore.class);
TableMetadataTasks kvtTasks = mock(TableMetadataTasks.class);
ControllerEventProcessorConfig config = ControllerEventProcessorConfigImpl.withDefault();
EventProcessorSystem system = mock(EventProcessorSystem.class);
doAnswer(x -> null).when(streamMetadataTasks).initializeStreamWriters(any(), any());
doAnswer(x -> null).when(streamTransactionMetadataTasks).initializeStreamWriters(any(EventStreamClientFactory.class), any(ControllerEventProcessorConfig.class));
LinkedBlockingQueue<CompletableFuture<Boolean>> createScopeResponses = new LinkedBlockingQueue<>();
LinkedBlockingQueue<CompletableFuture<Void>> createScopeSignals = new LinkedBlockingQueue<>();
List<CompletableFuture<Boolean>> createScopeResponsesList = new LinkedList<>();
List<CompletableFuture<Void>> createScopeSignalsList = new LinkedList<>();
for (int i = 0; i < 2; i++) {
CompletableFuture<Boolean> responseFuture = new CompletableFuture<>();
CompletableFuture<Void> signalFuture = new CompletableFuture<>();
createScopeResponsesList.add(responseFuture);
createScopeResponses.add(responseFuture);
createScopeSignalsList.add(signalFuture);
createScopeSignals.add(signalFuture);
}
// return a future from latches queue
doAnswer(x -> {
createScopeSignals.take().complete(null);
return createScopeResponses.take();
}).when(controller).createScope(anyString());
LinkedBlockingQueue<CompletableFuture<Boolean>> createStreamResponses = new LinkedBlockingQueue<>();
LinkedBlockingQueue<CompletableFuture<Void>> createStreamSignals = new LinkedBlockingQueue<>();
List<CompletableFuture<Boolean>> createStreamResponsesList = new LinkedList<>();
List<CompletableFuture<Void>> createStreamSignalsList = new LinkedList<>();
for (int i = 0; i < 8; i++) {
CompletableFuture<Boolean> responseFuture = new CompletableFuture<>();
CompletableFuture<Void> signalFuture = new CompletableFuture<>();
createStreamResponsesList.add(responseFuture);
createStreamResponses.add(responseFuture);
createStreamSignalsList.add(signalFuture);
createStreamSignals.add(signalFuture);
}
// return a future from latches queue
doAnswer(x -> {
createStreamSignals.take().complete(null);
return createStreamResponses.take();
}).when(controller).createInternalStream(anyString(), anyString(), any());
@Cleanup ControllerEventProcessors processors = new ControllerEventProcessors("host1", config, controller, checkpointStore, streamStore, bucketStore, connectionPool, streamMetadataTasks, streamTransactionMetadataTasks, kvtStore, kvtTasks, system, executorService());
// call bootstrap on ControllerEventProcessors
processors.bootstrap(streamTransactionMetadataTasks, streamMetadataTasks, kvtTasks);
// wait on create scope being called.
createScopeSignalsList.get(0).join();
verify(controller, times(1)).createScope(any());
// complete scopeFuture1 exceptionally. this should result in a retry.
createScopeResponsesList.get(0).completeExceptionally(new RuntimeException());
// wait on second scope signal being called
createScopeSignalsList.get(1).join();
verify(controller, times(2)).createScope(any());
// so far no create stream should have been invoked
verify(controller, times(0)).createInternalStream(anyString(), anyString(), any());
// complete scopeFuture2 successfully
createScopeResponsesList.get(1).complete(true);
// create streams should be called now
// since we call four create streams. We will wait on first three signal futures
createStreamSignalsList.get(0).join();
createStreamSignalsList.get(1).join();
createStreamSignalsList.get(2).join();
createStreamSignalsList.get(3).join();
verify(controller, times(4)).createInternalStream(anyString(), anyString(), any());
// fail first four requests
createStreamResponsesList.get(0).completeExceptionally(new RuntimeException());
createStreamResponsesList.get(1).completeExceptionally(new RuntimeException());
createStreamResponsesList.get(2).completeExceptionally(new RuntimeException());
createStreamResponsesList.get(3).completeExceptionally(new RuntimeException());
// this should result in a retry for four create streams. wait on next four signals
createStreamSignalsList.get(4).join();
createStreamSignalsList.get(5).join();
createStreamSignalsList.get(6).join();
createStreamSignalsList.get(7).join();
verify(controller, times(8)).createInternalStream(anyString(), anyString(), any());
// complete successfully
createStreamResponsesList.get(4).complete(true);
createStreamResponsesList.get(5).complete(true);
createStreamResponsesList.get(6).complete(true);
createStreamResponsesList.get(7).complete(true);
AssertExtensions.assertEventuallyEquals(true, () -> processors.getBootstrapCompleted().get(), 10000);
}
use of io.pravega.controller.store.kvtable.KVTableMetadataStore in project pravega by pravega.
the class ControllerEventProcessorsTest method testIsReady.
@Test(timeout = 30000L)
public void testIsReady() throws Exception {
LocalController controller = mock(LocalController.class);
StreamMetadataStore streamStore = mock(StreamMetadataStore.class);
BucketStore bucketStore = mock(BucketStore.class);
ConnectionPool connectionPool = mock(ConnectionPool.class);
StreamMetadataTasks streamMetadataTasks = mock(StreamMetadataTasks.class);
StreamTransactionMetadataTasks streamTransactionMetadataTasks = mock(StreamTransactionMetadataTasks.class);
KVTableMetadataStore kvtStore = mock(KVTableMetadataStore.class);
TableMetadataTasks kvtTasks = mock(TableMetadataTasks.class);
ControllerEventProcessorConfig config = ControllerEventProcessorConfigImpl.withDefault();
EventProcessorSystem system = mock(EventProcessorSystem.class);
CuratorZookeeperClient curatorZKClientMock = mock(CuratorZookeeperClient.class);
CuratorFramework client = mock(CuratorFramework.class);
Listenable listen = mock(Listenable.class);
doNothing().when(listen).addListener(any(ConnectionStateListener.class));
doReturn(listen).when(client).getConnectionStateListenable();
doReturn(curatorZKClientMock).when(client).getZookeeperClient();
doReturn(true).when(curatorZKClientMock).isConnected();
ZKCheckpointStore checkpointStore = (ZKCheckpointStore) CheckpointStoreFactory.createZKStore(client);
doAnswer(x -> null).when(streamMetadataTasks).initializeStreamWriters(any(), any());
doAnswer(x -> null).when(streamTransactionMetadataTasks).initializeStreamWriters(any(EventStreamClientFactory.class), any(ControllerEventProcessorConfig.class));
CompletableFuture<Boolean> createScopeResponseFuture = new CompletableFuture<>();
CompletableFuture<Void> createScopeSignalFuture = new CompletableFuture<>();
doAnswer(x -> {
createScopeSignalFuture.complete(null);
return createScopeResponseFuture;
}).when(controller).createScope(anyString());
LinkedBlockingQueue<CompletableFuture<Boolean>> createStreamResponses = new LinkedBlockingQueue<>();
LinkedBlockingQueue<CompletableFuture<Void>> createStreamSignals = new LinkedBlockingQueue<>();
List<CompletableFuture<Boolean>> createStreamResponsesList = new LinkedList<>();
List<CompletableFuture<Void>> createStreamSignalsList = new LinkedList<>();
for (int i = 0; i < 4; i++) {
CompletableFuture<Boolean> responseFuture = new CompletableFuture<>();
CompletableFuture<Void> signalFuture = new CompletableFuture<>();
createStreamResponsesList.add(responseFuture);
createStreamResponses.add(responseFuture);
createStreamSignalsList.add(signalFuture);
createStreamSignals.add(signalFuture);
}
// return a future from latches queue
doAnswer(x -> {
createStreamSignals.take().complete(null);
return createStreamResponses.take();
}).when(controller).createInternalStream(anyString(), anyString(), any());
@Cleanup ControllerEventProcessors processors = spy(new ControllerEventProcessors("host1", config, controller, checkpointStore, streamStore, bucketStore, connectionPool, streamMetadataTasks, streamTransactionMetadataTasks, kvtStore, kvtTasks, system, executorService()));
// Check isReady() method before invoking bootstrap
Assert.assertFalse(processors.getBootstrapCompleted().get());
Assert.assertTrue(processors.isMetadataServiceConnected());
Assert.assertFalse(processors.isRunning());
Assert.assertFalse(processors.isReady());
// Call bootstrap on ControllerEventProcessors
processors.bootstrap(streamTransactionMetadataTasks, streamMetadataTasks, kvtTasks);
// Wait on create scope being called.
createScopeSignalFuture.join();
createScopeResponseFuture.complete(true);
createStreamSignalsList.get(0).join();
createStreamSignalsList.get(1).join();
createStreamSignalsList.get(2).join();
createStreamSignalsList.get(3).join();
createStreamResponsesList.get(0).complete(true);
createStreamResponsesList.get(1).complete(true);
createStreamResponsesList.get(2).complete(true);
createStreamResponsesList.get(3).complete(true);
AssertExtensions.assertEventuallyEquals(true, () -> processors.getBootstrapCompleted().get(), 10000);
Assert.assertTrue(processors.isMetadataServiceConnected());
Assert.assertFalse(processors.isRunning());
Assert.assertFalse(processors.isReady());
EventProcessorGroup mockEventProcessorGroup = mock(EventProcessorGroup.class);
doNothing().when(mockEventProcessorGroup).awaitRunning();
doReturn(mockEventProcessorGroup).when(system).createEventProcessorGroup(any(EventProcessorConfig.class), any(CheckpointStore.class), any(ScheduledExecutorService.class));
processors.startAsync();
processors.awaitRunning();
Assert.assertTrue(processors.isMetadataServiceConnected());
Assert.assertTrue(processors.isBootstrapCompleted());
Assert.assertTrue(processors.isRunning());
Assert.assertTrue(processors.isReady());
}
Aggregations