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)));
+ }
+ }
}