Просмотр исходного кода

bug #I5F73R 隐式子流程如果是并发的,则初始参数在并发中会被覆盖的问题

everywhere.z 2 лет назад
Родитель
Сommit
0409561d45
17 измененных файлов с 350 добавлено и 6 удалено
  1. 15 2
      liteflow-core/src/main/java/com/yomahub/liteflow/slot/Slot.java
  2. 14 1
      liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/java/com/yomahub/liteflow/test/subflow/ImplicitSubFlowELDeclSpringbootTest.java
  3. 35 0
      liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/java/com/yomahub/liteflow/test/subflow/cmp2/PCmp.java
  4. 33 0
      liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/java/com/yomahub/liteflow/test/subflow/cmp2/QCmp.java
  5. 8 0
      liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/resources/subflow/flow-implicit.el.xml
  6. 14 1
      liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/java/com/yomahub/liteflow/test/subflow/ImplicitSubFlowTest.java
  7. 27 0
      liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/java/com/yomahub/liteflow/test/subflow/cmp2/PCmp.java
  8. 27 0
      liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/java/com/yomahub/liteflow/test/subflow/cmp2/QCmp.java
  9. 11 0
      liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/resources/subflow/flow-implicit.el.xml
  10. 14 1
      liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/subflow/ImplicitSubFlowELSpringbootTest.java
  11. 32 0
      liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/subflow/cmp2/PCmp.java
  12. 31 0
      liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/subflow/cmp2/QCmp.java
  13. 8 0
      liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/subflow/flow-implicit.el.xml
  14. 14 1
      liteflow-testcase-el/liteflow-testcase-el-springnative/src/test/java/com/yomahub/liteflow/test/subflow/ImplicitSubFlowELSpringTest.java
  15. 30 0
      liteflow-testcase-el/liteflow-testcase-el-springnative/src/test/java/com/yomahub/liteflow/test/subflow/cmp2/PCmp.java
  16. 29 0
      liteflow-testcase-el/liteflow-testcase-el-springnative/src/test/java/com/yomahub/liteflow/test/subflow/cmp2/QCmp.java
  17. 8 0
      liteflow-testcase-el/liteflow-testcase-el-springnative/src/test/resources/subflow/flow-implicit.el.xml

+ 15 - 2
liteflow-core/src/main/java/com/yomahub/liteflow/slot/Slot.java

@@ -7,6 +7,7 @@
  */
 package com.yomahub.liteflow.slot;
 
+import cn.hutool.core.collection.ListUtil;
 import cn.hutool.core.util.ObjectUtil;
 import com.yomahub.liteflow.exception.NoSuchContextBeanException;
 import com.yomahub.liteflow.exception.NullParamException;
@@ -112,11 +113,23 @@ public class Slot{
 	}
 
 	public <T> T getChainReqData(String chainId) {
-		return (T) metaDataMap.get(CHAIN_REQ_PREFIX + chainId);
+		String key = CHAIN_REQ_PREFIX + chainId;
+		if (hasMetaData(key)){
+			Queue<Object> queue = (Queue<Object>) metaDataMap.get(key);
+			return (T)queue.poll();
+		}else{
+			return null;
+		}
 	}
 
 	public <T> void setChainReqData(String chainId, T t) {
-		putMetaDataMap(CHAIN_REQ_PREFIX + chainId, t);
+		String key = CHAIN_REQ_PREFIX + chainId;
+		if (hasMetaData(key)){
+			Queue<Object> queue = (Queue<Object>) metaDataMap.get(key);
+			queue.offer(t);
+		}else{
+			putMetaDataMap(key, new ConcurrentLinkedQueue<>(ListUtil.toList(t)));
+		}
 	}
 
 	public <T> void setPrivateDeliveryData(String nodeId, T t){

+ 14 - 1
liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/java/com/yomahub/liteflow/test/subflow/ImplicitSubFlowELDeclSpringbootTest.java

@@ -36,7 +36,7 @@ public class ImplicitSubFlowELDeclSpringbootTest extends BaseTest {
 
     //这里GCmp中隐式的调用chain4,从而执行了h,m
     @Test
-    public void testImplicitSubFlow() {
+    public void testImplicitSubFlow1() {
         LiteflowResponse response = flowExecutor.execute2Resp("chain3", "it's a request");
         DefaultContext context = response.getFirstContextBean();
         Assert.assertTrue(response.isSuccess());
@@ -49,4 +49,17 @@ public class ImplicitSubFlowELDeclSpringbootTest extends BaseTest {
         //requestData的取值正确
         Assert.assertEquals("it's implicit subflow.", context.getData("innerRequest"));
     }
+
+    //在p里多线程调用q 10次,每个q取到的参数都是不同的。
+    @Test
+    public void testImplicitSubFlow2() {
+        LiteflowResponse response = flowExecutor.execute2Resp("c1", "it's a request");
+        DefaultContext context = response.getFirstContextBean();
+        Assert.assertTrue(response.isSuccess());
+
+        Set<String> set = context.getData("test");
+
+        //requestData的取值正确
+        Assert.assertEquals(10, set.size());
+    }
 }

+ 35 - 0
liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/java/com/yomahub/liteflow/test/subflow/cmp2/PCmp.java

@@ -0,0 +1,35 @@
+package com.yomahub.liteflow.test.subflow.cmp2;
+
+import com.yomahub.liteflow.annotation.LiteflowCmpDefine;
+import com.yomahub.liteflow.annotation.LiteflowMethod;
+import com.yomahub.liteflow.core.FlowExecutor;
+import com.yomahub.liteflow.core.NodeComponent;
+import com.yomahub.liteflow.enums.LiteFlowMethodEnum;
+import com.yomahub.liteflow.flow.element.Node;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+
+@Component("p")
+@LiteflowCmpDefine
+public class PCmp{
+
+    @Autowired
+    private FlowExecutor flowExecutor;
+
+    @LiteflowMethod(LiteFlowMethodEnum.PROCESS)
+    public void process(NodeComponent bindCmp) throws Exception {
+        int slotIndex = bindCmp.getSlotIndex();
+        for (int i = 0; i < 10; i++) {
+            int finalI = i;
+            new Thread(() -> {
+                try {
+                    flowExecutor.invoke("c2", "it's implicit subflow " + finalI, slotIndex);
+                } catch (Exception e) {
+                    throw new RuntimeException(e);
+                }
+            }).start();
+        }
+        Thread.sleep(1000);
+    }
+}

+ 33 - 0
liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/java/com/yomahub/liteflow/test/subflow/cmp2/QCmp.java

@@ -0,0 +1,33 @@
+package com.yomahub.liteflow.test.subflow.cmp2;
+
+import com.yomahub.liteflow.annotation.LiteflowCmpDefine;
+import com.yomahub.liteflow.annotation.LiteflowMethod;
+import com.yomahub.liteflow.core.NodeComponent;
+import com.yomahub.liteflow.enums.LiteFlowMethodEnum;
+import com.yomahub.liteflow.slot.DefaultContext;
+import org.springframework.stereotype.Component;
+
+import java.util.HashSet;
+import java.util.Set;
+
+
+@Component("q")
+@LiteflowCmpDefine
+public class QCmp{
+    @LiteflowMethod(LiteFlowMethodEnum.PROCESS)
+    public void process(NodeComponent bindCmp) throws Exception {
+        String requestData = bindCmp.getSubChainReqData();
+        DefaultContext context = bindCmp.getFirstContextBean();
+
+        synchronized (QCmp.class){
+            if (context.hasData("test")){
+                Set<String> set = context.getData("test");
+                set.add(requestData);
+            }else{
+                Set<String> set = new HashSet<>();
+                set.add(requestData);
+                context.setData("test", set);
+            }
+        }
+    }
+}

+ 8 - 0
liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/resources/subflow/flow-implicit.el.xml

@@ -7,4 +7,12 @@
     <chain name="chain4">
         THEN(h, m);
     </chain>
+
+    <chain name="c1">
+        THEN(p);
+    </chain>
+
+    <chain name="c2">
+        THEN(q);
+    </chain>
 </flow>

+ 14 - 1
liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/java/com/yomahub/liteflow/test/subflow/ImplicitSubFlowTest.java

@@ -34,7 +34,7 @@ public class ImplicitSubFlowTest extends BaseTest {
 
     //这里GCmp中隐式的调用chain4,从而执行了h,m
     @Test
-    public void testImplicitSubFlow() {
+    public void testImplicitSubFlow1() {
         LiteflowResponse response = flowExecutor.execute2Resp("chain3", "it's a request");
         DefaultContext context = response.getFirstContextBean();
         Assert.assertTrue(response.isSuccess());
@@ -47,4 +47,17 @@ public class ImplicitSubFlowTest extends BaseTest {
         //requestData的取值正确
         Assert.assertEquals("it's implicit subflow.", context.getData("innerRequest"));
     }
+
+    //在p里多线程调用q 10次,每个q取到的参数都是不同的。
+    @Test
+    public void testImplicitSubFlow2() {
+        LiteflowResponse response = flowExecutor.execute2Resp("c1", "it's a request");
+        DefaultContext context = response.getFirstContextBean();
+        Assert.assertTrue(response.isSuccess());
+
+        Set<String> set = context.getData("test");
+
+        //requestData的取值正确
+        Assert.assertEquals(10, set.size());
+    }
 }

+ 27 - 0
liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/java/com/yomahub/liteflow/test/subflow/cmp2/PCmp.java

@@ -0,0 +1,27 @@
+package com.yomahub.liteflow.test.subflow.cmp2;
+
+import com.yomahub.liteflow.core.FlowExecutor;
+import com.yomahub.liteflow.core.FlowExecutorHolder;
+import com.yomahub.liteflow.core.NodeComponent;
+
+
+public class PCmp extends NodeComponent {
+
+    private FlowExecutor flowExecutor = FlowExecutorHolder.loadInstance();
+
+    @Override
+    public void process() throws Exception {
+        int slotIndex = this.getSlotIndex();
+        for (int i = 0; i < 10; i++) {
+            int finalI = i;
+            new Thread(() -> {
+                try {
+                    flowExecutor.invoke("c2", "it's implicit subflow " + finalI, slotIndex);
+                } catch (Exception e) {
+                    throw new RuntimeException(e);
+                }
+            }).start();
+        }
+        Thread.sleep(1000);
+    }
+}

+ 27 - 0
liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/java/com/yomahub/liteflow/test/subflow/cmp2/QCmp.java

@@ -0,0 +1,27 @@
+package com.yomahub.liteflow.test.subflow.cmp2;
+
+import com.yomahub.liteflow.core.NodeComponent;
+import com.yomahub.liteflow.slot.DefaultContext;
+
+import java.util.HashSet;
+import java.util.Set;
+
+
+public class QCmp extends NodeComponent {
+    @Override
+    public void process() throws Exception {
+        String requestData = this.getSubChainReqData();
+        DefaultContext context = this.getFirstContextBean();
+
+        synchronized (QCmp.class){
+            if (context.hasData("test")){
+                Set<String> set = context.getData("test");
+                set.add(requestData);
+            }else{
+                Set<String> set = new HashSet<>();
+                set.add(requestData);
+                context.setData("test", set);
+            }
+        }
+    }
+}

+ 11 - 0
liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/resources/subflow/flow-implicit.el.xml

@@ -5,7 +5,10 @@
         <node id="g" class="com.yomahub.liteflow.test.subflow.cmp2.GCmp"/>
         <node id="h" class="com.yomahub.liteflow.test.subflow.cmp2.HCmp"/>
         <node id="m" class="com.yomahub.liteflow.test.subflow.cmp2.MCmp"/>
+        <node id="p" class="com.yomahub.liteflow.test.subflow.cmp2.PCmp"/>
+        <node id="q" class="com.yomahub.liteflow.test.subflow.cmp2.QCmp"/>
     </nodes>
+
     <chain name="chain3">
         THEN(f, g);
     </chain>
@@ -13,4 +16,12 @@
     <chain name="chain4">
         THEN(h, m);
     </chain>
+
+    <chain name="c1">
+        THEN(p);
+    </chain>
+
+    <chain name="c2">
+        THEN(q);
+    </chain>
 </flow>

+ 14 - 1
liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/subflow/ImplicitSubFlowELSpringbootTest.java

@@ -36,7 +36,7 @@ public class ImplicitSubFlowELSpringbootTest extends BaseTest {
 
     //这里GCmp中隐式的调用chain4,从而执行了h,m
     @Test
-    public void testImplicitSubFlow() {
+    public void testImplicitSubFlow1() {
         LiteflowResponse response = flowExecutor.execute2Resp("chain3", "it's a request");
         DefaultContext context = response.getFirstContextBean();
         Assert.assertTrue(response.isSuccess());
@@ -49,4 +49,17 @@ public class ImplicitSubFlowELSpringbootTest extends BaseTest {
         //requestData的取值正确
         Assert.assertEquals("it's implicit subflow.", context.getData("innerRequest"));
     }
+
+    //在p里多线程调用q 10次,每个q取到的参数都是不同的。
+    @Test
+    public void testImplicitSubFlow2() {
+        LiteflowResponse response = flowExecutor.execute2Resp("c1", "it's a request");
+        DefaultContext context = response.getFirstContextBean();
+        Assert.assertTrue(response.isSuccess());
+
+        Set<String> set = context.getData("test");
+
+        //requestData的取值正确
+        Assert.assertEquals(10, set.size());
+    }
 }

+ 32 - 0
liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/subflow/cmp2/PCmp.java

@@ -0,0 +1,32 @@
+package com.yomahub.liteflow.test.subflow.cmp2;
+
+import com.yomahub.liteflow.core.FlowExecutor;
+import com.yomahub.liteflow.core.NodeComponent;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import static com.yomahub.liteflow.test.subflow.ImplicitSubFlowELSpringbootTest.RUN_TIME_SLOT;
+
+
+@Component("p")
+public class PCmp extends NodeComponent {
+
+    @Autowired
+    private FlowExecutor flowExecutor;
+
+    @Override
+    public void process() throws Exception {
+        int slotIndex = this.getSlotIndex();
+        for (int i = 0; i < 10; i++) {
+            int finalI = i;
+            new Thread(() -> {
+                try {
+                    flowExecutor.invoke("c2", "it's implicit subflow " + finalI, slotIndex);
+                } catch (Exception e) {
+                    throw new RuntimeException(e);
+                }
+            }).start();
+        }
+        Thread.sleep(1000);
+    }
+}

+ 31 - 0
liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/subflow/cmp2/QCmp.java

@@ -0,0 +1,31 @@
+package com.yomahub.liteflow.test.subflow.cmp2;
+
+import com.yomahub.liteflow.core.NodeComponent;
+import com.yomahub.liteflow.slot.DefaultContext;
+import org.springframework.stereotype.Component;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import static com.yomahub.liteflow.test.subflow.ImplicitSubFlowELSpringbootTest.RUN_TIME_SLOT;
+
+
+@Component("q")
+public class QCmp extends NodeComponent {
+    @Override
+    public void process() throws Exception {
+        String requestData = this.getSubChainReqData();
+        DefaultContext context = this.getFirstContextBean();
+
+        synchronized (QCmp.class){
+            if (context.hasData("test")){
+                Set<String> set = context.getData("test");
+                set.add(requestData);
+            }else{
+                Set<String> set = new HashSet<>();
+                set.add(requestData);
+                context.setData("test", set);
+            }
+        }
+    }
+}

+ 8 - 0
liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/subflow/flow-implicit.el.xml

@@ -7,4 +7,12 @@
     <chain name="chain4">
         THEN(h, m);
     </chain>
+
+    <chain name="c1">
+        THEN(p);
+    </chain>
+
+    <chain name="c2">
+        THEN(q);
+    </chain>
 </flow>

+ 14 - 1
liteflow-testcase-el/liteflow-testcase-el-springnative/src/test/java/com/yomahub/liteflow/test/subflow/ImplicitSubFlowELSpringTest.java

@@ -30,7 +30,7 @@ public class ImplicitSubFlowELSpringTest extends BaseTest {
 
     //这里GCmp中隐式的调用chain4,从而执行了h,m
     @Test
-    public void testImplicitSubFlow() {
+    public void testImplicitSubFlow1() {
         LiteflowResponse response = flowExecutor.execute2Resp("chain3", "it's a request");
         DefaultContext context = response.getFirstContextBean();
         Assert.assertTrue(response.isSuccess());
@@ -43,4 +43,17 @@ public class ImplicitSubFlowELSpringTest extends BaseTest {
         //requestData的取值正确
         Assert.assertEquals("it's implicit subflow.", context.getData("innerRequest"));
     }
+
+    //在p里多线程调用q 10次,每个q取到的参数都是不同的。
+    @Test
+    public void testImplicitSubFlow2() {
+        LiteflowResponse response = flowExecutor.execute2Resp("c1", "it's a request");
+        DefaultContext context = response.getFirstContextBean();
+        Assert.assertTrue(response.isSuccess());
+
+        Set<String> set = context.getData("test");
+
+        //requestData的取值正确
+        Assert.assertEquals(10, set.size());
+    }
 }

+ 30 - 0
liteflow-testcase-el/liteflow-testcase-el-springnative/src/test/java/com/yomahub/liteflow/test/subflow/cmp2/PCmp.java

@@ -0,0 +1,30 @@
+package com.yomahub.liteflow.test.subflow.cmp2;
+
+import com.yomahub.liteflow.core.FlowExecutor;
+import com.yomahub.liteflow.core.NodeComponent;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+
+@Component("p")
+public class PCmp extends NodeComponent {
+
+    @Autowired
+    private FlowExecutor flowExecutor;
+
+    @Override
+    public void process() throws Exception {
+        int slotIndex = this.getSlotIndex();
+        for (int i = 0; i < 10; i++) {
+            int finalI = i;
+            new Thread(() -> {
+                try {
+                    flowExecutor.invoke("c2", "it's implicit subflow " + finalI, slotIndex);
+                } catch (Exception e) {
+                    throw new RuntimeException(e);
+                }
+            }).start();
+        }
+        Thread.sleep(1000);
+    }
+}

+ 29 - 0
liteflow-testcase-el/liteflow-testcase-el-springnative/src/test/java/com/yomahub/liteflow/test/subflow/cmp2/QCmp.java

@@ -0,0 +1,29 @@
+package com.yomahub.liteflow.test.subflow.cmp2;
+
+import com.yomahub.liteflow.core.NodeComponent;
+import com.yomahub.liteflow.slot.DefaultContext;
+import org.springframework.stereotype.Component;
+
+import java.util.HashSet;
+import java.util.Set;
+
+
+@Component("q")
+public class QCmp extends NodeComponent {
+    @Override
+    public void process() throws Exception {
+        String requestData = this.getSubChainReqData();
+        DefaultContext context = this.getFirstContextBean();
+
+        synchronized (QCmp.class){
+            if (context.hasData("test")){
+                Set<String> set = context.getData("test");
+                set.add(requestData);
+            }else{
+                Set<String> set = new HashSet<>();
+                set.add(requestData);
+                context.setData("test", set);
+            }
+        }
+    }
+}

+ 8 - 0
liteflow-testcase-el/liteflow-testcase-el-springnative/src/test/resources/subflow/flow-implicit.el.xml

@@ -7,4 +7,12 @@
     <chain name="chain4">
         THEN(h, m)
     </chain>
+
+    <chain name="c1">
+        THEN(p);
+    </chain>
+
+    <chain name="c2">
+        THEN(q);
+    </chain>
 </flow>