use of io.pravega.controller.stream.api.grpc.v1.Controller.TxnId in project pravega by pravega.
the class TimeoutServiceTest method testControllerPingSuccess.
@Test(timeout = 10000)
public void testControllerPingSuccess() throws InterruptedException {
TxnId txnId = controllerService.createTransaction(SCOPE, STREAM, LEASE, SCALE_GRACE_PERIOD).thenApply(x -> ModelHelper.decode(x.getKey())).join();
Optional<Throwable> result = timeoutService.getTaskCompletionQueue().poll((long) (0.75 * LEASE), TimeUnit.MILLISECONDS);
Assert.assertNull(result);
TxnState txnState = controllerService.checkTransactionStatus(SCOPE, STREAM, txnId).join();
Assert.assertEquals(TxnState.State.OPEN, txnState.getState());
PingTxnStatus pingStatus = controllerService.pingTransaction(SCOPE, STREAM, txnId, LEASE).join();
Assert.assertEquals(PingTxnStatus.Status.OK, pingStatus.getStatus());
result = timeoutService.getTaskCompletionQueue().poll((long) (0.5 * LEASE), TimeUnit.MILLISECONDS);
Assert.assertNull(result);
txnState = controllerService.checkTransactionStatus(SCOPE, STREAM, txnId).join();
Assert.assertEquals(TxnState.State.OPEN, txnState.getState());
result = timeoutService.getTaskCompletionQueue().poll((long) (0.8 * LEASE), TimeUnit.MILLISECONDS);
Assert.assertNotNull(result);
txnState = controllerService.checkTransactionStatus(SCOPE, STREAM, txnId).join();
Assert.assertEquals(TxnState.State.ABORTING, txnState.getState());
}
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 {
TxnId txnId = controllerService.createTransaction(SCOPE, STREAM, LEASE, SCALE_GRACE_PERIOD).thenApply(x -> ModelHelper.decode(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).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).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).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 TimeoutServiceTest method testUnknownTxnPingSuccess.
@Test(timeout = 10000)
public void testUnknownTxnPingSuccess() throws InterruptedException {
UUID txnId = UUID.randomUUID();
VersionedTransactionData txData = streamStore.createTransaction(SCOPE, STREAM, txnId, LEASE, 10 * LEASE, SCALE_GRACE_PERIOD, null, executor).join();
TxnId tx = TxnId.newBuilder().setHighBits(txnId.getMostSignificantBits()).setLowBits(txnId.getLeastSignificantBits()).build();
controllerService.pingTransaction(SCOPE, STREAM, tx, LEASE);
TxnStatus status = streamStore.transactionStatus(SCOPE, STREAM, txData.getId(), null, executor).join();
Assert.assertEquals(TxnStatus.OPEN, status);
}
use of io.pravega.controller.stream.api.grpc.v1.Controller.TxnId in project pravega by pravega.
the class TimeoutServiceTest method testTimeout.
@Test(timeout = 10000)
public void testTimeout() throws InterruptedException {
UUID txnId = UUID.randomUUID();
VersionedTransactionData txData = streamStore.createTransaction(SCOPE, STREAM, txnId, LEASE, 10 * LEASE, SCALE_GRACE_PERIOD, null, executor).join();
long begin = System.currentTimeMillis();
timeoutService.addTxn(SCOPE, STREAM, txData.getId(), txData.getVersion(), LEASE, txData.getMaxExecutionExpiryTime(), txData.getScaleGracePeriod());
Optional<Throwable> result = timeoutService.getTaskCompletionQueue().poll((long) (1.3 * LEASE), TimeUnit.MILLISECONDS);
long end = System.currentTimeMillis();
Assert.assertNotNull(result);
log.info("Delay until timeout = " + (end - begin));
Assert.assertTrue((end - begin) >= LEASE);
TxnStatus status = streamStore.transactionStatus(SCOPE, STREAM, txData.getId(), null, executor).join();
Assert.assertEquals(TxnStatus.ABORTING, status);
}
use of io.pravega.controller.stream.api.grpc.v1.Controller.TxnId in project pravega by pravega.
the class StreamTransactionMetadataTasks method sealTxnBody.
/**
* Seals a txn and transitions it to COMMITTING (resp. ABORTING) state if commit param is true (resp. false).
*
* Post-condition:
* 1. If seal completes successfully, then
* (a) txn state is COMMITTING/ABORTING,
* (b) CommitEvent/AbortEvent is present in the commit stream/abort stream,
* (c) txn is removed from host-txn index,
* (d) txn is removed from the timeout service.
*
* 2. If process fails after transitioning txn to COMMITTING/ABORTING state, but before responding to client, then
* since txn is present in the host-txn index, some other controller process shall put CommitEvent/AbortEvent to
* commit stream/abort stream.
*
* @param host host id. It is different from hostId iff invoked from TxnSweeper for aborting orphaned txn.
* @param scope scope name.
* @param stream stream name.
* @param commit boolean indicating whether to commit txn.
* @param txnId txn id.
* @param version expected version of txn node in store.
* @param ctx context.
* @return Txn status after sealing it.
*/
CompletableFuture<TxnStatus> sealTxnBody(final String host, final String scope, final String stream, final boolean commit, final UUID txnId, final Integer version, final OperationContext ctx) {
TxnResource resource = new TxnResource(scope, stream, txnId);
Optional<Integer> versionOpt = Optional.ofNullable(version);
// Step 1. Add txn to current host's index, if it is not already present
CompletableFuture<Void> addIndex = host.equals(hostId) && !timeoutService.containsTxn(scope, stream, txnId) ? // then txn would no longer be open.
streamMetadataStore.addTxnToIndex(hostId, resource, Integer.MAX_VALUE) : CompletableFuture.completedFuture(null);
addIndex.whenComplete((v, e) -> {
if (e != null) {
log.debug("Txn={}, already present/newly added to host-txn index of host={}", txnId, hostId);
} else {
log.debug("Txn={}, added txn to host-txn index of host={}", txnId, hostId);
}
});
// Step 2. Seal txn
CompletableFuture<AbstractMap.SimpleEntry<TxnStatus, Integer>> sealFuture = addIndex.thenComposeAsync(x -> streamMetadataStore.sealTransaction(scope, stream, txnId, commit, versionOpt, ctx, executor), executor).whenComplete((v, e) -> {
if (e != null) {
log.debug("Txn={}, failed sealing txn", txnId);
} else {
log.debug("Txn={}, sealed successfully, commit={}", txnId, commit);
}
});
// Step 3. write event to corresponding stream.
return sealFuture.thenComposeAsync(pair -> {
TxnStatus status = pair.getKey();
switch(status) {
case COMMITTING:
return writeCommitEvent(scope, stream, pair.getValue(), txnId, status);
case ABORTING:
return writeAbortEvent(scope, stream, pair.getValue(), txnId, status);
case ABORTED:
case COMMITTED:
return CompletableFuture.completedFuture(status);
case OPEN:
case UNKNOWN:
default:
// exception would be thrown.
return CompletableFuture.completedFuture(status);
}
}, executor).thenComposeAsync(status -> {
// Step 4. Remove txn from timeoutService, and from the index.
timeoutService.removeTxn(scope, stream, txnId);
log.debug("Txn={}, removed from timeout service", txnId);
return streamMetadataStore.removeTxnFromIndex(host, resource, true).whenComplete((v, e) -> {
if (e != null) {
log.debug("Txn={}, failed removing txn from host-txn index of host={}", txnId, hostId);
} else {
log.debug("Txn={}, removed txn from host-txn index of host={}", txnId, hostId);
}
}).thenApply(x -> status);
}, executor);
}
Aggregations