Rollback reactive transaction on cancel
This commit introduces a change in reactive transaction semantics for cancel signals. Canceling a subscription now rolls back a reactive transaction to achieve a deterministic transaction outcome. Previously, cancel signals committed a transaction which could cause partially committed transactions depending on when the cancel happened.
This commit is contained in:
committed by
Juergen Hoeller
parent
8853f4b883
commit
217b6e37a6
@@ -878,7 +878,7 @@ public abstract class TransactionAspectSupport implements BeanFactoryAware, Init
|
||||
},
|
||||
this::commitTransactionAfterReturning,
|
||||
(txInfo, err) -> Mono.empty(),
|
||||
this::commitTransactionAfterReturning)
|
||||
this::rollbackTransactionOnCancel)
|
||||
.onErrorResume(ex ->
|
||||
completeTransactionAfterThrowing(it, ex).then(Mono.error(ex)));
|
||||
}
|
||||
@@ -908,7 +908,7 @@ public abstract class TransactionAspectSupport implements BeanFactoryAware, Init
|
||||
},
|
||||
this::commitTransactionAfterReturning,
|
||||
(txInfo, ex) -> Mono.empty(),
|
||||
this::commitTransactionAfterReturning)
|
||||
this::rollbackTransactionOnCancel)
|
||||
.onErrorResume(ex ->
|
||||
completeTransactionAfterThrowing(it, ex).then(Mono.error(ex)));
|
||||
}
|
||||
@@ -975,6 +975,16 @@ public abstract class TransactionAspectSupport implements BeanFactoryAware, Init
|
||||
return Mono.empty();
|
||||
}
|
||||
|
||||
private Mono<Void> rollbackTransactionOnCancel(@Nullable ReactiveTransactionInfo txInfo) {
|
||||
if (txInfo != null && txInfo.getReactiveTransaction() != null) {
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace("Rolling back transaction for [" + txInfo.getJoinpointIdentification() + "] after cancellation");
|
||||
}
|
||||
return txInfo.getTransactionManager().rollback(txInfo.getReactiveTransaction());
|
||||
}
|
||||
return Mono.empty();
|
||||
}
|
||||
|
||||
private Mono<Void> completeTransactionAfterThrowing(@Nullable ReactiveTransactionInfo txInfo, Throwable ex) {
|
||||
if (txInfo != null && txInfo.getReactiveTransaction() != null) {
|
||||
if (logger.isTraceEnabled()) {
|
||||
|
||||
@@ -79,7 +79,7 @@ final class TransactionalOperatorImpl implements TransactionalOperator {
|
||||
// Need re-wrapping of ReactiveTransaction until we get hold of the exception
|
||||
// through usingWhen.
|
||||
return status.flatMap(it -> Mono.usingWhen(Mono.just(it), ignore -> mono,
|
||||
this.transactionManager::commit, (res, err) -> Mono.empty(), this.transactionManager::commit)
|
||||
this.transactionManager::commit, (res, err) -> Mono.empty(), this.transactionManager::rollback)
|
||||
.onErrorResume(ex -> rollbackOnException(it, ex).then(Mono.error(ex))));
|
||||
})
|
||||
.subscriberContext(TransactionContextManager.getOrCreateContext())
|
||||
@@ -100,7 +100,7 @@ final class TransactionalOperatorImpl implements TransactionalOperator {
|
||||
action::doInTransaction,
|
||||
this.transactionManager::commit,
|
||||
(tx, ex) -> Mono.empty(),
|
||||
this.transactionManager::commit)
|
||||
this.transactionManager::rollback)
|
||||
.onErrorResume(ex ->
|
||||
rollbackOnException(it, ex).then(Mono.error(ex))));
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user