@Override public void close() { if ( !success ) { currentTransaction.failure(); } }
@Override public void failure() { transaction.failure(); }
@Override public void failure() { ktx.failure(); } }
@Override public void failure() { currentTransaction.failure(); }
@Override public void failTransaction() { statementContext.getKernelTransactionBoundToThisThread( true ).failure(); }
@Override public void failure() { internal.failure(); }
public void rollback() { try { KernelTransaction kernelTransactionBoundToThisThread = bridge.getKernelTransactionBoundToThisThread( false ); kernelTransactionBoundToThisThread.failure(); kernelTransactionBoundToThisThread.close(); } catch ( TransactionFailureException e ) { throw new RuntimeException( e ); } finally { bridge.unbindTransactionFromCurrentThread(); } }
@Test public void shouldRollbackParentByDefault() { // When placeboTx.close(); // Then verify( kernelTransaction ).failure(); }
void closeTransaction( MutableTransactionState ctx, boolean success ) throws TransactionFailureException { KernelTransaction tx = ctx.currentTransaction; ctx.currentTransaction = null; if ( tx != null ) { try { if ( success ) { tx.success(); } else { tx.failure(); } if ( tx.isOpen() ) { tx.close(); } } finally { ctx.currentTransaction = null; } } }
@Test public void shouldNotRollbackParentIfSuccessCalled() { // When placeboTx.success(); placeboTx.close(); // Then verify( kernelTransaction, never() ).failure(); }
@Test public void shouldRollbackParentIfFailureCalled() { // When placeboTx.failure(); placeboTx.close(); // Then verify( kernelTransaction, times(2) ).failure(); // We accept two calls to failure, since KernelTX#failure is idempotent }
@Test public void successCannotOverrideFailure() { // When placeboTx.failure(); placeboTx.success(); placeboTx.close(); // Then verify( kernelTransaction ).failure(); verify( kernelTransaction, never() ).success(); }
@Test public void shouldRollbackFailedTransaction() throws Exception { // GIVEN try ( KernelTransaction transaction = newTransaction( loginContext() ) ) { // WHEN transactionInitializer.accept( transaction ); transaction.failure(); } // THEN verify( transactionMonitor, times( 1 ) ).transactionFinished( false, isWriteTx ); verifyExtraInteractionWithTheMonitor( transactionMonitor, isWriteTx ); }
@Test void shouldDoNothingInAutoCommitTransactionUponInitialisationWhenValidated() throws Exception { KernelTransaction transaction = newTimedOutTransaction(); TransactionStateMachineV1SPI stateMachineSPI = newTransactionStateMachineSPI( transaction ); TransactionStateMachine stateMachine = newTransactionStateMachine( stateMachineSPI ); // We're in auto-commit state assertThat( stateMachine.state, is( TransactionStateMachine.State.AUTO_COMMIT ) ); assertNull( stateMachine.ctx.currentTransaction ); // call validate transaction stateMachine.validateTransaction(); assertThat( stateMachine.state, is( TransactionStateMachine.State.AUTO_COMMIT ) ); assertNull( stateMachine.ctx.currentTransaction ); verify( transaction, never() ).getReasonIfTerminated(); verify( transaction, never() ).failure(); verify( transaction, never() ).close(); }
@Test public void shouldNotDowngradeFailureState() throws Exception { try ( KernelTransaction transaction = newTransaction( loginContext() ) ) { // WHEN transactionInitializer.accept( transaction ); transaction.markForTermination( Status.General.UnknownError ); transaction.failure(); assertEquals( Status.General.UnknownError, transaction.getReasonIfTerminated().get() ); } // THEN verify( transactionMonitor, times( 1 ) ).transactionFinished( false, isWriteTx ); verify( transactionMonitor, times( 1 ) ).transactionTerminated( isWriteTx ); verifyExtraInteractionWithTheMonitor( transactionMonitor, isWriteTx ); }
@Test public void shouldRollbackAndThrowOnFailedAndSuccess() { // GIVEN boolean exceptionReceived = false; try ( KernelTransaction transaction = newTransaction( loginContext() ) ) { // WHEN transactionInitializer.accept( transaction ); transaction.failure(); transaction.success(); } catch ( TransactionFailureException e ) { // Expected. exceptionReceived = true; } // THEN assertTrue( exceptionReceived ); verify( transactionMonitor, times( 1 ) ).transactionFinished( false, isWriteTx ); verifyExtraInteractionWithTheMonitor( transactionMonitor, isWriteTx ); }
@Test void shouldResetInExplicitTransactionUponTxBeginWhenValidated() throws Exception { KernelTransaction transaction = newTimedOutTransaction(); TransactionStateMachineV1SPI stateMachineSPI = newTransactionStateMachineSPI( transaction ); TransactionStateMachine stateMachine = newTransactionStateMachine( stateMachineSPI ); // start an explicit transaction stateMachine.beginTransaction( null ); assertThat( stateMachine.state, is( TransactionStateMachine.State.EXPLICIT_TRANSACTION ) ); assertNotNull( stateMachine.ctx.currentTransaction ); // verify transaction, which is timed out stateMachine.validateTransaction(); assertThat( stateMachine.state, is( TransactionStateMachine.State.AUTO_COMMIT ) ); assertNull( stateMachine.ctx.currentTransaction ); assertNull( stateMachine.ctx.currentResult ); assertNull( stateMachine.ctx.currentResultHandle ); verify( transaction, times( 1 ) ).getReasonIfTerminated(); verify( transaction, times( 1 ) ).failure(); verify( transaction, times( 1 ) ).close(); }
@Test void shouldResetInAutoCommitTransactionWhileStatementIsRunningWhenValidated() throws Exception { KernelTransaction transaction = newTimedOutTransaction(); TransactionStateMachineV1SPI stateMachineSPI = newTransactionStateMachineSPI( transaction ); TransactionStateMachine stateMachine = newTransactionStateMachine( stateMachineSPI ); // We're in auto-commit state assertThat( stateMachine.state, is( TransactionStateMachine.State.AUTO_COMMIT ) ); assertNull( stateMachine.ctx.currentTransaction ); stateMachine.run( "RETURN 1", null ); // We're in auto-commit state assertThat( stateMachine.state, is( TransactionStateMachine.State.AUTO_COMMIT ) ); assertNotNull( stateMachine.ctx.currentTransaction ); // call validate transaction stateMachine.validateTransaction(); assertThat( stateMachine.state, is( TransactionStateMachine.State.AUTO_COMMIT ) ); assertNull( stateMachine.ctx.currentTransaction ); assertNull( stateMachine.ctx.currentResult ); assertNull( stateMachine.ctx.currentResultHandle ); verify( transaction, times( 1 ) ).getReasonIfTerminated(); verify( transaction, times( 1 ) ).failure(); verify( transaction, times( 1 ) ).close(); }
@Test void shouldResetInExplicitTransactionWhileStatementIsRunningWhenValidated() throws Exception { KernelTransaction transaction = newTimedOutTransaction(); TransactionStateMachineV1SPI stateMachineSPI = newTransactionStateMachineSPI( transaction ); TransactionStateMachine stateMachine = newTransactionStateMachine( stateMachineSPI ); // start an explicit transaction stateMachine.beginTransaction( null ); assertThat( stateMachine.state, is( TransactionStateMachine.State.EXPLICIT_TRANSACTION ) ); assertNotNull( stateMachine.ctx.currentTransaction ); stateMachine.run( "RETURN 1", null ); // verify transaction, which is timed out stateMachine.validateTransaction(); assertThat( stateMachine.state, is( TransactionStateMachine.State.AUTO_COMMIT ) ); assertNull( stateMachine.ctx.currentTransaction ); assertNull( stateMachine.ctx.currentResult ); assertNull( stateMachine.ctx.currentResultHandle ); verify( transaction, times( 1 ) ).getReasonIfTerminated(); verify( transaction, times( 1 ) ).failure(); verify( transaction, times( 1 ) ).close(); }
@Override public void failure() { ktx.failure(); } }