use of io.pravega.controller.stream.api.grpc.v1.Controller.TxnId in project pravega by pravega.
the class TimeoutServiceTest method testControllerPingFailureDisconnected.
@Test(timeout = 10000)
public void testControllerPingFailureDisconnected() throws InterruptedException {
UUID txnId = controllerService.createTransaction(SCOPE, STREAM, LEASE, 0L).thenApply(x -> x.getKey()).join();
Optional<Throwable> result = timeoutService.getTaskCompletionQueue().poll((long) (0.75 * LEASE), TimeUnit.MILLISECONDS);
Assert.assertNull(result);
TxnState status = controllerService.checkTransactionStatus(SCOPE, STREAM, txnId, 0L).join();
Assert.assertEquals(TxnState.State.OPEN, status.getState());
// Stop timeoutService, and then try pinging the transaction.
timeoutService.stopAsync();
PingTxnStatus pingStatus = controllerService.pingTransaction(SCOPE, STREAM, txnId, LEASE, 0L).join();
Assert.assertEquals(PingTxnStatus.Status.DISCONNECTED, pingStatus.getStatus());
result = timeoutService.getTaskCompletionQueue().poll((long) (0.5 * LEASE), TimeUnit.MILLISECONDS);
Assert.assertNull(result);
// Check that the transaction status is still open, since timeoutService has been stopped.
status = controllerService.checkTransactionStatus(SCOPE, STREAM, txnId, 0L).join();
Assert.assertEquals(TxnState.State.OPEN, status.getState());
}
use of io.pravega.controller.stream.api.grpc.v1.Controller.TxnId in project pravega by pravega.
the class StreamMetadataStoreTest method scaleWithTxTest.
@Test(timeout = 30000)
public void scaleWithTxTest() throws Exception {
final String scope = "ScopeScaleWithTx";
final String stream = "StreamScaleWithTx";
final ScalingPolicy policy = ScalingPolicy.fixed(2);
final StreamConfiguration configuration = StreamConfiguration.builder().scalingPolicy(policy).build();
long start = System.currentTimeMillis();
store.createScope(scope, null, executor).get();
store.createStream(scope, stream, configuration, start, null, executor).get();
store.setState(scope, stream, State.ACTIVE, null, executor).get();
long scaleTs = System.currentTimeMillis();
SimpleEntry<Double, Double> segment2 = new SimpleEntry<>(0.5, 0.75);
SimpleEntry<Double, Double> segment3 = new SimpleEntry<>(0.75, 1.0);
List<Long> scale1SealedSegments = Collections.singletonList(1L);
// region Txn created before scale and during scale
// scale with transaction test
// first txn created before-scale
UUID txnId = store.generateTransactionId(scope, stream, null, executor).join();
VersionedTransactionData tx01 = store.createTransaction(scope, stream, txnId, 100, 100, null, executor).get();
assertEquals(0, tx01.getEpoch());
VersionedMetadata<EpochTransitionRecord> versioned = store.submitScale(scope, stream, scale1SealedSegments, Arrays.asList(segment2, segment3), scaleTs, null, null, executor).join();
EpochTransitionRecord response = versioned.getObject();
Map<Long, Map.Entry<Double, Double>> scale1SegmentsCreated = response.getNewSegmentsWithRange();
final int epoch = response.getActiveEpoch();
assertEquals(0, epoch);
assertNotNull(scale1SegmentsCreated);
VersionedMetadata<State> state = store.getVersionedState(scope, stream, null, executor).join();
state = store.updateVersionedState(scope, stream, State.SCALING, state, null, executor).join();
versioned = store.startScale(scope, stream, false, versioned, state, null, executor).join();
// second txn created after new segments are created in segment table but not yet in history table
// assert that txn is created on old epoch
store.scaleCreateNewEpochs(scope, stream, versioned, null, executor).join();
txnId = store.generateTransactionId(scope, stream, null, executor).join();
VersionedTransactionData tx02 = store.createTransaction(scope, stream, txnId, 100, 100, null, executor).get();
assertEquals(0, tx02.getEpoch());
assertEquals(0, (int) (tx02.getId().getMostSignificantBits() >> 32));
// third transaction created after new epoch created
txnId = store.generateTransactionId(scope, stream, null, executor).join();
store.sealTransaction(scope, stream, tx02.getId(), true, Optional.of(tx02.getVersion()), "", Long.MIN_VALUE, null, executor).get();
store.sealTransaction(scope, stream, tx01.getId(), true, Optional.of(tx01.getVersion()), "", Long.MIN_VALUE, null, executor).get();
store.scaleSegmentsSealed(scope, stream, scale1SealedSegments.stream().collect(Collectors.toMap(x -> x, x -> 0L)), versioned, null, executor).join();
store.completeScale(scope, stream, versioned, null, executor).join();
VersionedTransactionData tx03 = store.createTransaction(scope, stream, txnId, 100, 100, null, executor).get();
assertEquals(0, tx03.getEpoch());
assertEquals(0, (int) (tx03.getId().getMostSignificantBits() >> 32));
store.setState(scope, stream, State.ACTIVE, null, executor).join();
// ensure that we can commit transactions on old epoch and roll over.
EpochRecord activeEpoch = store.getActiveEpoch(scope, stream, null, true, executor).join();
// submit another scale request without starting the scale
List<Long> scale2SealedSegments = Collections.singletonList(0L);
long scaleTs2 = System.currentTimeMillis();
SimpleEntry<Double, Double> segment4 = new SimpleEntry<>(0.0, 0.25);
SimpleEntry<Double, Double> segment5 = new SimpleEntry<>(0.25, 0.5);
VersionedMetadata<EpochTransitionRecord> versioned2 = store.submitScale(scope, stream, scale2SealedSegments, Arrays.asList(segment4, segment5), scaleTs2, null, null, executor).join();
EpochTransitionRecord response2 = versioned2.getObject();
assertEquals(activeEpoch.getEpoch(), response2.getActiveEpoch());
VersionedMetadata<CommittingTransactionsRecord> record = store.startCommitTransactions(scope, stream, 100, null, executor).join().getKey();
store.setState(scope, stream, State.COMMITTING_TXN, null, executor).join();
record = store.startRollingTxn(scope, stream, activeEpoch.getEpoch(), record, null, executor).join();
store.rollingTxnCreateDuplicateEpochs(scope, stream, Collections.emptyMap(), System.currentTimeMillis(), record, null, executor).join();
store.completeRollingTxn(scope, stream, Collections.emptyMap(), record, null, executor).join();
store.completeCommitTransactions(scope, stream, record, null, executor, Collections.emptyMap()).join();
store.setState(scope, stream, State.ACTIVE, null, executor).join();
activeEpoch = store.getActiveEpoch(scope, stream, null, true, executor).join();
assertEquals(3, activeEpoch.getEpoch());
assertEquals(1, activeEpoch.getReferenceEpoch());
assertEquals(3, activeEpoch.getSegments().size());
List<StreamSegmentRecord> txnDuplicate = store.getSegmentsInEpoch(scope, stream, 2, null, executor).join();
assertEquals(2, txnDuplicate.size());
List<StreamSegmentRecord> activeEpochDuplicate = store.getSegmentsInEpoch(scope, stream, 3, null, executor).join();
assertEquals(3, activeEpochDuplicate.size());
EpochRecord txnCommittedEpoch = store.getEpoch(scope, stream, 2, null, executor).join();
assertEquals(0, txnCommittedEpoch.getReferenceEpoch());
assertEquals(store.transactionStatus(scope, stream, tx01.getId(), null, executor).join(), TxnStatus.COMMITTED);
assertEquals(store.transactionStatus(scope, stream, tx02.getId(), null, executor).join(), TxnStatus.COMMITTED);
assertEquals(store.transactionStatus(scope, stream, tx03.getId(), null, executor).join(), TxnStatus.OPEN);
store.sealTransaction(scope, stream, tx03.getId(), true, Optional.of(tx03.getVersion()), "", Long.MIN_VALUE, null, executor).get();
// endregion
// region verify migrate request for manual scale
// now start manual scale against previously submitted scale request that was on old epoch from before rolling txn.
// verify that it gets migrated to latest duplicate epoch
state = store.getVersionedState(scope, stream, null, executor).join();
state = store.updateVersionedState(scope, stream, State.SCALING, state, null, executor).join();
versioned2 = store.submitScale(scope, stream, scale2SealedSegments, Arrays.asList(segment4, segment5), scaleTs2, null, null, executor).join();
versioned2 = store.startScale(scope, stream, true, versioned2, state, null, executor).join();
store.scaleCreateNewEpochs(scope, stream, versioned2, null, executor).join();
txnId = store.generateTransactionId(scope, stream, null, executor).join();
VersionedTransactionData tx14 = store.createTransaction(scope, stream, txnId, 100, 100, null, executor).get();
assertEquals(1, tx14.getEpoch());
store.sealTransaction(scope, stream, tx14.getId(), true, Optional.of(tx14.getVersion()), "", Long.MIN_VALUE, null, executor).get();
// verify that new txns can be created and are created on original epoch
txnId = store.generateTransactionId(scope, stream, null, executor).join();
VersionedTransactionData tx15 = store.createTransaction(scope, stream, txnId, 100, 100, null, executor).get();
assertEquals(1, tx15.getEpoch());
store.scaleCreateNewEpochs(scope, stream, versioned2, null, executor).join();
store.scaleSegmentsSealed(scope, stream, Collections.emptyMap(), versioned2, null, executor).join();
store.completeScale(scope, stream, versioned2, null, executor).join();
store.setState(scope, stream, State.ACTIVE, null, executor).get();
activeEpoch = store.getActiveEpoch(scope, stream, null, true, executor).join();
assertEquals(4, activeEpoch.getEpoch());
assertEquals(4, activeEpoch.getReferenceEpoch());
store.sealTransaction(scope, stream, tx15.getId(), true, Optional.of(tx15.getVersion()), "", Long.MIN_VALUE, null, executor).get();
record = store.startCommitTransactions(scope, stream, 100, null, executor).join().getKey();
store.setState(scope, stream, State.COMMITTING_TXN, null, executor).get();
record = store.startRollingTxn(scope, stream, activeEpoch.getEpoch(), record, null, executor).join();
store.rollingTxnCreateDuplicateEpochs(scope, stream, Collections.emptyMap(), System.currentTimeMillis(), record, null, executor).join();
store.completeRollingTxn(scope, stream, Collections.emptyMap(), record, null, executor).join();
store.completeCommitTransactions(scope, stream, record, null, executor, Collections.emptyMap()).join();
store.setState(scope, stream, State.ACTIVE, null, executor).join();
activeEpoch = store.getActiveEpoch(scope, stream, null, true, executor).join();
assertEquals(6, activeEpoch.getEpoch());
assertEquals(4, activeEpoch.getReferenceEpoch());
// endregion
}
use of io.pravega.controller.stream.api.grpc.v1.Controller.TxnId in project pravega by pravega.
the class StreamMetadataStoreTest method scaleWithTxnForInconsistentScanerios.
@Test(timeout = 30000)
public void scaleWithTxnForInconsistentScanerios() throws Exception {
final String scope = "ScopeScaleWithTx";
final String stream = "StreamScaleWithTx1";
final ScalingPolicy policy = ScalingPolicy.fixed(2);
final StreamConfiguration configuration = StreamConfiguration.builder().scalingPolicy(policy).build();
long start = System.currentTimeMillis();
store.createScope(scope, null, executor).get();
store.createStream(scope, stream, configuration, start, null, executor).get();
store.setState(scope, stream, State.ACTIVE, null, executor).get();
UUID txnId = store.generateTransactionId(scope, stream, null, executor).join();
VersionedTransactionData tx1 = store.createTransaction(scope, stream, txnId, 100, 100, null, executor).get();
store.sealTransaction(scope, stream, txnId, true, Optional.of(tx1.getVersion()), "", Long.MIN_VALUE, null, executor).get();
long scaleTs = System.currentTimeMillis();
List<Long> scale1SealedSegments = Collections.singletonList(0L);
// run a scale on segment 1
VersionedMetadata<EpochTransitionRecord> versioned = store.submitScale(scope, stream, scale1SealedSegments, Arrays.asList(new AbstractMap.SimpleEntry<>(0.0, 0.25), new AbstractMap.SimpleEntry<>(0.25, 0.5)), scaleTs, null, null, executor).join();
EpochTransitionRecord response = versioned.getObject();
assertEquals(0, response.getActiveEpoch());
VersionedMetadata<State> state = store.getVersionedState(scope, stream, null, executor).join();
state = store.updateVersionedState(scope, stream, State.SCALING, state, null, executor).join();
store.startScale(scope, stream, false, versioned, state, null, executor).join();
store.scaleCreateNewEpochs(scope, stream, versioned, null, executor).join();
store.scaleSegmentsSealed(scope, stream, scale1SealedSegments.stream().collect(Collectors.toMap(x -> x, x -> 0L)), versioned, null, executor).join();
store.completeScale(scope, stream, versioned, null, executor).join();
store.setState(scope, stream, State.ACTIVE, null, executor).join();
// start second scale
versioned = store.submitScale(scope, stream, Collections.singletonList(1L), Arrays.asList(new AbstractMap.SimpleEntry<>(0.5, 0.75), new AbstractMap.SimpleEntry<>(0.75, 1.0)), scaleTs, null, null, executor).join();
response = versioned.getObject();
assertEquals(1, response.getActiveEpoch());
EpochRecord activeEpoch = store.getActiveEpoch(scope, stream, null, true, executor).join();
VersionedMetadata<CommittingTransactionsRecord> record = store.startCommitTransactions(scope, stream, 100, null, executor).join().getKey();
store.setState(scope, stream, State.COMMITTING_TXN, null, executor).join();
record = store.startRollingTxn(scope, stream, activeEpoch.getEpoch(), record, null, executor).join();
store.rollingTxnCreateDuplicateEpochs(scope, stream, Collections.emptyMap(), System.currentTimeMillis(), record, null, executor).join();
store.completeRollingTxn(scope, stream, Collections.emptyMap(), record, null, executor).join();
store.completeCommitTransactions(scope, stream, record, null, executor, Collections.emptyMap()).join();
store.setState(scope, stream, State.ACTIVE, null, executor).join();
state = store.getVersionedState(scope, stream, null, executor).join();
state = store.updateVersionedState(scope, stream, State.SCALING, state, null, executor).join();
versioned = store.submitScale(scope, stream, Collections.singletonList(1L), Arrays.asList(new AbstractMap.SimpleEntry<>(0.5, 0.75), new AbstractMap.SimpleEntry<>(0.75, 1.0)), scaleTs, null, null, executor).join();
response = versioned.getObject();
assertEquals(1, response.getActiveEpoch());
AssertExtensions.assertFutureThrows("attempting to create new segments against inconsistent epoch transition record", store.startScale(scope, stream, false, versioned, state, null, executor), e -> Exceptions.unwrap(e) instanceof IllegalStateException);
// verify that state is reset to active
State stateVal = store.getState(scope, stream, true, null, executor).join();
assertEquals(State.ACTIVE, stateVal);
}
use of io.pravega.controller.stream.api.grpc.v1.Controller.TxnId in project pravega by pravega.
the class ControllerServiceTest method testTransactions.
@Test(timeout = 10000L)
public void testTransactions() {
TransactionMetrics.initialize();
UUID txnId = consumer.createTransaction(SCOPE, stream1, 10000L, 0L).join().getKey();
doThrow(StoreException.create(StoreException.Type.WRITE_CONFLICT, "Write conflict")).when(streamStore).sealTransaction(eq(SCOPE), eq(stream1), eq(txnId), anyBoolean(), any(), anyString(), anyLong(), any(), any());
AssertExtensions.assertFutureThrows("Write conflict should have been thrown", consumer.commitTransaction(SCOPE, stream1, txnId, "", 0L, 0L), e -> Exceptions.unwrap(e) instanceof StoreException.WriteConflictException);
AssertExtensions.assertFutureThrows("Write conflict should have been thrown", consumer.abortTransaction(SCOPE, stream1, txnId, 0L), e -> Exceptions.unwrap(e) instanceof StoreException.WriteConflictException);
doThrow(StoreException.create(StoreException.Type.CONNECTION_ERROR, "Connection failed")).when(streamStore).sealTransaction(eq(SCOPE), eq(stream1), eq(txnId), anyBoolean(), any(), anyString(), anyLong(), any(), any());
AssertExtensions.assertFutureThrows("Store connection exception should have been thrown", consumer.commitTransaction(SCOPE, stream1, txnId, "", 0L, 0L), e -> Exceptions.unwrap(e) instanceof StoreException.StoreConnectionException);
AssertExtensions.assertFutureThrows("Store connection exception should have been thrown", consumer.abortTransaction(SCOPE, stream1, txnId, 0L), e -> Exceptions.unwrap(e) instanceof StoreException.StoreConnectionException);
doThrow(StoreException.create(StoreException.Type.UNKNOWN, "Connection failed")).when(streamStore).sealTransaction(eq(SCOPE), eq(stream1), eq(txnId), anyBoolean(), any(), anyString(), anyLong(), any(), any());
AssertExtensions.assertFutureThrows("Unknown exception should have been thrown", consumer.commitTransaction(SCOPE, stream1, txnId, "", 0L, 0L), e -> Exceptions.unwrap(e) instanceof StoreException.UnknownException);
AssertExtensions.assertFutureThrows("Unknown exception should have been thrown", consumer.abortTransaction(SCOPE, stream1, txnId, 0L), e -> Exceptions.unwrap(e) instanceof StoreException.UnknownException);
doThrow(StoreException.create(StoreException.Type.DATA_NOT_FOUND, "Data Not Found")).when(streamStore).sealTransaction(eq(SCOPE), eq(stream1), eq(txnId), anyBoolean(), any(), anyString(), anyLong(), any(), any());
Controller.TxnStatus status = consumer.commitTransaction(SCOPE, stream1, txnId, "", 0L, 0L).join();
assertEquals(status.getStatus(), Controller.TxnStatus.Status.FAILURE);
status = consumer.abortTransaction(SCOPE, stream1, txnId, 0L).join();
assertEquals(status.getStatus(), Controller.TxnStatus.Status.FAILURE);
doThrow(StoreException.create(StoreException.Type.ILLEGAL_STATE, "Data Not Found")).when(streamStore).sealTransaction(eq(SCOPE), eq(stream1), eq(txnId), anyBoolean(), any(), anyString(), anyLong(), any(), any());
status = consumer.commitTransaction(SCOPE, stream1, txnId, "", 0L, 0L).join();
assertEquals(status.getStatus(), Controller.TxnStatus.Status.FAILURE);
status = consumer.abortTransaction(SCOPE, stream1, txnId, 0L).join();
assertEquals(status.getStatus(), Controller.TxnStatus.Status.FAILURE);
reset(streamStore);
}
Aggregations