This is an automated email from the ASF dual-hosted git repository.

funky-eyes pushed a commit to branch 2.x
in repository https://gitbox.apache.org/repos/asf/incubator-seata.git


The following commit(s) were added to refs/heads/2.x by this push:
     new e01f97c6db bugfix: prevent async commit cleanup race (#8201)
e01f97c6db is described below

commit e01f97c6db397165050caa6764020410c2c8199a
Author: Zhengcy05 <[email protected]>
AuthorDate: Fri Aug 14 09:47:52 2026 +0800

    bugfix: prevent async commit cleanup race (#8201)
---
 changes/en-us/2.x.md                               |   2 +
 changes/zh-cn/2.x.md                               |   2 +
 .../server/coordinator/DefaultCoordinator.java     |   3 +-
 .../server/coordinator/DefaultCoordinatorTest.java | 273 ++++++++++++++-------
 4 files changed, 188 insertions(+), 92 deletions(-)

diff --git a/changes/en-us/2.x.md b/changes/en-us/2.x.md
index e8c3f15a67..17ee0bc3e4 100644
--- a/changes/en-us/2.x.md
+++ b/changes/en-us/2.x.md
@@ -33,6 +33,7 @@ Add changes here for all PR submitted to the 2.x branch.
 - [[#8179](https://github.com/apache/incubator-seata/pull/8179)] set 
java.version to 17 for console module to fix compilation error
 - [[#8170](https://github.com/apache/incubator-seata/pull/8170)] fix 
ConfigTools encryption corrupting non-ASCII content on non-UTF-8 platforms
 - [[#8182](https://github.com/apache/incubator-seata/issues/8182)] fix 
registry preferred networks and ignored interfaces from Spring Boot 
application.yml
+- [[#8201](https://github.com/apache/incubator-seata/issues/8197)] fix 
residual file-mode global locks caused by an async commit cleanup race
 
 
 
@@ -72,6 +73,7 @@ Thanks to these contributors for their code commits. Please 
report an unintended
 - [funky-eyes](https://github.com/funky-eyes)
 - [pyshiweijia](https://github.com/pyshiweijia)
 - [biedongbin](https://github.com/biedongbin)
+- [Zhengcy05](https://github.com/Zhengcy05)
 
 
 
diff --git a/changes/zh-cn/2.x.md b/changes/zh-cn/2.x.md
index e1cd8eb723..b794203bd5 100644
--- a/changes/zh-cn/2.x.md
+++ b/changes/zh-cn/2.x.md
@@ -34,6 +34,7 @@
 - [[#8179](https://github.com/apache/incubator-seata/pull/8179)] 将 console 模块的 
java.version 设置为 17 以修复编译错误
 - [[#8170](https://github.com/apache/incubator-seata/pull/8170)] 修复 
ConfigTools 加密在非 UTF-8 默认字符集平台损坏非 ASCII 内容的问题
 - [[#8182](https://github.com/apache/incubator-seata/issues/8182)] 修复 Spring 
Boot application.yml 中 registry preferred networks 和 ignored interfaces 配置不生效的问题
+- [[#8201](https://github.com/apache/incubator-seata/issues/8197)] 
修复异步提交清理竞态导致 file 模式全局锁残留的问题
 
 
 ### optimize:
@@ -73,6 +74,7 @@
 - [funky-eyes](https://github.com/funky-eyes)
 - [pyshiweijia](https://github.com/pyshiweijia)
 - [biedongbin](https://github.com/biedongbin)
+- [Zhengcy05](https://github.com/Zhengcy05)
 
 
 
diff --git 
a/server/src/main/java/org/apache/seata/server/coordinator/DefaultCoordinator.java
 
b/server/src/main/java/org/apache/seata/server/coordinator/DefaultCoordinator.java
index e0c637a31d..89a3fd414f 100644
--- 
a/server/src/main/java/org/apache/seata/server/coordinator/DefaultCoordinator.java
+++ 
b/server/src/main/java/org/apache/seata/server/coordinator/DefaultCoordinator.java
@@ -530,7 +530,8 @@ public class DefaultCoordinator extends 
AbstractTCInboundHandler implements Tran
         }
         SessionHelper.forEach(asyncCommittingSessions, asyncCommittingSession 
-> {
             try {
-                core.doGlobalCommit(asyncCommittingSession, true);
+                SessionHolder.lockAndExecute(
+                        asyncCommittingSession, () -> 
core.doGlobalCommit(asyncCommittingSession, true));
             } catch (TransactionException ex) {
                 LOGGER.error(
                         "Failed to async committing [{}] {} {}",
diff --git 
a/server/src/test/java/org/apache/seata/server/coordinator/DefaultCoordinatorTest.java
 
b/server/src/test/java/org/apache/seata/server/coordinator/DefaultCoordinatorTest.java
index cb1d3d7695..9ddd8d30bf 100644
--- 
a/server/src/test/java/org/apache/seata/server/coordinator/DefaultCoordinatorTest.java
+++ 
b/server/src/test/java/org/apache/seata/server/coordinator/DefaultCoordinatorTest.java
@@ -73,7 +73,10 @@ import org.springframework.context.ApplicationContext;
 
 import java.io.IOException;
 import java.util.Collection;
+import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.TimeoutException;
 import java.util.stream.Stream;
@@ -90,23 +93,23 @@ import static org.mockito.Mockito.when;
 public class DefaultCoordinatorTest extends BaseSpringBootTest {
     private static DefaultCoordinator defaultCoordinator;
 
-    private static final String applicationId = "demo-child-app";
+    private static final String APPLICATION_ID = "demo-child-app";
 
-    private static final String txServiceGroup = "default_tx_group";
+    private static final String TX_SERVICE_GROUP = "default_tx_group";
 
-    private static final String txName = "tx-1";
+    private static final String TX_NAME = "tx-1";
 
-    private static final int timeout = 3000;
+    private static final int TIMEOUT = 3000;
 
-    private static final String resourceId = "tb_1";
+    private static final String RESOURCE_ID = "tb_1";
 
-    private static final String clientId = "c_1";
+    private static final String CLIENT_ID = "c_1";
 
-    private static final String lockKeys_1 = "tb_1:11";
+    private static final String LOCK_KEYS_1 = "tb_1:11";
 
-    private static final String lockKeys_2 = "tb_1:12";
+    private static final String LOCK_KEYS_2 = "tb_1:12";
 
-    private static final String applicationData = "{\"data\":\"test\"}";
+    private static final String APPLICATION_DATA = "{\"data\":\"test\"}";
 
     private static DefaultCore core;
 
@@ -140,8 +143,9 @@ public class DefaultCoordinatorTest extends 
BaseSpringBootTest {
         String xid = null;
         GlobalSession globalSession = null;
         try {
-            xid = core.begin(applicationId, txServiceGroup, txName, timeout);
-            Long branchId = core.branchRegister(BranchType.AT, resourceId, 
clientId, xid, applicationData, lockKeys_1);
+            xid = core.begin(APPLICATION_ID, TX_SERVICE_GROUP, TX_NAME, 
TIMEOUT);
+            Long branchId =
+                    core.branchRegister(BranchType.AT, RESOURCE_ID, CLIENT_ID, 
xid, APPLICATION_DATA, LOCK_KEYS_1);
             globalSession = SessionHolder.findGlobalSession(xid);
             result = core.branchCommit(globalSession, 
globalSession.getBranch(branchId));
         } catch (TransactionException e) {
@@ -170,8 +174,8 @@ public class DefaultCoordinatorTest extends 
BaseSpringBootTest {
     @Test
     public void handleRetryRollbackingTest() throws TransactionException, 
InterruptedException {
 
-        String xid = core.begin(applicationId, txServiceGroup, txName, 10);
-        Long branchId = core.branchRegister(BranchType.AT, "abcd", clientId, 
xid, applicationData, lockKeys_2);
+        String xid = core.begin(APPLICATION_ID, TX_SERVICE_GROUP, TX_NAME, 10);
+        Long branchId = core.branchRegister(BranchType.AT, "abcd", CLIENT_ID, 
xid, APPLICATION_DATA, LOCK_KEYS_2);
 
         Assertions.assertNotNull(branchId);
         Thread.sleep(100);
@@ -187,8 +191,8 @@ public class DefaultCoordinatorTest extends 
BaseSpringBootTest {
     }) // `ReflectionUtil.modifyStaticFinalField` does not supported java17 
and above versions
     public void handleRetryRollbackingTimeOutTest()
             throws TransactionException, InterruptedException, 
NoSuchFieldException, IllegalAccessException {
-        String xid = core.begin(applicationId, txServiceGroup, txName, 10);
-        Long branchId = core.branchRegister(BranchType.AT, "abcd", clientId, 
xid, applicationData, lockKeys_2);
+        String xid = core.begin(APPLICATION_ID, TX_SERVICE_GROUP, TX_NAME, 10);
+        Long branchId = core.branchRegister(BranchType.AT, "abcd", CLIENT_ID, 
xid, APPLICATION_DATA, LOCK_KEYS_2);
 
         GlobalSession globalSession = SessionHolder.findGlobalSession(xid);
         Assertions.assertNotNull(globalSession);
@@ -221,8 +225,8 @@ public class DefaultCoordinatorTest extends 
BaseSpringBootTest {
     }) // `ReflectionUtil.modifyStaticFinalField` does not supported java17 
and above versions
     public void handleRetryRollbackingTimeOut_unlockTest()
             throws TransactionException, InterruptedException, 
NoSuchFieldException, IllegalAccessException {
-        String xid = core.begin(applicationId, txServiceGroup, txName, 10);
-        Long branchId = core.branchRegister(BranchType.AT, "abcd", clientId, 
xid, applicationData, lockKeys_2);
+        String xid = core.begin(APPLICATION_ID, TX_SERVICE_GROUP, TX_NAME, 10);
+        Long branchId = core.branchRegister(BranchType.AT, "abcd", CLIENT_ID, 
xid, APPLICATION_DATA, LOCK_KEYS_2);
 
         GlobalSession globalSession = SessionHolder.findGlobalSession(xid);
         Assertions.assertNotNull(globalSession);
@@ -276,8 +280,8 @@ public class DefaultCoordinatorTest extends 
BaseSpringBootTest {
     }
 
     static Stream<Arguments> xidAndBranchIdProviderForRollback() throws 
Exception {
-        String xid = core.begin(applicationId, txServiceGroup, txName, 
timeout);
-        Long branchId = core.branchRegister(BranchType.AT, resourceId, 
clientId, xid, applicationData, lockKeys_2);
+        String xid = core.begin(APPLICATION_ID, TX_SERVICE_GROUP, TX_NAME, 
TIMEOUT);
+        Long branchId = core.branchRegister(BranchType.AT, RESOURCE_ID, 
CLIENT_ID, xid, APPLICATION_DATA, LOCK_KEYS_2);
         return Stream.of(Arguments.of(xid, branchId));
     }
 
@@ -308,7 +312,7 @@ public class DefaultCoordinatorTest extends 
BaseSpringBootTest {
 
     @Test
     public void doBranchDeleteNullBranchTest() throws TransactionException {
-        String xid = core.begin(applicationId, txServiceGroup, txName, 
timeout);
+        String xid = core.begin(APPLICATION_ID, TX_SERVICE_GROUP, TX_NAME, 
TIMEOUT);
         GlobalSession globalSession = SessionHolder.findGlobalSession(xid);
 
         Boolean result = defaultCoordinator.doBranchDelete(globalSession, 
null);
@@ -319,7 +323,7 @@ public class DefaultCoordinatorTest extends 
BaseSpringBootTest {
 
     @Test
     public void timeoutCheckNoTimeoutTest() throws TransactionException {
-        String xid = core.begin(applicationId, txServiceGroup, txName, 30000);
+        String xid = core.begin(APPLICATION_ID, TX_SERVICE_GROUP, TX_NAME, 
30000);
         GlobalSession globalSession = SessionHolder.findGlobalSession(xid);
         Assertions.assertNotNull(globalSession);
 
@@ -354,9 +358,9 @@ public class DefaultCoordinatorTest extends 
BaseSpringBootTest {
         request.setTimeout(3000);
 
         RpcContext rpcContext = new RpcContext();
-        rpcContext.setApplicationId(applicationId);
-        rpcContext.setTransactionServiceGroup(txServiceGroup);
-        rpcContext.setClientId(clientId);
+        rpcContext.setApplicationId(APPLICATION_ID);
+        rpcContext.setTransactionServiceGroup(TX_SERVICE_GROUP);
+        rpcContext.setClientId(CLIENT_ID);
 
         AbstractResultMessage response = defaultCoordinator.onRequest(request, 
rpcContext);
         Assertions.assertNotNull(response);
@@ -375,9 +379,9 @@ public class DefaultCoordinatorTest extends 
BaseSpringBootTest {
     @Test
     public void doBranchReportTest() throws TransactionException {
         // Create global transaction and branch (without lock to avoid 
conflicts)
-        String xid = core.begin(applicationId, txServiceGroup, txName, 
timeout);
+        String xid = core.begin(APPLICATION_ID, TX_SERVICE_GROUP, TX_NAME, 
TIMEOUT);
         Long branchId =
-                core.branchRegister(BranchType.AT, "resource_branch_report", 
clientId, xid, applicationData, null);
+                core.branchRegister(BranchType.AT, "resource_branch_report", 
CLIENT_ID, xid, APPLICATION_DATA, null);
 
         GlobalSession globalSession = SessionHolder.findGlobalSession(xid);
         Assertions.assertNotNull(globalSession);
@@ -389,13 +393,13 @@ public class DefaultCoordinatorTest extends 
BaseSpringBootTest {
         request.setBranchId(branchId);
         request.setBranchType(BranchType.AT);
         request.setStatus(BranchStatus.PhaseOne_Done);
-        request.setApplicationData(applicationData);
+        request.setApplicationData(APPLICATION_DATA);
 
         // Execute test
         RpcContext rpcContext = new RpcContext();
-        rpcContext.setApplicationId(applicationId);
-        rpcContext.setTransactionServiceGroup(txServiceGroup);
-        rpcContext.setClientId(clientId);
+        rpcContext.setApplicationId(APPLICATION_ID);
+        rpcContext.setTransactionServiceGroup(TX_SERVICE_GROUP);
+        rpcContext.setClientId(CLIENT_ID);
 
         BranchReportResponse response = defaultCoordinator.handle(request, 
rpcContext);
 
@@ -413,9 +417,9 @@ public class DefaultCoordinatorTest extends 
BaseSpringBootTest {
         String testLockKey1 = "lock_check:1";
         String testLockKey2 = "lock_check:2";
 
-        String xid = core.begin(applicationId, txServiceGroup, txName, 
timeout);
+        String xid = core.begin(APPLICATION_ID, TX_SERVICE_GROUP, TX_NAME, 
TIMEOUT);
         Long branchId =
-                core.branchRegister(BranchType.AT, testResourceId, clientId, 
xid, applicationData, testLockKey1);
+                core.branchRegister(BranchType.AT, testResourceId, CLIENT_ID, 
xid, APPLICATION_DATA, testLockKey1);
 
         Assertions.assertNotNull(branchId);
 
@@ -427,9 +431,9 @@ public class DefaultCoordinatorTest extends 
BaseSpringBootTest {
         request1.setLockKey(testLockKey2);
 
         RpcContext rpcContext = new RpcContext();
-        rpcContext.setApplicationId(applicationId);
-        rpcContext.setTransactionServiceGroup(txServiceGroup);
-        rpcContext.setClientId(clientId);
+        rpcContext.setApplicationId(APPLICATION_ID);
+        rpcContext.setTransactionServiceGroup(TX_SERVICE_GROUP);
+        rpcContext.setClientId(CLIENT_ID);
 
         GlobalLockQueryResponse response1 = 
defaultCoordinator.handle(request1, rpcContext);
 
@@ -467,7 +471,7 @@ public class DefaultCoordinatorTest extends 
BaseSpringBootTest {
     @Test
     public void branchRemoveTaskConstructorWithNullBranchTest() throws 
TransactionException {
         // Create global session
-        String xid = core.begin(applicationId, txServiceGroup, txName, 
timeout);
+        String xid = core.begin(APPLICATION_ID, TX_SERVICE_GROUP, TX_NAME, 
TIMEOUT);
         GlobalSession globalSession = SessionHolder.findGlobalSession(xid);
 
         // Test creating BranchRemoveTask with null branchSession should throw 
exception
@@ -482,9 +486,9 @@ public class DefaultCoordinatorTest extends 
BaseSpringBootTest {
     @Test
     public void branchRemoveTaskRunWithSingleBranchTest() throws 
TransactionException, InterruptedException {
         // Create global session and branch (without lock to avoid conflicts)
-        String xid = core.begin(applicationId, txServiceGroup, txName, 
timeout);
+        String xid = core.begin(APPLICATION_ID, TX_SERVICE_GROUP, TX_NAME, 
TIMEOUT);
         Long branchId =
-                core.branchRegister(BranchType.AT, "resource_remove_single", 
clientId, xid, applicationData, null);
+                core.branchRegister(BranchType.AT, "resource_remove_single", 
CLIENT_ID, xid, APPLICATION_DATA, null);
 
         GlobalSession globalSession = SessionHolder.findGlobalSession(xid);
         BranchSession branchSession = globalSession.getBranch(branchId);
@@ -508,9 +512,9 @@ public class DefaultCoordinatorTest extends 
BaseSpringBootTest {
     @Test
     public void branchRemoveTaskRunWithAllBranchesTest() throws 
TransactionException, InterruptedException {
         // Create global session and multiple branches (without lock to avoid 
conflicts)
-        String xid = core.begin(applicationId, txServiceGroup, txName, 
timeout);
-        core.branchRegister(BranchType.AT, "resource_remove_all_1", clientId, 
xid, applicationData, null);
-        core.branchRegister(BranchType.AT, "resource_remove_all_2", clientId, 
xid, applicationData, null);
+        String xid = core.begin(APPLICATION_ID, TX_SERVICE_GROUP, TX_NAME, 
TIMEOUT);
+        core.branchRegister(BranchType.AT, "resource_remove_all_1", CLIENT_ID, 
xid, APPLICATION_DATA, null);
+        core.branchRegister(BranchType.AT, "resource_remove_all_2", CLIENT_ID, 
xid, APPLICATION_DATA, null);
 
         GlobalSession globalSession = SessionHolder.findGlobalSession(xid);
 
@@ -543,8 +547,8 @@ public class DefaultCoordinatorTest extends 
BaseSpringBootTest {
     @Test
     public void handleCommittingByScheduledWithSessionTest() throws 
TransactionException, InterruptedException {
         // Create global transaction
-        String xid = core.begin(applicationId, txServiceGroup, txName, 
timeout);
-        core.branchRegister(BranchType.AT, "resource_committing_scheduled", 
clientId, xid, applicationData, null);
+        String xid = core.begin(APPLICATION_ID, TX_SERVICE_GROUP, TX_NAME, 
TIMEOUT);
+        core.branchRegister(BranchType.AT, "resource_committing_scheduled", 
CLIENT_ID, xid, APPLICATION_DATA, null);
 
         GlobalSession globalSession = SessionHolder.findGlobalSession(xid);
         Assertions.assertNotNull(globalSession);
@@ -571,8 +575,8 @@ public class DefaultCoordinatorTest extends 
BaseSpringBootTest {
     @Test
     public void handleRollbackingByScheduledWithSessionTest() throws 
TransactionException, InterruptedException {
         // Create global transaction
-        String xid = core.begin(applicationId, txServiceGroup, txName, 
timeout);
-        core.branchRegister(BranchType.AT, "resource_rollbacking_scheduled", 
clientId, xid, applicationData, null);
+        String xid = core.begin(APPLICATION_ID, TX_SERVICE_GROUP, TX_NAME, 
TIMEOUT);
+        core.branchRegister(BranchType.AT, "resource_rollbacking_scheduled", 
CLIENT_ID, xid, APPLICATION_DATA, null);
 
         GlobalSession globalSession = SessionHolder.findGlobalSession(xid);
         Assertions.assertNotNull(globalSession);
@@ -599,8 +603,8 @@ public class DefaultCoordinatorTest extends 
BaseSpringBootTest {
     @Test
     public void handleEndStatesByScheduledWithCommittedSessionTest() throws 
TransactionException, InterruptedException {
         // Create global transaction
-        String xid = core.begin(applicationId, txServiceGroup, txName, 
timeout);
-        core.branchRegister(BranchType.AT, "resource_end_committed", clientId, 
xid, applicationData, null);
+        String xid = core.begin(APPLICATION_ID, TX_SERVICE_GROUP, TX_NAME, 
TIMEOUT);
+        core.branchRegister(BranchType.AT, "resource_end_committed", 
CLIENT_ID, xid, APPLICATION_DATA, null);
 
         GlobalSession globalSession = SessionHolder.findGlobalSession(xid);
         Assertions.assertNotNull(globalSession);
@@ -626,8 +630,8 @@ public class DefaultCoordinatorTest extends 
BaseSpringBootTest {
     public void handleEndStatesByScheduledWithRollbackedSessionTest()
             throws TransactionException, InterruptedException {
         // Create global transaction
-        String xid = core.begin(applicationId, txServiceGroup, txName, 
timeout);
-        core.branchRegister(BranchType.AT, "resource_end_rollbacked", 
clientId, xid, applicationData, null);
+        String xid = core.begin(APPLICATION_ID, TX_SERVICE_GROUP, TX_NAME, 
TIMEOUT);
+        core.branchRegister(BranchType.AT, "resource_end_rollbacked", 
CLIENT_ID, xid, APPLICATION_DATA, null);
 
         GlobalSession globalSession = SessionHolder.findGlobalSession(xid);
         Assertions.assertNotNull(globalSession);
@@ -652,7 +656,7 @@ public class DefaultCoordinatorTest extends 
BaseSpringBootTest {
     @Test
     public void doBranchDeleteSagaTypeTest() throws TransactionException {
         // Create SAGA type global session
-        String xid = core.begin(applicationId, txServiceGroup, txName, 
timeout);
+        String xid = core.begin(APPLICATION_ID, TX_SERVICE_GROUP, TX_NAME, 
TIMEOUT);
         GlobalSession globalSession = SessionHolder.findGlobalSession(xid);
 
         // Create SAGA type branch session
@@ -661,7 +665,7 @@ public class DefaultCoordinatorTest extends 
BaseSpringBootTest {
         branchSession.setBranchId(1L);
         branchSession.setBranchType(BranchType.SAGA);
         branchSession.setResourceId("saga_resource");
-        branchSession.setApplicationData(applicationData);
+        branchSession.setApplicationData(APPLICATION_DATA);
 
         globalSession.addBranch(branchSession);
 
@@ -678,7 +682,7 @@ public class DefaultCoordinatorTest extends 
BaseSpringBootTest {
     @Test
     public void doBranchDeleteATSuccessTest() throws TransactionException {
         // Create global session
-        String xid = core.begin(applicationId, txServiceGroup, txName, 
timeout);
+        String xid = core.begin(APPLICATION_ID, TX_SERVICE_GROUP, TX_NAME, 
TIMEOUT);
         GlobalSession globalSession = SessionHolder.findGlobalSession(xid);
 
         // Create AT type branch session
@@ -687,7 +691,7 @@ public class DefaultCoordinatorTest extends 
BaseSpringBootTest {
         branchSession.setBranchId(1L);
         branchSession.setBranchType(BranchType.AT);
         branchSession.setResourceId("at_resource");
-        branchSession.setApplicationData(applicationData);
+        branchSession.setApplicationData(APPLICATION_DATA);
 
         globalSession.addBranch(branchSession);
 
@@ -710,7 +714,7 @@ public class DefaultCoordinatorTest extends 
BaseSpringBootTest {
     @Test
     public void doBranchDeleteATFailureTest() throws TransactionException {
         // Create global session
-        String xid = core.begin(applicationId, txServiceGroup, txName, 
timeout);
+        String xid = core.begin(APPLICATION_ID, TX_SERVICE_GROUP, TX_NAME, 
TIMEOUT);
         GlobalSession globalSession = SessionHolder.findGlobalSession(xid);
 
         // Create AT type branch session
@@ -719,7 +723,7 @@ public class DefaultCoordinatorTest extends 
BaseSpringBootTest {
         branchSession.setBranchId(1L);
         branchSession.setBranchType(BranchType.AT);
         branchSession.setResourceId("at_resource");
-        branchSession.setApplicationData(applicationData);
+        branchSession.setApplicationData(APPLICATION_DATA);
 
         globalSession.addBranch(branchSession);
 
@@ -742,7 +746,7 @@ public class DefaultCoordinatorTest extends 
BaseSpringBootTest {
     @Test
     public void doBranchDeleteTCCSuccessTest() throws TransactionException {
         // Create global session
-        String xid = core.begin(applicationId, txServiceGroup, txName, 
timeout);
+        String xid = core.begin(APPLICATION_ID, TX_SERVICE_GROUP, TX_NAME, 
TIMEOUT);
         GlobalSession globalSession = SessionHolder.findGlobalSession(xid);
 
         // Create TCC type branch session
@@ -751,7 +755,7 @@ public class DefaultCoordinatorTest extends 
BaseSpringBootTest {
         branchSession.setBranchId(1L);
         branchSession.setBranchType(BranchType.TCC);
         branchSession.setResourceId("tcc_resource");
-        branchSession.setApplicationData(applicationData);
+        branchSession.setApplicationData(APPLICATION_DATA);
 
         globalSession.addBranch(branchSession);
 
@@ -774,7 +778,7 @@ public class DefaultCoordinatorTest extends 
BaseSpringBootTest {
     @Test
     public void doBranchDeleteTCCFailureTest() throws TransactionException {
         // Create global session
-        String xid = core.begin(applicationId, txServiceGroup, txName, 
timeout);
+        String xid = core.begin(APPLICATION_ID, TX_SERVICE_GROUP, TX_NAME, 
TIMEOUT);
         GlobalSession globalSession = SessionHolder.findGlobalSession(xid);
 
         // Create TCC type branch session
@@ -783,7 +787,7 @@ public class DefaultCoordinatorTest extends 
BaseSpringBootTest {
         branchSession.setBranchId(1L);
         branchSession.setBranchType(BranchType.TCC);
         branchSession.setResourceId("tcc_resource");
-        branchSession.setApplicationData(applicationData);
+        branchSession.setApplicationData(APPLICATION_DATA);
 
         globalSession.addBranch(branchSession);
 
@@ -806,7 +810,7 @@ public class DefaultCoordinatorTest extends 
BaseSpringBootTest {
     @Test
     public void doBranchDeleteXASuccessTest() throws TransactionException {
         // Create global session
-        String xid = core.begin(applicationId, txServiceGroup, txName, 
timeout);
+        String xid = core.begin(APPLICATION_ID, TX_SERVICE_GROUP, TX_NAME, 
TIMEOUT);
         GlobalSession globalSession = SessionHolder.findGlobalSession(xid);
 
         // Create XA type branch session
@@ -815,7 +819,7 @@ public class DefaultCoordinatorTest extends 
BaseSpringBootTest {
         branchSession.setBranchId(1L);
         branchSession.setBranchType(BranchType.XA);
         branchSession.setResourceId("xa_resource");
-        branchSession.setApplicationData(applicationData);
+        branchSession.setApplicationData(APPLICATION_DATA);
 
         globalSession.addBranch(branchSession);
 
@@ -841,7 +845,7 @@ public class DefaultCoordinatorTest extends 
BaseSpringBootTest {
     public void doBranchDeleteXAXaerNotaTimeoutTest()
             throws TransactionException, InterruptedException, 
NoSuchFieldException, IllegalAccessException {
         // Create global session with short timeout (10ms)
-        String xid = core.begin(applicationId, txServiceGroup, txName, 10);
+        String xid = core.begin(APPLICATION_ID, TX_SERVICE_GROUP, TX_NAME, 10);
         GlobalSession globalSession = SessionHolder.findGlobalSession(xid);
 
         // Create XA type branch session
@@ -850,7 +854,7 @@ public class DefaultCoordinatorTest extends 
BaseSpringBootTest {
         branchSession.setBranchId(1L);
         branchSession.setBranchType(BranchType.XA);
         branchSession.setResourceId("xa_resource");
-        branchSession.setApplicationData(applicationData);
+        branchSession.setApplicationData(APPLICATION_DATA);
 
         globalSession.addBranch(branchSession);
 
@@ -889,7 +893,7 @@ public class DefaultCoordinatorTest extends 
BaseSpringBootTest {
     @Test
     public void doBranchDeleteXAXaerNotaNoTimeoutTest() throws 
TransactionException {
         // Create global session with long timeout
-        String xid = core.begin(applicationId, txServiceGroup, txName, 30000);
+        String xid = core.begin(APPLICATION_ID, TX_SERVICE_GROUP, TX_NAME, 
30000);
         GlobalSession globalSession = SessionHolder.findGlobalSession(xid);
 
         // Create XA type branch session
@@ -898,7 +902,7 @@ public class DefaultCoordinatorTest extends 
BaseSpringBootTest {
         branchSession.setBranchId(1L);
         branchSession.setBranchType(BranchType.XA);
         branchSession.setResourceId("xa_resource");
-        branchSession.setApplicationData(applicationData);
+        branchSession.setApplicationData(APPLICATION_DATA);
 
         globalSession.addBranch(branchSession);
 
@@ -921,7 +925,7 @@ public class DefaultCoordinatorTest extends 
BaseSpringBootTest {
     @Test
     public void doBranchDeleteXAFailureTest() throws TransactionException {
         // Create global session
-        String xid = core.begin(applicationId, txServiceGroup, txName, 
timeout);
+        String xid = core.begin(APPLICATION_ID, TX_SERVICE_GROUP, TX_NAME, 
TIMEOUT);
         GlobalSession globalSession = SessionHolder.findGlobalSession(xid);
 
         // Create XA type branch session
@@ -930,7 +934,7 @@ public class DefaultCoordinatorTest extends 
BaseSpringBootTest {
         branchSession.setBranchId(1L);
         branchSession.setBranchType(BranchType.XA);
         branchSession.setResourceId("xa_resource");
-        branchSession.setApplicationData(applicationData);
+        branchSession.setApplicationData(APPLICATION_DATA);
 
         globalSession.addBranch(branchSession);
 
@@ -953,7 +957,7 @@ public class DefaultCoordinatorTest extends 
BaseSpringBootTest {
     @Test
     public void doBranchDeleteUnretryableTest() throws TransactionException {
         // Create global session
-        String xid = core.begin(applicationId, txServiceGroup, txName, 
timeout);
+        String xid = core.begin(APPLICATION_ID, TX_SERVICE_GROUP, TX_NAME, 
TIMEOUT);
         GlobalSession globalSession = SessionHolder.findGlobalSession(xid);
 
         // Create AT type branch session
@@ -962,7 +966,7 @@ public class DefaultCoordinatorTest extends 
BaseSpringBootTest {
         branchSession.setBranchId(1L);
         branchSession.setBranchType(BranchType.AT);
         branchSession.setResourceId("at_resource");
-        branchSession.setApplicationData(applicationData);
+        branchSession.setApplicationData(APPLICATION_DATA);
 
         globalSession.addBranch(branchSession);
 
@@ -985,7 +989,7 @@ public class DefaultCoordinatorTest extends 
BaseSpringBootTest {
     @Test
     public void doBranchDeleteGeneralFailureTest() throws TransactionException 
{
         // Create global session
-        String xid = core.begin(applicationId, txServiceGroup, txName, 
timeout);
+        String xid = core.begin(APPLICATION_ID, TX_SERVICE_GROUP, TX_NAME, 
TIMEOUT);
         GlobalSession globalSession = SessionHolder.findGlobalSession(xid);
 
         // Create an unknown type branch session (using AT type but returns 
mismatched status)
@@ -994,7 +998,7 @@ public class DefaultCoordinatorTest extends 
BaseSpringBootTest {
         branchSession.setBranchId(1L);
         branchSession.setBranchType(BranchType.AT);
         branchSession.setResourceId("at_resource");
-        branchSession.setApplicationData(applicationData);
+        branchSession.setApplicationData(APPLICATION_DATA);
 
         globalSession.addBranch(branchSession);
 
@@ -1017,7 +1021,7 @@ public class DefaultCoordinatorTest extends 
BaseSpringBootTest {
     @Test
     public void doGlobalStatusTest() throws TransactionException {
         // Create global transaction
-        String xid = core.begin(applicationId, txServiceGroup, txName, 
timeout);
+        String xid = core.begin(APPLICATION_ID, TX_SERVICE_GROUP, TX_NAME, 
TIMEOUT);
         GlobalSession globalSession = SessionHolder.findGlobalSession(xid);
         Assertions.assertNotNull(globalSession);
 
@@ -1027,9 +1031,9 @@ public class DefaultCoordinatorTest extends 
BaseSpringBootTest {
 
         // Execute test
         RpcContext rpcContext = new RpcContext();
-        rpcContext.setApplicationId(applicationId);
-        rpcContext.setTransactionServiceGroup(txServiceGroup);
-        rpcContext.setClientId(clientId);
+        rpcContext.setApplicationId(APPLICATION_ID);
+        rpcContext.setTransactionServiceGroup(TX_SERVICE_GROUP);
+        rpcContext.setClientId(CLIENT_ID);
 
         GlobalStatusResponse response = defaultCoordinator.handle(request, 
rpcContext);
 
@@ -1044,7 +1048,7 @@ public class DefaultCoordinatorTest extends 
BaseSpringBootTest {
     @Test
     public void doGlobalReportTest() throws TransactionException {
         // Create global transaction
-        String xid = core.begin(applicationId, txServiceGroup, txName, 
timeout);
+        String xid = core.begin(APPLICATION_ID, TX_SERVICE_GROUP, TX_NAME, 
TIMEOUT);
         GlobalSession globalSession = SessionHolder.findGlobalSession(xid);
         Assertions.assertNotNull(globalSession);
 
@@ -1058,9 +1062,9 @@ public class DefaultCoordinatorTest extends 
BaseSpringBootTest {
 
         // Execute test
         RpcContext rpcContext = new RpcContext();
-        rpcContext.setApplicationId(applicationId);
-        rpcContext.setTransactionServiceGroup(txServiceGroup);
-        rpcContext.setClientId(clientId);
+        rpcContext.setApplicationId(APPLICATION_ID);
+        rpcContext.setTransactionServiceGroup(TX_SERVICE_GROUP);
+        rpcContext.setClientId(CLIENT_ID);
 
         GlobalReportResponse response = defaultCoordinator.handle(request, 
rpcContext);
 
@@ -1078,7 +1082,7 @@ public class DefaultCoordinatorTest extends 
BaseSpringBootTest {
     @Test
     public void doBranchRegisterTest() throws TransactionException {
         // Create global transaction
-        String xid = core.begin(applicationId, txServiceGroup, txName, 
timeout);
+        String xid = core.begin(APPLICATION_ID, TX_SERVICE_GROUP, TX_NAME, 
TIMEOUT);
         GlobalSession globalSession = SessionHolder.findGlobalSession(xid);
         Assertions.assertNotNull(globalSession);
 
@@ -1087,14 +1091,14 @@ public class DefaultCoordinatorTest extends 
BaseSpringBootTest {
         request.setXid(xid);
         request.setBranchType(BranchType.AT);
         request.setResourceId("resource_branch_register");
-        request.setApplicationData(applicationData);
+        request.setApplicationData(APPLICATION_DATA);
         request.setLockKey("branch_register:1");
 
         // Execute test
         RpcContext rpcContext = new RpcContext();
-        rpcContext.setApplicationId(applicationId);
-        rpcContext.setTransactionServiceGroup(txServiceGroup);
-        rpcContext.setClientId(clientId);
+        rpcContext.setApplicationId(APPLICATION_ID);
+        rpcContext.setTransactionServiceGroup(TX_SERVICE_GROUP);
+        rpcContext.setClientId(CLIENT_ID);
 
         BranchRegisterResponse response = defaultCoordinator.handle(request, 
rpcContext);
 
@@ -1115,7 +1119,7 @@ public class DefaultCoordinatorTest extends 
BaseSpringBootTest {
     @Test
     public void timeoutCheckWithTimeoutTest() throws TransactionException, 
InterruptedException {
         // Create global transaction with very short timeout (10ms)
-        String xid = core.begin(applicationId, txServiceGroup, txName, 10);
+        String xid = core.begin(APPLICATION_ID, TX_SERVICE_GROUP, TX_NAME, 10);
         GlobalSession globalSession = SessionHolder.findGlobalSession(xid);
         Assertions.assertNotNull(globalSession);
         Assertions.assertEquals(GlobalStatus.Begin, globalSession.getStatus());
@@ -1140,9 +1144,9 @@ public class DefaultCoordinatorTest extends 
BaseSpringBootTest {
     public void handleRetryCommittingTimeoutTest()
             throws TransactionException, InterruptedException, 
NoSuchFieldException, IllegalAccessException {
         // Create global transaction with short timeout
-        String xid = core.begin(applicationId, txServiceGroup, txName, 10);
+        String xid = core.begin(APPLICATION_ID, TX_SERVICE_GROUP, TX_NAME, 10);
         Long branchId =
-                core.branchRegister(BranchType.AT, "resource_commit_retry", 
clientId, xid, applicationData, null);
+                core.branchRegister(BranchType.AT, "resource_commit_retry", 
CLIENT_ID, xid, APPLICATION_DATA, null);
 
         GlobalSession globalSession = SessionHolder.findGlobalSession(xid);
         Assertions.assertNotNull(globalSession);
@@ -1189,7 +1193,7 @@ public class DefaultCoordinatorTest extends 
BaseSpringBootTest {
     @Test
     public void handleRetryCommittingWithEmptyBranchesTest() throws 
TransactionException {
         // Create global transaction
-        String xid = core.begin(applicationId, txServiceGroup, txName, 
timeout);
+        String xid = core.begin(APPLICATION_ID, TX_SERVICE_GROUP, TX_NAME, 
TIMEOUT);
         GlobalSession globalSession = SessionHolder.findGlobalSession(xid);
         Assertions.assertNotNull(globalSession);
 
@@ -1213,8 +1217,8 @@ public class DefaultCoordinatorTest extends 
BaseSpringBootTest {
     @Test
     public void handleAsyncCommittingSuccessTest() throws 
TransactionException, InterruptedException {
         // Create global transaction
-        String xid = core.begin(applicationId, txServiceGroup, txName, 
timeout);
-        core.branchRegister(BranchType.AT, "resource_async_commit", clientId, 
xid, applicationData, null);
+        String xid = core.begin(APPLICATION_ID, TX_SERVICE_GROUP, TX_NAME, 
TIMEOUT);
+        core.branchRegister(BranchType.AT, "resource_async_commit", CLIENT_ID, 
xid, APPLICATION_DATA, null);
 
         GlobalSession globalSession = SessionHolder.findGlobalSession(xid);
         Assertions.assertNotNull(globalSession);
@@ -1232,10 +1236,69 @@ public class DefaultCoordinatorTest extends 
BaseSpringBootTest {
         }
     }
 
+    @Test
+    public void handleAsyncCommittingWaitsForGlobalSessionLockTest() throws 
Exception {
+        LockTrackingGlobalSession globalSession =
+                new LockTrackingGlobalSession(APPLICATION_ID, 
TX_SERVICE_GROUP, TX_NAME, TIMEOUT);
+        globalSession.begin();
+        Long branchId = core.branchRegister(
+                BranchType.AT,
+                "resource_async_commit_lock",
+                CLIENT_ID,
+                globalSession.getXid(),
+                APPLICATION_DATA,
+                LOCK_KEYS_1);
+        ExecutorService executor = Executors.newSingleThreadExecutor();
+        Future<?> asyncCommitFuture = null;
+
+        try {
+            globalSession.lock();
+            try {
+                globalSession.changeGlobalStatus(GlobalStatus.AsyncCommitting);
+                globalSession.trackLockAttempt();
+                asyncCommitFuture = 
executor.submit(defaultCoordinator::handleAsyncCommitting);
+
+                Assertions.assertTrue(globalSession.awaitLockAttempt(5, 
TimeUnit.SECONDS));
+                Assertions.assertFalse(asyncCommitFuture.isDone());
+                Assertions.assertNotNull(globalSession.getBranch(branchId));
+
+                // Simulate the initial commit thread finishing global lock 
cleanup before releasing the session lock.
+                globalSession.clean();
+            } finally {
+                globalSession.unlock();
+            }
+
+            asyncCommitFuture.get(5, TimeUnit.SECONDS);
+            
Assertions.assertNull(SessionHolder.findGlobalSession(globalSession.getXid()));
+
+            String nextXid = core.begin(APPLICATION_ID, TX_SERVICE_GROUP, 
TX_NAME, TIMEOUT);
+            GlobalSession nextGlobalSession = 
SessionHolder.findGlobalSession(nextXid);
+            try {
+                Assertions.assertNotNull(core.branchRegister(
+                        BranchType.AT,
+                        "resource_async_commit_lock",
+                        CLIENT_ID,
+                        nextXid,
+                        APPLICATION_DATA,
+                        LOCK_KEYS_1));
+            } finally {
+                nextGlobalSession.changeGlobalStatus(GlobalStatus.Committed);
+                nextGlobalSession.end();
+            }
+        } finally {
+            executor.shutdownNow();
+            GlobalSession remainingSession = 
SessionHolder.findGlobalSession(globalSession.getXid());
+            if (remainingSession != null) {
+                remainingSession.changeGlobalStatus(GlobalStatus.Committed);
+                remainingSession.end();
+            }
+        }
+    }
+
     @Test
     public void undoLogDeleteWithActiveChannelsTest() throws 
TransactionException {
         // Create global transaction to ensure session manager is active
-        String xid = core.begin(applicationId, txServiceGroup, txName, 
timeout);
+        String xid = core.begin(APPLICATION_ID, TX_SERVICE_GROUP, TX_NAME, 
TIMEOUT);
         GlobalSession globalSession = SessionHolder.findGlobalSession(xid);
         Assertions.assertNotNull(globalSession);
 
@@ -1305,4 +1368,32 @@ public class DefaultCoordinatorTest extends 
BaseSpringBootTest {
         @Override
         public void registerProcessor(int messageType, RemotingProcessor 
processor, ExecutorService executor) {}
     }
+
+    private static class LockTrackingGlobalSession extends GlobalSession {
+
+        private final CountDownLatch lockAttempted = new CountDownLatch(1);
+
+        private volatile boolean trackLockAttempt;
+
+        private LockTrackingGlobalSession(
+                String applicationId, String transactionServiceGroup, String 
transactionName, int timeout) {
+            super(applicationId, transactionServiceGroup, transactionName, 
timeout);
+        }
+
+        @Override
+        public void lock() throws TransactionException {
+            if (trackLockAttempt) {
+                lockAttempted.countDown();
+            }
+            super.lock();
+        }
+
+        private void trackLockAttempt() {
+            trackLockAttempt = true;
+        }
+
+        private boolean awaitLockAttempt(long timeout, TimeUnit unit) throws 
InterruptedException {
+            return lockAttempted.await(timeout, unit);
+        }
+    }
 }


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to