9494import java .util .Map ;
9595import java .util .concurrent .CountDownLatch ;
9696import java .util .concurrent .TimeUnit ;
97+ import java .util .concurrent .atomic .AtomicBoolean ;
9798import java .util .concurrent .atomic .AtomicInteger ;
9899
99100import static org .hamcrest .CoreMatchers .containsString ;
@@ -1269,28 +1270,27 @@ public boolean isCloudNativeTableOrMaterializedView() {
12691270 }
12701271 };
12711272
1272- class InspectPersistedBatch extends TransactionStateBatch {
1273- private boolean persistedWhenAfterVisible = false ;
1274-
1275- InspectPersistedBatch (List <TransactionState > transactionStates ) {
1276- super (transactionStates );
1277- }
1278-
1273+ // With COW, the original stateBatch is copied internally, so we verify via callbacks
1274+ // that the transaction is persisted before afterVisible is called.
1275+ AtomicBoolean persistedWhenAfterVisible = new AtomicBoolean (false );
1276+ long checkCallbackId = 99999L ;
1277+ states .get (0 ).addCallbackId (checkCallbackId );
1278+ masterTransMgr .getCallbackFactory ().addCallback (new AbstractTxnStateChangeCallback () {
12791279 @ Override
1280- public void afterVisible (TransactionStatus transactionStatus , boolean txnOperated ) {
1281- long txnId = getTransactionStates ().get (0 ).getTransactionId ();
1282- persistedWhenAfterVisible = fakeEditLog .getTransaction (txnId ) != null ;
1283- super .afterVisible (transactionStatus , txnOperated );
1280+ public long getId () {
1281+ return checkCallbackId ;
12841282 }
12851283
1286- boolean isPersistedWhenAfterVisible () {
1287- return persistedWhenAfterVisible ;
1284+ @ Override
1285+ public void afterVisible (TransactionState txnState ) {
1286+ persistedWhenAfterVisible .set (
1287+ fakeEditLog .getTransaction (txnState .getTransactionId ()) != null );
12881288 }
1289- }
1289+ });
12901290
1291- InspectPersistedBatch stateBatch = new InspectPersistedBatch (states );
1291+ TransactionStateBatch stateBatch = new TransactionStateBatch (states );
12921292 masterTransMgr .finishTransactionBatch (GlobalStateMgrTestUtil .testDbId1 , stateBatch , null );
1293- assertTrue (stateBatch . isPersistedWhenAfterVisible ());
1293+ assertTrue (persistedWhenAfterVisible . get ());
12941294 }
12951295
12961296 @ Test
@@ -1306,21 +1306,25 @@ public boolean isCloudNativeTableOrMaterializedView() {
13061306 }
13071307 };
13081308
1309- class ThrowingBatch extends TransactionStateBatch {
1310- ThrowingBatch (List <TransactionState > transactionStates ) {
1311- super (transactionStates );
1309+ // Register a throwing callback to verify exception is swallowed
1310+ long throwCallbackId = 99998L ;
1311+ states .get (0 ).addCallbackId (throwCallbackId );
1312+ masterTransMgr .getCallbackFactory ().addCallback (new AbstractTxnStateChangeCallback () {
1313+ @ Override
1314+ public long getId () {
1315+ return throwCallbackId ;
13121316 }
13131317
13141318 @ Override
1315- public void afterVisible (TransactionStatus transactionStatus , boolean txnOperated ) {
1319+ public void afterVisible (TransactionState txnState ) {
13161320 throw new RuntimeException ("mock afterVisible failure" );
13171321 }
1318- }
1322+ });
13191323
1320- TransactionStateBatch stateBatch = new ThrowingBatch (states );
1321- Assertions .assertDoesNotThrow (
1324+ TransactionStateBatch stateBatch = new TransactionStateBatch (states );
1325+ TransactionStateBatch result = Assertions .assertDoesNotThrow (
13221326 () -> masterTransMgr .finishTransactionBatch (GlobalStateMgrTestUtil .testDbId1 , stateBatch , null ));
1323- for (TransactionState state : states ) {
1327+ for (TransactionState state : result . getTransactionStates () ) {
13241328 assertEquals (TransactionStatus .VISIBLE , state .getTransactionStatus ());
13251329 assertNotNull (fakeEditLog .getTransaction (state .getTransactionId ()));
13261330 }
@@ -1350,11 +1354,11 @@ public boolean isCloudNativeTableOrMaterializedView() {
13501354 };
13511355
13521356 TransactionStateBatch stateBatch = new TransactionStateBatch (states );
1353- Assertions .assertDoesNotThrow (
1357+ TransactionStateBatch result = Assertions .assertDoesNotThrow (
13541358 () -> masterTransMgr .finishTransactionBatch (GlobalStateMgrTestUtil .testDbId1 , stateBatch , null ));
13551359
13561360 assertEquals (2 , callbackInvokeCount .get ());
1357- for (TransactionState state : states ) {
1361+ for (TransactionState state : result . getTransactionStates () ) {
13581362 assertEquals (TransactionStatus .VISIBLE , state .getTransactionStatus ());
13591363 }
13601364 }
0 commit comments