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,67 +0,0 @@
package com.yomahub.liteflow.test.subflow;
import com.yomahub.liteflow.core.FlowExecutor;
import com.yomahub.liteflow.flow.LiteflowResponse;
import com.yomahub.liteflow.slot.DefaultContext;
import com.yomahub.liteflow.test.BaseTest;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.noear.solon.annotation.Import;
import org.noear.solon.annotation.Inject;
import org.noear.solon.test.SolonTest;
import java.util.HashSet;
import java.util.Set;
/**
* 测试隐式调用子流程 单元测试
*
* @author justin.xu
*/
@SolonTest
@Import(profiles="classpath:/subflow/application-implicit.properties")
public class ImplicitSubFlowELSpringbootTest extends BaseTest {
@Inject
private FlowExecutor flowExecutor;
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());
}
@Test
public void testImplicitSubFlow3() {
LiteflowResponse response = flowExecutor.execute2Resp("chain_r", "it's a request");
Assertions.assertTrue(response.isSuccess());
}
}

View File

@@ -1,49 +0,0 @@
package com.yomahub.liteflow.test.subflow;
import com.yomahub.liteflow.core.FlowExecutor;
import com.yomahub.liteflow.exception.MultipleParsersException;
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.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.noear.solon.annotation.Import;
import org.noear.solon.annotation.Inject;
import org.noear.solon.core.AppContext;
import org.noear.solon.test.SolonTest;
/**
* 测试主流程与子流程在不同的配置文件的场景
*
* @author Bryan.Zhang
*/
@SolonTest
@Import(profiles = "classpath:/subflow/application-subInDifferentConfig1.properties")
public class SubflowInDifferentConfigELSpringbootTest extends BaseTest {
@Inject
private FlowExecutor flowExecutor;
// 是否按照流程定义配置执行
@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());
}
@Inject
private AppContext context;
// 主要测试有不同的配置类型后会不会报出既定的错误
@Test
public void testExplicitSubFlow2() {
Assertions.assertThrows(MultipleParsersException.class, () -> {
LiteflowConfig config = context.getBean(LiteflowConfig.class);
config.setRuleSource("subflow/flow-main.el.xml,subflow/flow-sub1.el.xml,subflow/flow-sub2.el.yml");
flowExecutor.reloadRule();
});
}
}

View File

@@ -1,33 +0,0 @@
package com.yomahub.liteflow.test.subflow;
import com.yomahub.liteflow.core.FlowExecutor;
import com.yomahub.liteflow.flow.LiteflowResponse;
import com.yomahub.liteflow.test.BaseTest;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.noear.solon.annotation.Import;
import org.noear.solon.annotation.Inject;
import org.noear.solon.test.SolonTest;
/**
* 测试显示调用子流程(xml) 单元测试
*
* @author justin.xu
*/
@SolonTest
@Import(profiles ="classpath:/subflow/application-xml.properties")
public class SubflowXMLELSpringBootTest extends BaseTest {
@Inject
private FlowExecutor flowExecutor;
// 是否按照流程定义配置执行
@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,33 +0,0 @@
package com.yomahub.liteflow.test.subflow;
import com.yomahub.liteflow.core.FlowExecutor;
import com.yomahub.liteflow.flow.LiteflowResponse;
import com.yomahub.liteflow.test.BaseTest;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.noear.solon.annotation.Import;
import org.noear.solon.annotation.Inject;
import org.noear.solon.test.SolonTest;
/**
* 测试显示调用子流程(yml) 单元测试
*
* @author justin.xu
*/
@SolonTest
@Import(profiles ="classpath:/subflow/application-yml.properties")
public class SubflowYmlELSpringBootTest extends BaseTest {
@Inject
private FlowExecutor flowExecutor;
// 是否按照流程定义配置执行
@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,14 +0,0 @@
package com.yomahub.liteflow.test.subflow.cmp1;
import com.yomahub.liteflow.core.NodeComponent;
import org.noear.solon.annotation.Component;
@Component("a")
public class ACmp extends NodeComponent {
@Override
public void process() {
System.out.println("Acomp executed!");
}
}

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,23 +0,0 @@
package com.yomahub.liteflow.test.subflow.cmp2;
import com.yomahub.liteflow.core.NodeComponent;
import com.yomahub.liteflow.slot.DefaultContext;
import org.noear.solon.annotation.Component;
import static com.yomahub.liteflow.test.subflow.ImplicitSubFlowELSpringbootTest.RUN_TIME_SLOT;
@Component("f")
public class FCmp extends NodeComponent {
@Override
public void process() throws Exception {
RUN_TIME_SLOT.add(this.getSlot().getRequestId());
DefaultContext context = this.getFirstContextBean();
context.setData("innerRequestData", "inner request");
System.out.println("Fcomp executed!");
}
}

View File

@@ -1,26 +0,0 @@
package com.yomahub.liteflow.test.subflow.cmp2;
import com.yomahub.liteflow.core.FlowExecutor;
import com.yomahub.liteflow.core.NodeComponent;
import org.noear.solon.annotation.Component;
import org.noear.solon.annotation.Inject;
import static com.yomahub.liteflow.test.subflow.ImplicitSubFlowELSpringbootTest.RUN_TIME_SLOT;
@Component("g")
public class GCmp extends NodeComponent {
@Inject
private FlowExecutor flowExecutor;
@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,23 +0,0 @@
package com.yomahub.liteflow.test.subflow.cmp2;
import com.yomahub.liteflow.core.NodeComponent;
import com.yomahub.liteflow.slot.DefaultContext;
import org.noear.solon.annotation.Component;
import static com.yomahub.liteflow.test.subflow.ImplicitSubFlowELSpringbootTest.RUN_TIME_SLOT;
@Component("h")
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,19 +0,0 @@
package com.yomahub.liteflow.test.subflow.cmp2;
import com.yomahub.liteflow.core.NodeComponent;
import org.noear.solon.annotation.Component;
import static com.yomahub.liteflow.test.subflow.ImplicitSubFlowELSpringbootTest.RUN_TIME_SLOT;
@Component("m")
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,25 +0,0 @@
package com.yomahub.liteflow.test.subflow.cmp2;
import com.yomahub.liteflow.core.FlowExecutor;
import com.yomahub.liteflow.core.NodeComponent;
import org.noear.solon.annotation.Component;
import org.noear.solon.annotation.Inject;
@Component("p")
public class PCmp extends NodeComponent {
@Inject
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(() -> flowExecutor.invoke2RespInAsync("c2", "it's implicit subflow " + finalI, slotIndex))
.start();
}
Thread.sleep(1000);
}
}

View File

@@ -1,33 +0,0 @@
package com.yomahub.liteflow.test.subflow.cmp2;
import com.yomahub.liteflow.core.NodeComponent;
import com.yomahub.liteflow.slot.DefaultContext;
import org.noear.solon.annotation.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.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,14 +0,0 @@
package com.yomahub.liteflow.test.subflow.cmp2;
import com.yomahub.liteflow.annotation.LiteflowComponent;
import com.yomahub.liteflow.core.NodeComponent;
@LiteflowComponent("r")
public class R extends NodeComponent {
@Override
public void process() throws Exception {
this.invoke2Resp("chain_s", "");
}
}

View File

@@ -1,14 +0,0 @@
package com.yomahub.liteflow.test.subflow.cmp2;
import com.yomahub.liteflow.annotation.LiteflowComponent;
import com.yomahub.liteflow.core.NodeComponent;
@LiteflowComponent("s")
public class S extends NodeComponent {
@Override
public void process() throws Exception {
throw new RuntimeException("test");
}
}

View File

@@ -1,33 +0,0 @@
package com.yomahub.liteflow.test.subflow2;
import com.yomahub.liteflow.core.FlowExecutor;
import com.yomahub.liteflow.flow.LiteflowResponse;
import com.yomahub.liteflow.test.BaseTest;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.noear.solon.annotation.Import;
import org.noear.solon.annotation.Inject;
import org.noear.solon.test.SolonTest;
/**
* 测试显示调用子流程(json) 单元测试
*
* @author justin.xu
*/
@SolonTest
@Import(profiles ="classpath:/subflow/application-json.properties")
public class SubflowJsonELSpringBootTest extends BaseTest {
@Inject
private FlowExecutor flowExecutor;
// 是否按照流程定义配置执行
@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,14 +0,0 @@
package com.yomahub.liteflow.test.subflow2.cmp1;
import com.yomahub.liteflow.core.NodeComponent;
import org.noear.solon.annotation.Component;
@Component("a")
public class ACmp extends NodeComponent {
@Override
public void process() {
System.out.println("Acomp executed!");
}
}

View File

@@ -1,14 +0,0 @@
package com.yomahub.liteflow.test.subflow2.cmp1;
import com.yomahub.liteflow.core.NodeComponent;
import org.noear.solon.annotation.Component;
@Component("b")
public class BCmp extends NodeComponent {
@Override
public void process() {
System.out.println("Bcomp executed!");
}
}

View File

@@ -1,14 +0,0 @@
package com.yomahub.liteflow.test.subflow2.cmp1;
import com.yomahub.liteflow.core.NodeComponent;
import org.noear.solon.annotation.Component;
@Component("c")
public class CCmp extends NodeComponent {
@Override
public void process() throws Exception {
System.out.println("Ccomp executed!");
}
}

View File

@@ -1,14 +0,0 @@
package com.yomahub.liteflow.test.subflow2.cmp1;
import com.yomahub.liteflow.core.NodeComponent;
import org.noear.solon.annotation.Component;
@Component("d")
public class DCmp extends NodeComponent {
@Override
public void process() throws Exception {
System.out.println("Dcomp executed!");
}
}

View File

@@ -1,14 +0,0 @@
package com.yomahub.liteflow.test.subflow2.cmp1;
import com.yomahub.liteflow.core.NodeComponent;
import org.noear.solon.annotation.Component;
@Component("e")
public class ECmp extends NodeComponent {
@Override
public void process() throws Exception {
System.out.println("Ecomp executed!");
}
}

View File

@@ -1 +0,0 @@
liteflow.rule-source=subflow/flow-implicit.el.xml

View File

@@ -1 +0,0 @@
liteflow.rule-source=subflow/flow.el.json

View File

@@ -1 +0,0 @@
liteflow.rule-source=subflow/flow-main.el.xml,subflow/flow-sub1.el.xml,subflow/flow-sub2.el.xml

View File

@@ -1 +0,0 @@
liteflow.rule-source=subflow/flow-main.el.xml,subflow/flow-sub1.el.xml,subflow/flow-sub2.el.yml

View File

@@ -1 +0,0 @@
liteflow.rule-source=subflow/flow.el.xml

View File

@@ -1 +0,0 @@
liteflow.rule-source=subflow/flow.el.yml

View File

@@ -1,26 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<flow>
<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>
<chain name="chain_r">
THEN(r);
</chain>
<chain name="chain_s">
THEN(s);
</chain>
</flow>

View File

@@ -1,6 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<flow>
<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,22 +0,0 @@
{
"flow": {
"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,18 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<flow>
<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,10 +0,0 @@
flow:
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);"