From d4b20eced9c32396ce7de87d43027401114a4d0c Mon Sep 17 00:00:00 2001
From: caohdgege <1170050364@qq.com>
Date: Thu, 29 Apr 2021 09:29:55 +0800
Subject: [PATCH] bugfix: fix the case that could not retry acquire global lock
 (#3687)

---
 all/pom.xml                                   |  2 +-
 bom/pom.xml                                   |  2 +-
 changes/1.5.0.md                              |  2 ++
 changes/en-us/1.5.0.md                        |  5 ++++-
 .../java/io/seata/core/protocol/Version.java  |  2 +-
 pom.xml                                       |  2 +-
 .../seata/rm/datasource/ConnectionProxy.java  | 21 ++++++++++++++-----
 .../exec/AbstractDMLBaseExecutor.java         |  3 +--
 .../rm/datasource/ConnectionProxyTest.java    |  8 +++----
 9 files changed, 31 insertions(+), 16 deletions(-)

diff --git a/all/pom.xml b/all/pom.xml
index 544712a0a..7ad0d2de5 100644
--- a/all/pom.xml
+++ b/all/pom.xml
@@ -21,7 +21,7 @@
 
     <groupId>io.seata</groupId>
     <artifactId>seata-all</artifactId>
-    <version>1.4.2</version>
+    <version>1.5.0-SNAPSHOT</version>
 
     <name>Seata All-in-one ${project.version}</name>
     <url>http://seata.io</url>
diff --git a/bom/pom.xml b/bom/pom.xml
index 20e7cd58f..93f09d76f 100644
--- a/bom/pom.xml
+++ b/bom/pom.xml
@@ -20,7 +20,7 @@
 
     <groupId>io.seata</groupId>
     <artifactId>seata-bom</artifactId>
-    <version>1.4.2</version>
+    <version>1.5.0-SNAPSHOT</version>
 
     <modelVersion>4.0.0</modelVersion>
     <packaging>pom</packaging>
diff --git a/changes/1.5.0.md b/changes/1.5.0.md
index ccddd779c..f5fdff0e7 100644
--- a/changes/1.5.0.md
+++ b/changes/1.5.0.md
@@ -29,6 +29,7 @@ Seata 是一款开源的分布式事务解决方案,提供高性能和简单
 
 - [[#3678](https://github.com/seata/seata/pull/3678)] 补充遗漏的配置及新版本pr登记md文件
 - [[#3654](https://github.com/seata/seata/pull/3654)] 修正拼写,applicationContex -> applicationContext
+- [[#3687](https://github.com/seata/seata/pull/3687)] 修复某些场景下无法重试全局锁的问题
 
   ### test:
 
@@ -40,6 +41,7 @@ Seata 是一款开源的分布式事务解决方案,提供高性能和简单
   - [slievrly](https://github.com/slievrly) 
   - [a364176773](https://github.com/a364176773) 
   - [drgnchan](https://github.com/drgnchan) 
+  - [caohdgege](https://github.com/caohdgege)
 
 
 
diff --git a/changes/en-us/1.5.0.md b/changes/en-us/1.5.0.md
index e1614905e..7bcd9aefa 100644
--- a/changes/en-us/1.5.0.md
+++ b/changes/en-us/1.5.0.md
@@ -29,6 +29,8 @@
 
 - [[#3678](https://github.com/seata/seata/pull/3678)] supplement missing configuration and new version documents
 - [[#3654](https://github.com/seata/seata/pull/3654)] fix typo,applicationContex -> applicationContext
+- [[#3687](https://github.com/seata/seata/pull/3687)] fix the case that could not retry acquire global lock
+
 
   ### test:	
 
@@ -39,8 +41,9 @@
   - [slievrly](https://github.com/slievrly) 
   - [a364176773](https://github.com/a364176773) 
   - [drgnchan](https://github.com/drgnchan) 
+  - [caohdgege](https://github.com/caohdgege)
+
 
-    
 
   Also, we receive many valuable issues, questions and advices from our community. Thanks for you all.	
 
diff --git a/core/src/main/java/io/seata/core/protocol/Version.java b/core/src/main/java/io/seata/core/protocol/Version.java
index f03f30851..7a81a9a88 100644
--- a/core/src/main/java/io/seata/core/protocol/Version.java
+++ b/core/src/main/java/io/seata/core/protocol/Version.java
@@ -32,7 +32,7 @@ public class Version {
     /**
      * The constant CURRENT.
      */
-    private static final String CURRENT = "1.4.2";
+    private static final String CURRENT = "1.5.0-SNAPSHOT";
     private static final String VERSION_0_7_1 = "0.7.1";
     private static final int MAX_VERSION_DOT = 3;
 
diff --git a/pom.xml b/pom.xml
index 17f1e85cd..09611c383 100644
--- a/pom.xml
+++ b/pom.xml
@@ -89,7 +89,7 @@
 
     <properties>
         <!-- seata version -->
-        <revision>1.4.2</revision>
+        <revision>1.5.0-SNAPSHOT</revision>
 
         <!-- Compiler settings properties -->
         <maven.compiler.source>1.8</maven.compiler.source>
diff --git a/rm-datasource/src/main/java/io/seata/rm/datasource/ConnectionProxy.java b/rm-datasource/src/main/java/io/seata/rm/datasource/ConnectionProxy.java
index 784a4bee0..465da1b73 100644
--- a/rm-datasource/src/main/java/io/seata/rm/datasource/ConnectionProxy.java
+++ b/rm-datasource/src/main/java/io/seata/rm/datasource/ConnectionProxy.java
@@ -48,7 +48,9 @@ public class ConnectionProxy extends AbstractConnectionProxy {
 
     private static final Logger LOGGER = LoggerFactory.getLogger(ConnectionProxy.class);
 
-    private ConnectionContext context = new ConnectionContext();
+    private final ConnectionContext context = new ConnectionContext();
+
+    private final LockRetryPolicy lockRetryPolicy = new LockRetryPolicy(this);
 
     private static final int REPORT_RETRY_COUNT = ConfigurationFactory.getInstance().getInt(
         ConfigurationKeys.CLIENT_REPORT_RETRY_COUNT, DEFAULT_CLIENT_REPORT_RETRY_COUNT);
@@ -56,8 +58,6 @@ public class ConnectionProxy extends AbstractConnectionProxy {
     public static final boolean IS_REPORT_SUCCESS_ENABLE = ConfigurationFactory.getInstance().getBoolean(
         ConfigurationKeys.CLIENT_REPORT_SUCCESS_ENABLE, DEFAULT_CLIENT_REPORT_SUCCESS_ENABLE);
 
-    private final static LockRetryPolicy LOCK_RETRY_POLICY = new LockRetryPolicy();
-
     /**
      * Instantiates a new Connection proxy.
      *
@@ -184,7 +184,7 @@ public class ConnectionProxy extends AbstractConnectionProxy {
     @Override
     public void commit() throws SQLException {
         try {
-            LOCK_RETRY_POLICY.execute(() -> {
+            lockRetryPolicy.execute(() -> {
                 doCommit();
                 return null;
             });
@@ -328,10 +328,21 @@ public class ConnectionProxy extends AbstractConnectionProxy {
         protected static final boolean LOCK_RETRY_POLICY_BRANCH_ROLLBACK_ON_CONFLICT = ConfigurationFactory
             .getInstance().getBoolean(ConfigurationKeys.CLIENT_LOCK_RETRY_POLICY_BRANCH_ROLLBACK_ON_CONFLICT, DEFAULT_CLIENT_LOCK_RETRY_POLICY_BRANCH_ROLLBACK_ON_CONFLICT);
 
+        protected final ConnectionProxy connection;
+
+        public LockRetryPolicy(ConnectionProxy connection) {
+            this.connection = connection;
+        }
+
         public <T> T execute(Callable<T> callable) throws Exception {
-            if (LOCK_RETRY_POLICY_BRANCH_ROLLBACK_ON_CONFLICT) {
+            // the only case that not need to retry acquire lock hear is
+            //    LOCK_RETRY_POLICY_BRANCH_ROLLBACK_ON_CONFLICT == true && connection#autoCommit == true
+            // because it has retry acquire lock when AbstractDMLBaseExecutor#executeAutoCommitTrue
+            if (LOCK_RETRY_POLICY_BRANCH_ROLLBACK_ON_CONFLICT && connection.getContext().isAutoCommitChanged()) {
                 return callable.call();
             } else {
+                // LOCK_RETRY_POLICY_BRANCH_ROLLBACK_ON_CONFLICT == false
+                // or LOCK_RETRY_POLICY_BRANCH_ROLLBACK_ON_CONFLICT == true && autoCommit == false
                 return doRetryOnLockConflict(callable);
             }
         }
diff --git a/rm-datasource/src/main/java/io/seata/rm/datasource/exec/AbstractDMLBaseExecutor.java b/rm-datasource/src/main/java/io/seata/rm/datasource/exec/AbstractDMLBaseExecutor.java
index d42d365bc..ae73f5ddc 100644
--- a/rm-datasource/src/main/java/io/seata/rm/datasource/exec/AbstractDMLBaseExecutor.java
+++ b/rm-datasource/src/main/java/io/seata/rm/datasource/exec/AbstractDMLBaseExecutor.java
@@ -172,10 +172,9 @@ public abstract class AbstractDMLBaseExecutor<T, S extends Statement> extends Ba
     protected abstract TableRecords afterImage(TableRecords beforeImage) throws SQLException;
 
     private static class LockRetryPolicy extends ConnectionProxy.LockRetryPolicy {
-        private final ConnectionProxy connection;
 
         LockRetryPolicy(final ConnectionProxy connection) {
-            this.connection = connection;
+            super(connection);
         }
 
         @Override
diff --git a/rm-datasource/src/test/java/io/seata/rm/datasource/ConnectionProxyTest.java b/rm-datasource/src/test/java/io/seata/rm/datasource/ConnectionProxyTest.java
index 7170f8c6e..5864d8c7c 100644
--- a/rm-datasource/src/test/java/io/seata/rm/datasource/ConnectionProxyTest.java
+++ b/rm-datasource/src/test/java/io/seata/rm/datasource/ConnectionProxyTest.java
@@ -20,8 +20,9 @@ import io.seata.core.exception.TransactionExceptionCode;
 import io.seata.core.model.BranchType;
 import io.seata.core.model.ResourceManager;
 import io.seata.rm.DefaultResourceManager;
-import io.seata.rm.datasource.exec.LockConflictException;
 import io.seata.rm.datasource.exec.LockWaitTimeoutException;
+import io.seata.rm.datasource.mock.MockConnection;
+import io.seata.rm.datasource.mock.MockDriver;
 import io.seata.rm.datasource.undo.SQLUndoLog;
 import org.junit.jupiter.api.Assertions;
 import org.junit.jupiter.api.BeforeEach;
@@ -72,11 +73,10 @@ public class ConnectionProxyTest {
     public void testLockRetryPolicyRollbackOnConflict() throws Exception {
         boolean oldBranchRollbackFlag = (boolean) branchRollbackFlagField.get(null);
         branchRollbackFlagField.set(null, true);
-        ConnectionProxy connectionProxy = new ConnectionProxy(dataSourceProxy, null);
-        connectionProxy.bind(TEST_XID);
+        ConnectionProxy connectionProxy = new ConnectionProxy(dataSourceProxy, new MockConnection(new MockDriver(), "", null));        connectionProxy.bind(TEST_XID);
         connectionProxy.appendUndoLog(new SQLUndoLog());
         connectionProxy.appendLockKey(lockKey);
-        Assertions.assertThrows(LockConflictException.class, connectionProxy::commit);
+        Assertions.assertThrows(LockWaitTimeoutException.class, connectionProxy::commit);
         branchRollbackFlagField.set(null, oldBranchRollbackFlag);
     }
 
-- 
GitLab