package jnpf.flowable.service; import com.baomidou.dynamic.datasource.tx.*; import org.junit.After; import org.junit.Test; import java.util.concurrent.atomic.AtomicInteger; import static org.junit.Assert.*; /** Uses the installed dynamic-datasource transaction executor, not a simulated callback loader. */ public class DmsLifecycleEngineCompensationTest { @After public void cleanup() {TransactionContext.remove();TransactionContext.removeSynchronizations();} private void transaction(Runnable work) throws Throwable { var info=new TransactionalInfo();info.setPropagation(DsPropagation.REQUIRED); info.setRollbackFor(new Class[]{Exception.class});info.setNoRollbackFor(new Class[]{}); new TransactionalTemplate().execute(new TransactionalExecutor() { public Object execute() {work.run();return null;} public TransactionalInfo getTransactionInfo() {return info;} }); } @Test public void successfulCommitRetainsEngineInstance() throws Throwable { var deleted=new AtomicInteger(); transaction(()->DmsLifecycleEngineCompensation.register("engine",deleted::incrementAndGet)); assertEquals(0,deleted.get());assertTrue(TransactionContext.getSynchronizations().isEmpty()); } @Test public void laterFailureRollsBackEveryPreviouslyStartedDmsInstance() throws Throwable { var deleted=new AtomicInteger(); try { transaction(()->{ DmsLifecycleEngineCompensation.register("first",deleted::incrementAndGet); DmsLifecycleEngineCompensation.register("second",deleted::incrementAndGet); throw new IllegalStateException("later native save failed"); });fail(); } catch(IllegalStateException expected) { } assertEquals(2,deleted.get());assertTrue(TransactionContext.getSynchronizations().isEmpty()); } @Test public void immediateCompensationDoesNotDeleteTwiceOnRollback() throws Throwable { var deleted=new AtomicInteger(); try { transaction(()->{ var ticket=DmsLifecycleEngineCompensation.register("engine",deleted::incrementAndGet); var failure=new IllegalStateException("configuration read failed"); ticket.compensate(failure);throw failure; });fail(); } catch(IllegalStateException expected) { } assertEquals(1,deleted.get()); } @Test public void failedImmediateDeletionRetriesAtOuterRollback() throws Throwable { var attempts=new AtomicInteger();var failure=new IllegalArgumentException("native failure"); try { transaction(()->{ var ticket=DmsLifecycleEngineCompensation.register("engine",()->{ if(attempts.incrementAndGet()==1) throw new IllegalStateException("temporary engine failure"); });ticket.compensate(failure);throw failure; });fail(); } catch(IllegalArgumentException expected) {assertSame(failure,expected);} assertEquals(2,attempts.get());assertEquals(1,failure.getSuppressed().length); } }