use of io.pravega.controller.store.stream.StreamMetadataStore in project pravega by pravega.
the class RequestHandlersTest method concurrentRollingTxnCommit.
private void concurrentRollingTxnCommit(String stream, String func, boolean expectFailureOnFirstJob, Predicate<Throwable> firstExceptionPredicate, Map<String, Integer> invocationCount, int expectedVersion) {
StreamMetadataStore streamStore1 = getStore();
StreamMetadataStore streamStore1Spied = spy(getStore());
StreamConfiguration config = StreamConfiguration.builder().scalingPolicy(ScalingPolicy.byEventRate(1, 2, 1)).build();
streamStore1.createStream(scope, stream, config, System.currentTimeMillis(), null, executor).join();
streamStore1.setState(scope, stream, State.ACTIVE, null, executor).join();
StreamMetadataStore streamStore2 = getStore();
CommitRequestHandler requestHandler1 = new CommitRequestHandler(streamStore1Spied, streamMetadataTasks, streamTransactionMetadataTasks, bucketStore, executor);
CommitRequestHandler requestHandler2 = new CommitRequestHandler(streamStore2, streamMetadataTasks, streamTransactionMetadataTasks, bucketStore, executor);
ScaleOperationTask scaleRequesthandler = new ScaleOperationTask(streamMetadataTasks, streamStore2, executor);
// create txn on epoch 0 and set it to committing
UUID txnId = streamStore1.generateTransactionId(scope, stream, null, executor).join();
VersionedTransactionData txnEpoch0 = streamStore1.createTransaction(scope, stream, txnId, 1000L, 10000L, null, executor).join();
streamStore1.sealTransaction(scope, stream, txnId, true, Optional.of(txnEpoch0.getVersion()), "", Long.MIN_VALUE, null, executor).join();
// perform scale
ScaleOpEvent event = new ScaleOpEvent(scope, stream, Lists.newArrayList(0L), Lists.newArrayList(new AbstractMap.SimpleEntry<>(0.0, 1.0)), false, System.currentTimeMillis(), System.currentTimeMillis());
scaleRequesthandler.execute(event).join();
// regular commit
// start commit transactions
CompletableFuture<Void> wait = new CompletableFuture<>();
CompletableFuture<Void> signal = new CompletableFuture<>();
// test rolling transaction --> since transaction on epoch 0 is committing, it will get committed first.
CommitEvent commitOnEpoch0 = new CommitEvent(scope, stream, 0);
setMockCommitTxnLatch(streamStore1, streamStore1Spied, func, signal, wait);
// start rolling txn
// stall rolling transaction in different stages
CompletableFuture<Void> future1Rolling = CompletableFuture.completedFuture(null).thenComposeAsync(v -> requestHandler1.execute(commitOnEpoch0), executor);
signal.join();
requestHandler2.execute(commitOnEpoch0).join();
wait.complete(null);
if (expectFailureOnFirstJob) {
AssertExtensions.assertSuppliedFutureThrows("first commit should fail", () -> future1Rolling, firstExceptionPredicate);
verify(streamStore1Spied, times(invocationCount.get("startCommitTransactions"))).startCommitTransactions(anyString(), anyString(), anyInt(), any(), any());
verify(streamStore1Spied, times(invocationCount.get("startRollingTxn"))).startRollingTxn(anyString(), anyString(), anyInt(), any(), any(), any());
verify(streamStore1Spied, times(invocationCount.get("rollingTxnCreateDuplicateEpochs"))).rollingTxnCreateDuplicateEpochs(anyString(), anyString(), any(), anyLong(), any(), any(), any());
verify(streamStore1Spied, times(invocationCount.get("completeRollingTxn"))).completeRollingTxn(anyString(), anyString(), any(), any(), any(), any());
verify(streamStore1Spied, times(invocationCount.get("completeCommitTransactions"))).completeCommitTransactions(anyString(), anyString(), any(), any(), any(), any());
verify(streamStore1Spied, times(invocationCount.get("updateVersionedState"))).updateVersionedState(anyString(), anyString(), any(), any(), any(), any());
} else {
future1Rolling.join();
}
// validate rolling txn done and first job has updated the CTR with new txn record
VersionedMetadata<CommittingTransactionsRecord> versioned = streamStore1.getVersionedCommittingTransactionsRecord(scope, stream, null, executor).join();
assertEquals(CommittingTransactionsRecord.EMPTY, versioned.getObject());
assertEquals(expectedVersion, getVersionNumber(versioned.getVersion()));
assertEquals(3, streamStore1.getActiveEpoch(scope, stream, null, true, executor).join().getEpoch());
assertEquals(State.ACTIVE, streamStore1.getState(scope, stream, true, null, executor).join());
}
use of io.pravega.controller.store.stream.StreamMetadataStore in project pravega by pravega.
the class RequestHandlersTest method concurrentUpdateStream.
// concurrent update stream
@SuppressWarnings("unchecked")
@Test(timeout = 300000)
public void concurrentUpdateStream() throws Exception {
String stream = "update";
StreamMetadataStore streamStore1 = getStore();
StreamMetadataStore streamStore1Spied = spy(getStore());
StreamConfiguration config = StreamConfiguration.builder().scalingPolicy(ScalingPolicy.byEventRate(1, 2, 1)).build();
streamStore1.createStream(scope, stream, config, System.currentTimeMillis(), null, executor).join();
streamStore1.setState(scope, stream, State.ACTIVE, null, executor).join();
StreamMetadataStore streamStore2 = getStore();
UpdateStreamTask requestHandler1 = new UpdateStreamTask(streamMetadataTasks, streamStore1Spied, bucketStore, executor);
UpdateStreamTask requestHandler2 = new UpdateStreamTask(streamMetadataTasks, streamStore2, bucketStore, executor);
CompletableFuture<Void> wait = new CompletableFuture<>();
CompletableFuture<Void> signal = new CompletableFuture<>();
streamStore1.startUpdateConfiguration(scope, stream, config, null, executor).join();
UpdateStreamEvent event = new UpdateStreamEvent(scope, stream, System.currentTimeMillis());
doAnswer(x -> {
signal.complete(null);
wait.join();
return streamStore1.completeUpdateConfiguration(x.getArgument(0), x.getArgument(1), x.getArgument(2), x.getArgument(3), x.getArgument(4));
}).when(streamStore1Spied).completeUpdateConfiguration(anyString(), anyString(), any(), any(), any());
CompletableFuture<Void> future1 = CompletableFuture.completedFuture(null).thenComposeAsync(v -> requestHandler1.execute(event), executor);
signal.join();
requestHandler2.execute(event).join();
wait.complete(null);
AssertExtensions.assertSuppliedFutureThrows("first update job should fail", () -> future1, e -> Exceptions.unwrap(e) instanceof StoreException.WriteConflictException);
// validate rolling txn done
VersionedMetadata<StreamConfigurationRecord> versioned = streamStore1.getConfigurationRecord(scope, stream, null, executor).join();
assertFalse(versioned.getObject().isUpdating());
assertEquals(2, getVersionNumber(versioned.getVersion()));
assertEquals(State.ACTIVE, streamStore1.getState(scope, stream, true, null, executor).join());
streamStore1.close();
streamStore2.close();
}
use of io.pravega.controller.store.stream.StreamMetadataStore in project pravega by pravega.
the class RequestHandlersTest method idempotentUpdatePartialScaleCompleted.
@Test(timeout = 300000)
public void idempotentUpdatePartialScaleCompleted() throws Exception {
String stream = "update2";
StreamMetadataStore streamStore1 = getStore();
StreamMetadataStore streamStore1Spied = spy(getStore());
StreamConfiguration config = StreamConfiguration.builder().scalingPolicy(ScalingPolicy.fixed(1)).build();
streamStore1.createStream(scope, stream, config, System.currentTimeMillis(), null, executor).join();
streamStore1.setState(scope, stream, State.ACTIVE, null, executor).join();
StreamMetadataStore streamStore2 = getStore();
UpdateStreamTask requestHandler1 = new UpdateStreamTask(streamMetadataTasks, streamStore1Spied, bucketStore, executor);
UpdateStreamTask requestHandler2 = new UpdateStreamTask(streamMetadataTasks, streamStore2, bucketStore, executor);
CompletableFuture<Void> wait = new CompletableFuture<>();
CompletableFuture<Void> signal = new CompletableFuture<>();
config = StreamConfiguration.builder().scalingPolicy(ScalingPolicy.fixed(2)).build();
streamStore1.startUpdateConfiguration(scope, stream, config, null, executor).join();
UpdateStreamEvent event = new UpdateStreamEvent(scope, stream, System.currentTimeMillis());
// make this wait at reset epoch transition. this has already changed the state to updating. both executions are
// performing the same update.
doAnswer(x -> {
signal.complete(null);
wait.join();
return streamStore1.scaleSegmentsSealed(x.getArgument(0), x.getArgument(1), x.getArgument(2), x.getArgument(3), x.getArgument(4), x.getArgument(5));
}).when(streamStore1Spied).scaleSegmentsSealed(anyString(), anyString(), any(), any(), any(), any());
CompletableFuture<Void> future1 = CompletableFuture.completedFuture(null).thenComposeAsync(v -> requestHandler1.execute(event), executor);
signal.join();
requestHandler2.execute(event).join();
wait.complete(null);
AssertExtensions.assertSuppliedFutureThrows("first update job should fail", () -> future1, e -> Exceptions.unwrap(e) instanceof StoreException.WriteConflictException);
VersionedMetadata<StreamConfigurationRecord> versioned = streamStore1.getConfigurationRecord(scope, stream, null, executor).join();
assertFalse(versioned.getObject().isUpdating());
assertEquals(2, getVersionNumber(versioned.getVersion()));
assertEquals(State.ACTIVE, streamStore1.getState(scope, stream, true, null, executor).join());
assertEquals(1, streamStore1.getActiveEpoch(scope, stream, null, true, executor).join().getEpoch());
// repeat the above experiment with complete scale step also having been performed.
streamStore1.close();
streamStore2.close();
}
use of io.pravega.controller.store.stream.StreamMetadataStore in project pravega by pravega.
the class RequestHandlersTest method updateSealedStream.
@SuppressWarnings("unchecked")
@Test(timeout = 300000)
public void updateSealedStream() throws Exception {
String stream = "updateSealed";
StreamMetadataStore streamStore = getStore();
StreamMetadataStore streamStoreSpied = spy(getStore());
StreamConfiguration config = StreamConfiguration.builder().scalingPolicy(ScalingPolicy.byEventRate(1, 2, 1)).build();
streamStore.createStream(scope, stream, config, System.currentTimeMillis(), null, executor).join();
streamStore.setState(scope, stream, State.ACTIVE, null, executor).join();
streamStore.setState(scope, stream, State.SEALED, null, executor).join();
UpdateStreamTask requestHandler = new UpdateStreamTask(streamMetadataTasks, streamStoreSpied, bucketStore, executor);
CompletableFuture<Void> wait = new CompletableFuture<>();
CompletableFuture<Void> signal = new CompletableFuture<>();
streamStore.startUpdateConfiguration(scope, stream, config, null, executor).join();
UpdateStreamEvent event = new UpdateStreamEvent(scope, stream, System.currentTimeMillis());
doAnswer(x -> {
signal.complete(null);
wait.join();
return streamStore.completeUpdateConfiguration(x.getArgument(0), x.getArgument(1), x.getArgument(2), x.getArgument(3), x.getArgument(4));
}).when(streamStoreSpied).completeUpdateConfiguration(anyString(), anyString(), any(), any(), any());
CompletableFuture<Void> future = CompletableFuture.completedFuture(null).thenComposeAsync(v -> requestHandler.execute(event), executor);
signal.join();
wait.complete(null);
AssertExtensions.assertSuppliedFutureThrows("Updating sealed stream job should fail", () -> future, e -> Exceptions.unwrap(e) instanceof UnsupportedOperationException);
// validate
VersionedMetadata<StreamConfigurationRecord> versioned = streamStore.getConfigurationRecord(scope, stream, null, executor).join();
assertFalse(versioned.getObject().isUpdating());
assertEquals(2, getVersionNumber(versioned.getVersion()));
assertEquals(State.SEALED, streamStore.getState(scope, stream, true, null, executor).join());
streamStore.close();
}
use of io.pravega.controller.store.stream.StreamMetadataStore in project pravega by pravega.
the class RequestHandlersTest method scopeDeleteTest.
@Test
public void scopeDeleteTest() {
final String testScope = "testScope";
final String testStream = "testStream";
final String testRG = "_RGTestRG";
final String testKVT = "testKVT";
StreamMetadataStore streamStoreSpied = spy(getStore());
KVTableMetadataStore kvtStoreSpied = spy(getKvtStore());
StreamMetadataTasks streamMetadataTasks1 = mock(StreamMetadataTasks.class);
TableMetadataTasks kvtTasksMocked = mock(TableMetadataTasks.class);
streamStoreSpied.createScope(testScope, null, executor).join();
OperationContext ctx = new OperationContext() {
@Override
public long getOperationStartTime() {
return 0;
}
@Override
public long getRequestId() {
return 0;
}
};
UUID scopeId = streamStoreSpied.getScopeId(testScope, ctx, executor).join();
doAnswer(x -> {
CompletableFuture<UUID> cf = new CompletableFuture<>();
cf.complete(scopeId);
return cf;
}).when(streamStoreSpied).getScopeId(eq(testScope), eq(ctx), eq(executor));
doAnswer(invocation -> {
CompletableFuture<Boolean> cf = new CompletableFuture<>();
cf.complete(true);
return cf;
}).when(streamStoreSpied).isScopeSealed(eq(testScope), any(), any());
createStreamInStore(testStream, testScope);
createStreamInStore(testRG, testScope);
assertTrue(streamStore.checkStreamExists(testScope, testStream, ctx, executor).join());
doAnswer(invocation -> {
CompletableFuture<Controller.UpdateStreamStatus.Status> future = new CompletableFuture<>();
future.complete(Controller.UpdateStreamStatus.Status.SUCCESS);
return future;
}).when(streamMetadataTasks1).sealStream(anyString(), anyString(), anyLong());
doAnswer(invocation -> {
CompletableFuture<Controller.DeleteStreamStatus.Status> future = new CompletableFuture<>();
future.complete(Controller.DeleteStreamStatus.Status.SUCCESS);
return future;
}).when(streamMetadataTasks1).deleteStream(anyString(), anyString(), anyLong());
// Create Reader Group
ReaderGroupConfig rgConfig = ReaderGroupConfig.builder().stream(NameUtils.getScopedStreamName(testScope, testStream)).build();
final ReaderGroupConfig config = ReaderGroupConfig.cloneConfig(rgConfig, UUID.randomUUID(), 123L);
Controller.ReaderGroupConfiguration expectedConfig = ModelHelper.decode(testScope, testRG, config);
doAnswer(invocationOnMock -> {
CompletableFuture<Controller.CreateReaderGroupResponse.Status> createRG = new CompletableFuture<>();
createRG.complete(Controller.CreateReaderGroupResponse.Status.SUCCESS);
return createRG;
}).when(streamMetadataTasks1).createReaderGroup(anyString(), any(), any(), anyLong(), anyLong());
doAnswer(invocation -> CompletableFuture.completedFuture(Controller.ReaderGroupConfigResponse.newBuilder().setStatus(Controller.ReaderGroupConfigResponse.Status.SUCCESS).setConfig(expectedConfig).build())).when(streamMetadataTasks1).getReaderGroupConfig(eq(testScope), anyString(), anyLong());
doAnswer(invocationOnMock -> {
CompletableFuture<Controller.DeleteReaderGroupStatus.Status> future = new CompletableFuture<>();
future.complete(Controller.DeleteReaderGroupStatus.Status.SUCCESS);
return future;
}).when(streamMetadataTasks1).deleteReaderGroup(anyString(), anyString(), anyString(), anyLong());
// Create KVT
KeyValueTableConfiguration kvtConfig = KeyValueTableConfiguration.builder().partitionCount(1).primaryKeyLength(1).secondaryKeyLength(1).build();
doAnswer(invocationOnMock -> {
CompletableFuture<Controller.CreateKeyValueTableStatus.Status> fut = new CompletableFuture<>();
fut.complete(Controller.CreateKeyValueTableStatus.Status.SUCCESS);
return fut;
}).when(kvtTasksMocked).createKeyValueTable(anyString(), anyString(), any(), anyLong(), anyLong());
List<String> tableList = new ArrayList<>();
tableList.add(testKVT);
Pair<List<String>, String> listOfKVTables = new ImmutablePair<>(tableList, "");
doAnswer(invocationOnMock -> CompletableFuture.completedFuture(listOfKVTables)).doAnswer(invocationOnMock -> CompletableFuture.completedFuture(new ImmutablePair<>(Collections.emptyList(), invocationOnMock.getArgument(0)))).when(kvtStoreSpied).listKeyValueTables(anyString(), any(), anyInt(), any(), any());
doAnswer(invocationOnMock -> {
CompletableFuture<Controller.DeleteKVTableStatus.Status> future = new CompletableFuture<>();
future.complete(Controller.DeleteKVTableStatus.Status.SUCCESS);
return future;
}).when(kvtTasksMocked).deleteKeyValueTable(anyString(), anyString(), anyLong());
Controller.CreateKeyValueTableStatus.Status status = kvtTasksMocked.createKeyValueTable(testScope, testKVT, kvtConfig, System.currentTimeMillis(), 123L).join();
assertEquals(status, Controller.CreateKeyValueTableStatus.Status.SUCCESS);
DeleteScopeTask requestHandler = new DeleteScopeTask(streamMetadataTasks1, streamStoreSpied, kvtStoreSpied, kvtTasksMocked, executor);
DeleteScopeEvent event = new DeleteScopeEvent(testScope, 123L, scopeId);
CompletableFuture<Void> future = requestHandler.execute(event);
future.join();
}
Aggregations