Transaction manager to not retry inner transactions (#1974)

This commit is contained in:
Pavlo Tkach 2023-04-05 16:46:36 -04:00 committed by GitHub
parent 33b43c05e7
commit 8d7088552f
2 changed files with 30 additions and 0 deletions

View file

@ -154,6 +154,10 @@ public class JpaTransactionManagerImpl implements JpaTransactionManager {
@Override
public <T> T transact(Supplier<T> work) {
// This prevents inner transaction from retrying, thus avoiding a cascade retry effect.
if (inTransaction()) {
return transactNoRetry(work);
}
return retrier.callWithRetry(() -> transactNoRetry(work), JpaRetries::isFailedTxnRetriable);
}

View file

@ -580,6 +580,32 @@ class JpaTransactionManagerImplTest {
.isFalse());
}
@Test
void innerTransactions_noRetry() {
JpaTransactionManager spyJpaTm = spy(tm());
doThrow(OptimisticLockException.class).when(spyJpaTm).delete(any(VKey.class));
spyJpaTm.transact(() -> spyJpaTm.insert(theEntity));
Supplier<Runnable> supplier =
() -> {
Runnable work = () -> spyJpaTm.delete(theEntityKey);
work.run();
return null;
};
assertThrows(
OptimisticLockException.class,
() ->
spyJpaTm.transact(
() -> {
spyJpaTm.exists(theEntity);
spyJpaTm.transact(supplier);
}));
verify(spyJpaTm, times(3)).exists(theEntity);
verify(spyJpaTm, times(3)).delete(theEntityKey);
}
private void insertPerson(int age) {
tm().getEntityManager()
.createNativeQuery(String.format("INSERT INTO Person (age) VALUES (%d)", age))