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

duanzhengqiang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/shardingsphere.git


The following commit(s) were added to refs/heads/master by this push:
     new 78b1bfdfc59 Fix thread safety issue in inline expression (#30295)
78b1bfdfc59 is described below

commit 78b1bfdfc592a4981acdcfe81d4d178de716b145
Author: ZhangCheng <[email protected]>
AuthorDate: Mon Feb 26 18:24:10 2024 +0800

    Fix thread safety issue in inline expression (#30295)
    
    * Remove unused transaction test config
    
    * Fix thread safety issue in inline expression
    
    * Fix thread safety issue in inline expression
    
    * Fix thread safety issue in inline expression
    
    * Fix thread safety issue in inline expression
---
 .../infra/expr/spi/InlineExpressionParser.java     |  2 --
 .../expr/groovy/GroovyInlineExpressionParser.java  |  5 ++--
 .../groovy/GroovyInlineExpressionParserTest.java   | 34 ++++++++++++++++++++++
 3 files changed, 36 insertions(+), 5 deletions(-)

diff --git 
a/infra/expr/spi/src/main/java/org/apache/shardingsphere/infra/expr/spi/InlineExpressionParser.java
 
b/infra/expr/spi/src/main/java/org/apache/shardingsphere/infra/expr/spi/InlineExpressionParser.java
index 7de26d6c13b..28a2ed02bbc 100644
--- 
a/infra/expr/spi/src/main/java/org/apache/shardingsphere/infra/expr/spi/InlineExpressionParser.java
+++ 
b/infra/expr/spi/src/main/java/org/apache/shardingsphere/infra/expr/spi/InlineExpressionParser.java
@@ -17,7 +17,6 @@
 
 package org.apache.shardingsphere.infra.expr.spi;
 
-import org.apache.shardingsphere.infra.spi.annotation.SingletonSPI;
 import org.apache.shardingsphere.infra.spi.type.typed.TypedSPI;
 
 import java.util.List;
@@ -26,7 +25,6 @@ import java.util.Map;
 /**
  * Inline expression parser.
  */
-@SingletonSPI
 public interface InlineExpressionParser extends TypedSPI {
     
     /**
diff --git 
a/infra/expr/type/groovy/src/main/java/org/apache/shardingsphere/infra/expr/groovy/GroovyInlineExpressionParser.java
 
b/infra/expr/type/groovy/src/main/java/org/apache/shardingsphere/infra/expr/groovy/GroovyInlineExpressionParser.java
index 181d4516ca8..039da3526a2 100644
--- 
a/infra/expr/type/groovy/src/main/java/org/apache/shardingsphere/infra/expr/groovy/GroovyInlineExpressionParser.java
+++ 
b/infra/expr/type/groovy/src/main/java/org/apache/shardingsphere/infra/expr/groovy/GroovyInlineExpressionParser.java
@@ -88,9 +88,8 @@ public final class GroovyInlineExpressionParser implements 
InlineExpressionParse
      */
     @Override
     public String evaluateWithArgs(final Map<String, Comparable<?>> map) {
-        Closure<?> result = (Closure<?>) evaluate("{it -> \"" + 
handlePlaceHolder(inlineExpression) + "\"}");
-        result.rehydrate(new Expando(), null, null)
-                .setResolveStrategy(Closure.DELEGATE_ONLY);
+        Closure<?> result = ((Closure<?>) evaluate("{it -> \"" + 
handlePlaceHolder(inlineExpression) + "\"}")).rehydrate(new Expando(), null, 
null);
+        result.setResolveStrategy(Closure.DELEGATE_ONLY);
         map.forEach(result::setProperty);
         return result.call().toString();
     }
diff --git 
a/infra/expr/type/groovy/src/test/java/org/apache/shardingsphere/infra/expr/groovy/GroovyInlineExpressionParserTest.java
 
b/infra/expr/type/groovy/src/test/java/org/apache/shardingsphere/infra/expr/groovy/GroovyInlineExpressionParserTest.java
index 7c2aec2464a..e2d85bd1999 100644
--- 
a/infra/expr/type/groovy/src/test/java/org/apache/shardingsphere/infra/expr/groovy/GroovyInlineExpressionParserTest.java
+++ 
b/infra/expr/type/groovy/src/test/java/org/apache/shardingsphere/infra/expr/groovy/GroovyInlineExpressionParserTest.java
@@ -17,15 +17,21 @@
 
 package org.apache.shardingsphere.infra.expr.groovy;
 
+import lombok.SneakyThrows;
 import org.apache.shardingsphere.infra.expr.spi.InlineExpressionParser;
 import org.apache.shardingsphere.infra.spi.type.typed.TypedSPILoader;
 import org.apache.shardingsphere.test.util.PropertiesBuilder;
 import org.junit.jupiter.api.Test;
 
+import java.util.ArrayList;
 import java.util.Collections;
 import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Properties;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
 
 import static org.hamcrest.CoreMatchers.hasItems;
 import static org.hamcrest.CoreMatchers.is;
@@ -135,4 +141,32 @@ class GroovyInlineExpressionParserTest {
         assertThat(TypedSPILoader.getService(InlineExpressionParser.class, 
"GROOVY", PropertiesBuilder.build(
                 new 
PropertiesBuilder.Property(InlineExpressionParser.INLINE_EXPRESSION_KEY, 
"${1+2}"))).evaluateWithArgs(new LinkedHashMap<>()), is("3"));
     }
+    
+    @Test
+    @SneakyThrows({ExecutionException.class, InterruptedException.class})
+    void assertThreadSafety() {
+        int threadCount = 10;
+        ExecutorService pool = Executors.newFixedThreadPool(threadCount);
+        List<Future<?>> futures = new ArrayList<>(threadCount);
+        for (int i = 0; i < threadCount; i++) {
+            Future<?> future = 
pool.submit(this::createInlineExpressionParseTask);
+            futures.add(future);
+        }
+        for (Future<?> future : futures) {
+            future.get();
+        }
+        pool.shutdown();
+    }
+    
+    private void createInlineExpressionParseTask() {
+        for (int j = 0; j < 5; j++) {
+            String resultSuffix = Thread.currentThread().getName() + "--" + j;
+            String actual = 
TypedSPILoader.getService(InlineExpressionParser.class, "GROOVY", 
PropertiesBuilder.build(
+                    new 
PropertiesBuilder.Property(InlineExpressionParser.INLINE_EXPRESSION_KEY, 
"ds_${id}"))).evaluateWithArgs(Collections.singletonMap("id", resultSuffix));
+            assertThat(actual, is(String.format("ds_%s", resultSuffix)));
+            String actual2 = 
TypedSPILoader.getService(InlineExpressionParser.class, "GROOVY", 
PropertiesBuilder.build(
+                    new 
PropertiesBuilder.Property(InlineExpressionParser.INLINE_EXPRESSION_KEY, 
"account_${id}"))).evaluateWithArgs(Collections.singletonMap("id", 
resultSuffix));
+            assertThat(actual2, is(String.format("account_%s", resultSuffix)));
+        }
+    }
 }

Reply via email to