use of org.apache.tephra.TransactionFailureException in project cdap by caskdata.
the class AbstractTransactionContext method checkpoint.
@Override
public void checkpoint() throws TransactionFailureException {
Preconditions.checkState(currentTx != null, "Cannot checkpoint tx that has not been started");
persist();
try {
currentTx = txClient.checkpoint(currentTx);
// update the current transaction with all TransactionAwares
for (TransactionAware txAware : getTransactionAwares()) {
txAware.updateTx(currentTx);
}
} catch (TransactionFailureException e) {
abort(e);
} catch (Throwable e) {
abort(new TransactionFailureException(String.format("Exception from checkpoint for transaction %d.", currentTx.getTransactionId()), e));
}
}
use of org.apache.tephra.TransactionFailureException in project cdap by caskdata.
the class QueueTest method testRollback.
@Test(timeout = TIMEOUT_MS)
public void testRollback() throws Exception {
QueueName queueName = QueueName.fromFlowlet(NamespaceId.DEFAULT.getEntityName(), "app", "flow", "flowlet", "queuerollback");
ConsumerConfig consumerConfig = new ConsumerConfig(0, 0, 1, DequeueStrategy.FIFO, null);
configureGroups(queueName, ImmutableList.of(consumerConfig));
try (QueueProducer producer = queueClientFactory.createProducer(queueName);
QueueConsumer consumer = queueClientFactory.createConsumer(queueName, consumerConfig, 1)) {
TransactionContext txContext = createTxContext(producer, consumer, new TransactionAware() {
boolean canCommit = false;
@Override
public void startTx(Transaction tx) {
}
@Override
public void updateTx(Transaction tx) {
}
@Override
public Collection<byte[]> getTxChanges() {
return ImmutableList.of();
}
@Override
public boolean commitTx() throws Exception {
// Flip-flop between commit success/failure.
boolean res = canCommit;
canCommit = !canCommit;
return res;
}
@Override
public void postTxCommit() {
}
@Override
public boolean rollbackTx() throws Exception {
return true;
}
@Override
public String getTransactionAwareName() {
return "test";
}
});
// First, try to enqueue and commit would fail
txContext.start();
try {
producer.enqueue(new QueueEntry(Bytes.toBytes(1)));
txContext.finish();
// If reaches here, it's wrong, as exception should be thrown.
Assert.assertTrue(false);
} catch (TransactionFailureException e) {
txContext.abort();
}
// Try to enqueue again. Within the same transaction, dequeue should be empty.
txContext.start();
producer.enqueue(new QueueEntry(Bytes.toBytes(1)));
Assert.assertTrue(consumer.dequeue().isEmpty());
txContext.finish();
// This time, enqueue has been committed, dequeue would see the item
txContext.start();
try {
Assert.assertEquals(1, Bytes.toInt(consumer.dequeue().iterator().next()));
txContext.finish();
// If reaches here, it's wrong, as exception should be thrown.
Assert.assertTrue(false);
} catch (TransactionFailureException e) {
txContext.abort();
}
// Dequeue again, since last tx was rollback, this dequeue should see the item again.
txContext.start();
Assert.assertEquals(1, Bytes.toInt(consumer.dequeue().iterator().next()));
txContext.finish();
}
}
use of org.apache.tephra.TransactionFailureException in project cdap by caskdata.
the class ObjectStoreDatasetTest method testInstantiateWrongClass.
@Test
public void testInstantiateWrongClass() throws Exception {
DatasetId pairs = DatasetFrameworkTestUtil.NAMESPACE_ID.dataset("pairs");
createObjectStoreInstance(pairs, new TypeToken<ImmutablePair<Integer, String>>() {
}.getType());
// note: due to type erasure, this succeeds
final ObjectStoreDataset<Custom> store = dsFrameworkUtil.getInstance(pairs);
TransactionExecutor storeTxnl = dsFrameworkUtil.newTransactionExecutor(store);
// but now it must fail with incompatible type
try {
storeTxnl.execute(new TransactionExecutor.Subroutine() {
@Override
public void apply() throws Exception {
Custom custom = new Custom(42, Lists.newArrayList("one", "two"));
store.write(a, custom);
}
});
Assert.fail("write should have failed with incompatible type");
} catch (TransactionFailureException e) {
// expected
}
// write a correct object to the pair store
final ObjectStoreDataset<ImmutablePair<Integer, String>> pairStore = dsFrameworkUtil.getInstance(pairs);
TransactionExecutor pairStoreTxnl = dsFrameworkUtil.newTransactionExecutor(pairStore);
final ImmutablePair<Integer, String> pair = new ImmutablePair<>(1, "second");
pairStoreTxnl.execute(new TransactionExecutor.Subroutine() {
@Override
public void apply() throws Exception {
// should succeed
pairStore.write(a, pair);
}
});
pairStoreTxnl.execute(new TransactionExecutor.Subroutine() {
@Override
public void apply() throws Exception {
ImmutablePair<Integer, String> actualPair = pairStore.read(a);
Assert.assertEquals(pair, actualPair);
}
});
// now try to read that as a custom object, should fail with class cast
try {
storeTxnl.execute(new TransactionExecutor.Subroutine() {
@Override
public void apply() throws Exception {
Custom custom = store.read(a);
Preconditions.checkNotNull(custom);
}
});
Assert.fail("write should have failed with class cast exception");
} catch (TransactionFailureException e) {
// expected
}
pairStoreTxnl.execute(new TransactionExecutor.Subroutine() {
@Override
public void apply() throws Exception {
deleteAndVerify(pairStore, a);
}
});
dsFrameworkUtil.deleteInstance(pairs);
}
use of org.apache.tephra.TransactionFailureException in project cdap by caskdata.
the class TransactionContextTest method testPersistFailure.
@Test
public void testPersistFailure() throws TransactionFailureException, InterruptedException {
ds1.failCommitTxOnce = InduceFailure.ThrowException;
TransactionContext context = newTransactionContext(ds1, ds2);
// start transaction
context.start();
// add a change to ds1 and ds2
ds1.addChange(A);
ds2.addChange(B);
// commit transaction should fail and cause rollback
try {
context.finish();
Assert.fail("Persist should have failed - exception should be thrown");
} catch (TransactionFailureException e) {
Assert.assertEquals("persist failure", e.getCause().getMessage());
}
// verify both are rolled back and tx is aborted
Assert.assertTrue(ds1.started);
Assert.assertTrue(ds2.started);
Assert.assertTrue(ds1.checked);
Assert.assertTrue(ds2.checked);
Assert.assertTrue(ds1.committed);
Assert.assertFalse(ds2.committed);
Assert.assertFalse(ds1.postCommitted);
Assert.assertFalse(ds2.postCommitted);
Assert.assertTrue(ds1.rolledBack);
Assert.assertTrue(ds2.rolledBack);
Assert.assertEquals(txClient.state, DummyTxClient.CommitState.Aborted);
}
use of org.apache.tephra.TransactionFailureException in project cdap by caskdata.
the class TransactionContextTest method testPersistFalse.
@Test
public void testPersistFalse() throws TransactionFailureException, InterruptedException {
ds1.failCommitTxOnce = InduceFailure.ReturnFalse;
TransactionContext context = newTransactionContext(ds1, ds2);
// start transaction
context.start();
// add a change to ds1 and ds2
ds1.addChange(A);
ds2.addChange(B);
// commit transaction should fail and cause rollback
try {
context.finish();
Assert.fail("Persist should have failed - exception should be thrown");
} catch (TransactionFailureException e) {
// in this case, the ds simply returned false
Assert.assertNull(e.getCause());
}
// verify both are rolled back and tx is aborted
Assert.assertTrue(ds1.started);
Assert.assertTrue(ds2.started);
Assert.assertTrue(ds1.checked);
Assert.assertTrue(ds2.checked);
Assert.assertTrue(ds1.committed);
Assert.assertFalse(ds2.committed);
Assert.assertFalse(ds1.postCommitted);
Assert.assertFalse(ds2.postCommitted);
Assert.assertTrue(ds1.rolledBack);
Assert.assertTrue(ds2.rolledBack);
Assert.assertEquals(txClient.state, DummyTxClient.CommitState.Aborted);
}
Aggregations