enhancement #ICANTH 去除隐式子流程特性

This commit is contained in:
everywhere.z
2025-05-26 20:33:41 +08:00
parent e695648728
commit cc7ca69450
217 changed files with 337 additions and 4143 deletions

View File

@@ -1,63 +0,0 @@
package com.yomahub.liteflow.test.subflow;
import com.yomahub.liteflow.core.FlowExecutor;
import com.yomahub.liteflow.core.FlowExecutorHolder;
import com.yomahub.liteflow.flow.LiteflowResponse;
import com.yomahub.liteflow.property.LiteflowConfig;
import com.yomahub.liteflow.slot.DefaultContext;
import com.yomahub.liteflow.test.BaseTest;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import java.util.HashSet;
import java.util.Set;
/**
* 测试隐式调用子流程 单元测试
*
* @author justin.xu
*/
public class ImplicitSubFlowTest extends BaseTest {
private static FlowExecutor flowExecutor;
@BeforeAll
public static void init() {
LiteflowConfig config = new LiteflowConfig();
config.setRuleSource("subflow/flow-implicit.el.xml");
flowExecutor = FlowExecutorHolder.loadInstance(config);
}
public static final Set<String> RUN_TIME_SLOT = new HashSet<>();
// 这里GCmp中隐式的调用chain4从而执行了hm
@Test
public void testImplicitSubFlow1() {
LiteflowResponse response = flowExecutor.execute2Resp("chain3", "it's a request");
DefaultContext context = response.getFirstContextBean();
Assertions.assertTrue(response.isSuccess());
Assertions.assertEquals("f==>g==>h==>m", response.getExecuteStepStr());
// 传递了slotIndex则set的size==1
Assertions.assertEquals(1, RUN_TIME_SLOT.size());
// set中第一次设置的requestId和response中的requestId一致
Assertions.assertTrue(RUN_TIME_SLOT.contains(response.getSlot().getRequestId()));
// requestData的取值正确
Assertions.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();
Assertions.assertTrue(response.isSuccess());
Set<String> set = context.getData("test");
// requestData的取值正确
Assertions.assertEquals(10, set.size());
}
}

View File

@@ -1,48 +0,0 @@
package com.yomahub.liteflow.test.subflow;
import com.yomahub.liteflow.core.FlowExecutor;
import com.yomahub.liteflow.core.FlowExecutorHolder;
import com.yomahub.liteflow.exception.MultipleParsersException;
import com.yomahub.liteflow.flow.LiteflowResponse;
import com.yomahub.liteflow.property.LiteflowConfig;
import com.yomahub.liteflow.property.LiteflowConfigGetter;
import com.yomahub.liteflow.test.BaseTest;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
/**
* 测试主流程与子流程在不同的配置文件的场景
*
* @author Bryan.Zhang
*/
public class SubflowInDifferentConfigTest extends BaseTest {
private static FlowExecutor flowExecutor;
@BeforeAll
public static void init() {
LiteflowConfig config = new LiteflowConfig();
config.setRuleSource("subflow/flow-main.el.xml,subflow/flow-sub1.el.xml,subflow/flow-sub2.el.xml");
flowExecutor = FlowExecutorHolder.loadInstance(config);
}
// 是否按照流程定义配置执行
@Test
public void testExplicitSubFlow1() {
LiteflowResponse response = flowExecutor.execute2Resp("chain1", "it's a request");
Assertions.assertTrue(response.isSuccess());
Assertions.assertEquals("a==>b==>b==>a==>e==>d", response.getExecuteStepStr());
}
// 主要测试有不同的配置类型后会不会报出既定的错误
@Test
public void testExplicitSubFlow2() {
Assertions.assertThrows(MultipleParsersException.class, () -> {
LiteflowConfig config = LiteflowConfigGetter.get();
config.setRuleSource("subflow/flow-main.xml,subflow/flow-sub1.xml,subflow/flow-sub2.yml");
flowExecutor.reloadRule();
});
}
}

View File

@@ -1,36 +0,0 @@
package com.yomahub.liteflow.test.subflow;
import com.yomahub.liteflow.core.FlowExecutor;
import com.yomahub.liteflow.core.FlowExecutorHolder;
import com.yomahub.liteflow.flow.LiteflowResponse;
import com.yomahub.liteflow.property.LiteflowConfig;
import com.yomahub.liteflow.test.BaseTest;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
/**
* 测试显示调用子流程(json) 单元测试
*
* @author justin.xu
*/
public class SubflowJsonTest extends BaseTest {
private static FlowExecutor flowExecutor;
@BeforeAll
public static void init() {
LiteflowConfig config = new LiteflowConfig();
config.setRuleSource("subflow/flow.el.json");
flowExecutor = FlowExecutorHolder.loadInstance(config);
}
// 是否按照流程定义配置执行
@Test
public void testExplicitSubFlow() {
LiteflowResponse response = flowExecutor.execute2Resp("chain1", "it's a request");
Assertions.assertTrue(response.isSuccess());
Assertions.assertEquals("a==>b==>c==>b==>a==>e==>d", response.getExecuteStepStr());
}
}

View File

@@ -1,36 +0,0 @@
package com.yomahub.liteflow.test.subflow;
import com.yomahub.liteflow.core.FlowExecutor;
import com.yomahub.liteflow.core.FlowExecutorHolder;
import com.yomahub.liteflow.flow.LiteflowResponse;
import com.yomahub.liteflow.property.LiteflowConfig;
import com.yomahub.liteflow.test.BaseTest;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
/**
* 测试显示调用子流程(xml) 单元测试
*
* @author justin.xu
*/
public class SubflowXMLTest extends BaseTest {
private static FlowExecutor flowExecutor;
@BeforeAll
public static void init() {
LiteflowConfig config = new LiteflowConfig();
config.setRuleSource("subflow/flow.el.xml");
flowExecutor = FlowExecutorHolder.loadInstance(config);
}
// 是否按照流程定义配置执行
@Test
public void testExplicitSubFlow() {
LiteflowResponse response = flowExecutor.execute2Resp("chain1", "it's a request");
Assertions.assertTrue(response.isSuccess());
Assertions.assertEquals("a==>b==>c==>b==>a==>e==>d", response.getExecuteStepStr());
}
}

View File

@@ -1,36 +0,0 @@
package com.yomahub.liteflow.test.subflow;
import com.yomahub.liteflow.core.FlowExecutor;
import com.yomahub.liteflow.core.FlowExecutorHolder;
import com.yomahub.liteflow.flow.LiteflowResponse;
import com.yomahub.liteflow.property.LiteflowConfig;
import com.yomahub.liteflow.test.BaseTest;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
/**
* 测试显示调用子流程(yml) 单元测试
*
* @author justin.xu
*/
public class SubflowYmlTest extends BaseTest {
private static FlowExecutor flowExecutor;
@BeforeAll
public static void init() {
LiteflowConfig config = new LiteflowConfig();
config.setRuleSource("subflow/flow.el.yml");
flowExecutor = FlowExecutorHolder.loadInstance(config);
}
// 是否按照流程定义配置执行
@Test
public void testExplicitSubFlowYml() {
LiteflowResponse response = flowExecutor.execute2Resp("chain1", "it's a request");
Assertions.assertTrue(response.isSuccess());
Assertions.assertEquals("a==>b==>c==>b==>a==>e==>d", response.getExecuteStepStr());
}
}

View File

@@ -1,12 +0,0 @@
package com.yomahub.liteflow.test.subflow.cmp1;
import com.yomahub.liteflow.core.NodeComponent;
public class ACmp extends NodeComponent {
@Override
public void process() {
System.out.println("Acomp executed!");
}
}

View File

@@ -1,12 +0,0 @@
package com.yomahub.liteflow.test.subflow.cmp1;
import com.yomahub.liteflow.core.NodeComponent;
public class BCmp extends NodeComponent {
@Override
public void process() {
System.out.println("Bcomp executed!");
}
}

View File

@@ -1,12 +0,0 @@
package com.yomahub.liteflow.test.subflow.cmp1;
import com.yomahub.liteflow.core.NodeComponent;
public class CCmp extends NodeComponent {
@Override
public void process() throws Exception {
System.out.println("Ccomp executed!");
}
}

View File

@@ -1,12 +0,0 @@
package com.yomahub.liteflow.test.subflow.cmp1;
import com.yomahub.liteflow.core.NodeComponent;
public class DCmp extends NodeComponent {
@Override
public void process() throws Exception {
System.out.println("Dcomp executed!");
}
}

View File

@@ -1,12 +0,0 @@
package com.yomahub.liteflow.test.subflow.cmp1;
import com.yomahub.liteflow.core.NodeComponent;
public class ECmp extends NodeComponent {
@Override
public void process() throws Exception {
System.out.println("Ecomp executed!");
}
}

View File

@@ -1,17 +0,0 @@
package com.yomahub.liteflow.test.subflow.cmp2;
import com.yomahub.liteflow.core.NodeComponent;
import static com.yomahub.liteflow.test.subflow.ImplicitSubFlowTest.RUN_TIME_SLOT;
public class FCmp extends NodeComponent {
@Override
public void process() throws Exception {
RUN_TIME_SLOT.add(this.getSlot().getRequestId());
System.out.println("Fcomp executed!");
}
}

View File

@@ -1,19 +0,0 @@
package com.yomahub.liteflow.test.subflow.cmp2;
import com.yomahub.liteflow.core.NodeComponent;
import static com.yomahub.liteflow.test.subflow.ImplicitSubFlowTest.RUN_TIME_SLOT;
public class GCmp extends NodeComponent {
@Override
public void process() throws Exception {
RUN_TIME_SLOT.add(this.getSlot().getRequestId());
System.out.println("Gcmp executed!");
this.invoke("chain4", "it's implicit subflow.");
}
}

View File

@@ -1,21 +0,0 @@
package com.yomahub.liteflow.test.subflow.cmp2;
import com.yomahub.liteflow.core.NodeComponent;
import com.yomahub.liteflow.slot.DefaultContext;
import static com.yomahub.liteflow.test.subflow.ImplicitSubFlowTest.RUN_TIME_SLOT;
public class HCmp extends NodeComponent {
@Override
public void process() throws Exception {
String requestData = this.getSubChainReqData();
DefaultContext context = this.getFirstContextBean();
context.setData("innerRequest", requestData);
RUN_TIME_SLOT.add(this.getSlot().getRequestId());
System.out.println("Hcomp executed!");
}
}

View File

@@ -1,17 +0,0 @@
package com.yomahub.liteflow.test.subflow.cmp2;
import com.yomahub.liteflow.core.NodeComponent;
import static com.yomahub.liteflow.test.subflow.ImplicitSubFlowTest.RUN_TIME_SLOT;
public class MCmp extends NodeComponent {
@Override
public void process() throws Exception {
RUN_TIME_SLOT.add(this.getSlot().getRequestId());
System.out.println("Mcomp executed!");
}
}

View File

@@ -1,28 +0,0 @@
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.invokeInAsync("c2", "it's implicit subflow " + finalI, slotIndex);
}
catch (Exception e) {
throw new RuntimeException(e);
}
}).start();
}
Thread.sleep(1000);
}
}

View File

@@ -1,29 +0,0 @@
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.getSubChainReqDataInAsync();
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);
}
}
}
}

View File

@@ -1,27 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<flow>
<nodes>
<node id="f" class="com.yomahub.liteflow.test.subflow.cmp2.FCmp"/>
<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>
<chain name="chain4">
THEN(h, m);
</chain>
<chain name="c1">
THEN(p);
</chain>
<chain name="c2">
THEN(q);
</chain>
</flow>

View File

@@ -1,17 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<flow>
<nodes>
<node id="a" class="com.yomahub.liteflow.test.subflow.cmp1.ACmp"/>
<node id="b" class="com.yomahub.liteflow.test.subflow.cmp1.BCmp"/>
<node id="c" class="com.yomahub.liteflow.test.subflow.cmp1.CCmp"/>
<node id="d" class="com.yomahub.liteflow.test.subflow.cmp1.DCmp"/>
<node id="e" class="com.yomahub.liteflow.test.subflow.cmp1.ECmp"/>
<node id="f" class="com.yomahub.liteflow.test.subflow.cmp2.FCmp"/>
<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"/>
</nodes>
<chain name="chain1">
THEN(a, b, chain2);
</chain>
</flow>

View File

@@ -1,6 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<flow>
<chain name="chain2">
THEN(b, a, chain3);
</chain>
</flow>

View File

@@ -1,6 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<flow>
<chain name="chain3">
THEN(e, d);
</chain>
</flow>

View File

@@ -1,4 +0,0 @@
flow:
chain:
- name: chain3
value: "THEN(e, d);"

View File

@@ -1,62 +0,0 @@
{
"flow": {
"nodes": {
"node": [
{
"id": "a",
"class": "com.yomahub.liteflow.test.subflow.cmp1.ACmp"
},
{
"id": "b",
"class": "com.yomahub.liteflow.test.subflow.cmp1.BCmp"
},
{
"id": "c",
"class": "com.yomahub.liteflow.test.subflow.cmp1.CCmp"
},
{
"id": "d",
"class": "com.yomahub.liteflow.test.subflow.cmp1.DCmp"
},
{
"id": "e",
"class": "com.yomahub.liteflow.test.subflow.cmp1.ECmp"
},
{
"id": "f",
"class": "com.yomahub.liteflow.test.subflow.cmp2.FCmp"
},
{
"id": "g",
"class": "com.yomahub.liteflow.test.subflow.cmp2.GCmp"
},
{
"id": "h",
"class": "com.yomahub.liteflow.test.subflow.cmp2.HCmp"
},
{
"id": "M",
"class": "com.yomahub.liteflow.test.subflow.cmp2.MCmp"
}
]
},
"chain": [
{
"name": "chain3",
"value": "THEN(e,d);"
},
{
"name": "chain2",
"value": "THEN(b, a, chain3);"
},
{
"name": "chain1",
"value": "THEN(a, b, c, chain2);"
},
{
"name": "c",
"value": "THEN(d, e);"
}
]
}
}

View File

@@ -1,29 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<flow>
<nodes>
<node id="a" class="com.yomahub.liteflow.test.subflow.cmp1.ACmp"/>
<node id="b" class="com.yomahub.liteflow.test.subflow.cmp1.BCmp"/>
<node id="c" class="com.yomahub.liteflow.test.subflow.cmp1.CCmp"/>
<node id="d" class="com.yomahub.liteflow.test.subflow.cmp1.DCmp"/>
<node id="e" class="com.yomahub.liteflow.test.subflow.cmp1.ECmp"/>
<node id="f" class="com.yomahub.liteflow.test.subflow.cmp2.FCmp"/>
<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"/>
</nodes>
<chain name="chain1">
THEN(a, b, c, chain2);
</chain>
<chain name="c">
THEN(d, e);
</chain>
<chain name="chain2">
THEN(b, a, chain3);
</chain>
<chain name="chain3">
THEN(e, d);
</chain>
</flow>

View File

@@ -1,30 +0,0 @@
flow:
nodes:
node:
- id: a
class: com.yomahub.liteflow.test.subflow.cmp1.ACmp
- id: b
class: com.yomahub.liteflow.test.subflow.cmp1.BCmp
- id: c
class: com.yomahub.liteflow.test.subflow.cmp1.CCmp
- id: d
class: com.yomahub.liteflow.test.subflow.cmp1.DCmp
- id: e
class: com.yomahub.liteflow.test.subflow.cmp1.ECmp
- id: f
class: com.yomahub.liteflow.test.subflow.cmp2.FCmp
- id: g
class: com.yomahub.liteflow.test.subflow.cmp2.GCmp
- id: h
class: com.yomahub.liteflow.test.subflow.cmp2.HCmp
- id: h
class: com.yomahub.liteflow.test.subflow.cmp2.MCmp
chain:
- name: chain3
value: "THEN(e, d);"
- name: chain1
value: "THEN(a, b, c, chain2);"
- name: c
value: "THEN(d, e);"
- name: chain2
value: "THEN(b, a, chain3);"