Merge branch 'dev' of https://gitee.com/dromara/liteFlow into issues/I5OFMU

 Conflicts:
	liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/WhenOperator.java
This commit is contained in:
tangkc 2022-09-07 11:16:24 +08:00
commit eb76825e9f
23 changed files with 208 additions and 224 deletions

View File

@ -1,31 +1,42 @@
package com.yomahub.liteflow.builder.el.operator;
import com.ql.util.express.Operator;
import com.ql.util.express.exception.QLException;
import com.yomahub.liteflow.builder.el.operator.base.BaseOperator;
import com.yomahub.liteflow.builder.el.operator.base.OperatorHelper;
import com.yomahub.liteflow.exception.ELParseException;
import com.yomahub.liteflow.flow.element.Executable;
import com.yomahub.liteflow.flow.element.condition.WhenCondition;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* EL规则中的WHEN的操作符
*
* @author Bryan.Zhang
* @since 2.8.0
*/
public class WhenOperator extends BaseOperator {
public class WhenOperator extends Operator {
@Override
public Object buildCondition(Object[] objects) throws Exception {
OperatorHelper.checkObjectSizeGtZero(objects);
private final Logger LOG = LoggerFactory.getLogger(this.getClass());
WhenCondition whenCondition = new WhenCondition();
for (Object obj : objects) {
if (obj instanceof Executable) {
whenCondition.addExecutable((Executable) obj);
} else {
throw new QLException("parameter error");
}
}
return whenCondition;
}
@Override
public WhenCondition executeInner(Object[] objects) throws Exception {
try {
if (objects.length == 0) {
throw new QLException("parameter is empty");
}
WhenCondition whenCondition = new WhenCondition();
for (Object obj : objects) {
if (obj instanceof Executable) {
whenCondition.addExecutable((Executable) obj);
} else {
throw new QLException("parameter must be executable item");
}
}
return whenCondition;
}catch (QLException e){
throw e;
}catch (Exception e){
throw new ELParseException("errors occurred in EL parsing");
}
}
}

View File

@ -163,29 +163,32 @@ public class FlowExecutor {
}
//隐式流程的调用方法
@Deprecated
public void invoke(String chainId, Object param, Integer slotIndex) throws Exception {
LiteflowResponse response = this.execute2Resp(chainId, param, null, null, slotIndex, InnerChainTypeEnum.IN_SYNC);
LiteflowResponse response = this.invoke2Resp(chainId, param, slotIndex, InnerChainTypeEnum.IN_SYNC);
if (!response.isSuccess()){
throw response.getCause();
}
}
@Deprecated
public void invokeInAsync(String chainId, Object param, Integer slotIndex) throws Exception {
LiteflowResponse response = this.invoke2Resp(chainId, param, slotIndex, InnerChainTypeEnum.IN_ASYNC);
if (!response.isSuccess()){
throw response.getCause();
}
}
public LiteflowResponse invoke2Resp(String chainId, Object param, Integer slotIndex) {
return this.execute2Resp(chainId, param, null, null, slotIndex, InnerChainTypeEnum.IN_SYNC);
}
public void invokeInAsync(String chainId, Object param, Integer slotIndex) throws Exception {
LiteflowResponse response = this.execute2Resp(chainId, param, null, null, slotIndex, InnerChainTypeEnum.IN_ASYNC);
if (!response.isSuccess()){
throw response.getCause();
}
return this.invoke2Resp(chainId, param, slotIndex, InnerChainTypeEnum.IN_SYNC);
}
public LiteflowResponse invoke2RespInAsync(String chainId, Object param, Integer slotIndex) {
return this.execute2Resp(chainId, param, null, null, slotIndex, InnerChainTypeEnum.IN_ASYNC);
return this.invoke2Resp(chainId, param, slotIndex, InnerChainTypeEnum.IN_ASYNC);
}
//单独调用某一个node
@Deprecated
public void invoke(String nodeId, Integer slotIndex) throws Exception {
Node node = FlowBus.getNode(nodeId);
node.execute(slotIndex);
@ -203,26 +206,27 @@ public class FlowExecutor {
//调用一个流程并返回LiteflowResponse允许多上下文的传入
public LiteflowResponse execute2Resp(String chainId, Object param, Class<?>... contextBeanClazzArray) {
return this.execute2Resp(chainId, param, contextBeanClazzArray, null, null, InnerChainTypeEnum.NONE);
return this.execute2Resp(chainId, param, contextBeanClazzArray, null);
}
public LiteflowResponse execute2Resp(String chainId, Object param, Object... contextBeanArray) {
return this.execute2Resp(chainId, param, null, contextBeanArray);
}
//调用一个流程并返回Future<LiteflowResponse>允许多上下文的传入
public Future<LiteflowResponse> execute2Future(String chainId, Object param, Class<?>... contextBeanClazzArray) {
return ExecutorHelper.loadInstance().buildMainExecutor(liteflowConfig.getMainExecutorClass()).submit(()
-> FlowExecutorHolder.loadInstance().execute2Resp(chainId, param, contextBeanClazzArray,null, null, InnerChainTypeEnum.NONE));
-> FlowExecutorHolder.loadInstance().execute2Resp(chainId, param, contextBeanClazzArray,null));
}
public LiteflowResponse execute2Resp(String chainId, Object param, Object... contextBeanArray) {
return this.execute2Resp(chainId, param, null, contextBeanArray, null, InnerChainTypeEnum.NONE);
}
public Future<LiteflowResponse> execute2Future(String chainId, Object param, Object... contextBeanArray) {
return ExecutorHelper.loadInstance().buildMainExecutor(liteflowConfig.getMainExecutorClass()).submit(()
-> FlowExecutorHolder.loadInstance().execute2Resp(chainId, param, null, contextBeanArray, null, InnerChainTypeEnum.NONE));
-> FlowExecutorHolder.loadInstance().execute2Resp(chainId, param, null, contextBeanArray));
}
//调用一个流程返回默认的上下文适用于简单的调用
@Deprecated
public DefaultContext execute(String chainId, Object param) throws Exception{
LiteflowResponse response = this.execute2Resp(chainId, param, DefaultContext.class);
if (!response.isSuccess()){
@ -235,10 +239,16 @@ public class FlowExecutor {
private LiteflowResponse execute2Resp(String chainId,
Object param,
Class<?>[] contextBeanClazzArray,
Object[] contextBeanArray,
Object[] contextBeanArray) {
Slot slot = doExecute(chainId, param, contextBeanClazzArray, contextBeanArray, null, InnerChainTypeEnum.NONE);
return LiteflowResponse.newMainResponse(slot);
}
private LiteflowResponse invoke2Resp(String chainId,
Object param,
Integer slotIndex, InnerChainTypeEnum innerChainType) {
Slot slot = doExecute(chainId, param, contextBeanClazzArray, contextBeanArray, slotIndex, innerChainType);
return new LiteflowResponse(slot);
Slot slot = doExecute(chainId, param, null, null, slotIndex, innerChainType);
return LiteflowResponse.newInnerResponse(chainId, slot);
}
private Slot doExecute(String chainId,
@ -251,7 +261,9 @@ public class FlowExecutor {
init();
}
//如果不是隐式流程那么需要分配Slot
if (innerChainType.equals(InnerChainTypeEnum.NONE) && ObjectUtil.isNull(slotIndex)) {
//这里可以根据class分配也可以根据bean去分配
if (ArrayUtil.isNotEmpty(contextBeanClazzArray)){
slotIndex = DataBus.offerSlotByClass(ListUtil.toList(contextBeanClazzArray));
}else{
@ -266,11 +278,20 @@ public class FlowExecutor {
throw new NoAvailableSlotException("there is no available slot");
}
Slot slot = DataBus.getSlot(slotIndex);
if (ObjectUtil.isNull(slot)) {
throw new NoAvailableSlotException(StrUtil.format("the slot[{}] is not exist", slotIndex));
}
//如果是隐式流程事先把subException给置空然后把隐式流程的chainId放入slot元数据中
//我知道这在多线程调用隐式流程中会有问题但是考虑到这种场景的不会多也有其他的转换方式
//所以暂且这么做以后再优化
if (!innerChainType.equals(InnerChainTypeEnum.NONE)){
slot.removeSubException(chainId);
slot.addSubChain(chainId);
}
if (StrUtil.isBlank(slot.getRequestId())) {
slot.generateRequestId();
if (BooleanUtil.isTrue(liteflowConfig.getPrintExecutionLog())) {
@ -318,7 +339,14 @@ public class FlowExecutor {
LOG.error(e.getMessage());
}
}
slot.setException(e);
//如果是正常流程需要把异常设置到slot的exception属性里
//如果是隐式流程则需要设置到隐式流程的exception属性里
if (innerChainType.equals(InnerChainTypeEnum.NONE)) {
slot.setException(e);
}else{
slot.setSubException(chainId, e);
}
} finally {
if (innerChainType.equals(InnerChainTypeEnum.NONE)) {
slot.printStep();

View File

@ -113,6 +113,9 @@ public abstract class NodeComponent{
}
throw e;
} finally {
//后置处理
self.afterProcess(this.getNodeId(), slot);
stopWatch.stop();
final long timeSpent = stopWatch.getTotalTimeMillis();
LOG.debug("[{}]:component[{}] finished in {} milliseconds",slot.getRequestId(),this.getDisplayName(),timeSpent);
@ -120,9 +123,6 @@ public abstract class NodeComponent{
//往CmpStep中放入时间消耗信息
cmpStep.setTimeSpent(timeSpent);
//后置处理
self.afterProcess(this.getNodeId(), slot);
// 性能统计
if (ObjectUtil.isNotNull(monitorBus)) {
CompStatistics statistics = new CompStatistics(this.getClass().getSimpleName(), timeSpent);
@ -156,7 +156,7 @@ public abstract class NodeComponent{
return true;
}
//出错是否继续执行(这个只适用于串行流程并行节点不起作用)
//出错是否继续执行(这个只适用于并行流程串行流程不起作用)
public boolean isContinueOnError() {
return false;
}

View File

@ -28,20 +28,30 @@ public class LiteflowResponse implements Serializable {
private Slot slot;
public LiteflowResponse() {
this(null);
}
public LiteflowResponse(Slot slot) {
if (slot != null && slot.getException() != null) {
this.success = false;
this.cause = slot.getException();
this.message = this.cause.getMessage();
this.code = this.cause instanceof LiteFlowException ? ((LiteFlowException)this.cause).getCode() : null;
public static LiteflowResponse newMainResponse(Slot slot){
return newResponse(slot, slot.getException());
}
public static LiteflowResponse newInnerResponse(String chainId, Slot slot){
return newResponse(slot, slot.getSubException(chainId));
}
private static LiteflowResponse newResponse(Slot slot, Exception e){
LiteflowResponse response = new LiteflowResponse();
if (slot != null && e != null) {
response.setSuccess(false);
response.setCause(e);
response.setMessage(response.getCause().getMessage());
response.setCode(response.getCause() instanceof LiteFlowException ? ((LiteFlowException)response.getCause()).getCode() : null);
} else {
this.success = true;
response.setSuccess(true);
}
this.slot = slot;
response.setSlot(slot);
return response;
}
public boolean isSuccess() {
return success;
}

View File

@ -89,7 +89,11 @@ public class Chain implements Executable {
throw e;
}catch (Exception e){
//这里事先取到exception set到slot里为了方便finally取到exception
slot.setException(e);
if (slot.isSubChain(chainName)){
slot.setSubException(chainName, e);
}else{
slot.setException(e);
}
throw e;
}finally {
//执行后置

View File

@ -11,7 +11,7 @@ import com.yomahub.liteflow.enums.ConditionTypeEnum;
import com.yomahub.liteflow.flow.element.Executable;
/**
* 置Condition
* 置Condition
* @author Bryan.Zhang
* @since 2.6.4
*/

View File

@ -7,6 +7,7 @@
*/
package com.yomahub.liteflow.slot;
import cn.hutool.core.collection.ConcurrentHashSet;
import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.util.ObjectUtil;
import com.yomahub.liteflow.exception.NoSuchContextBeanException;
@ -20,6 +21,7 @@ import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Queue;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedDeque;
import java.util.concurrent.ConcurrentLinkedQueue;
@ -54,8 +56,12 @@ public class Slot{
private static final String EXCEPTION = "_exception";
private static final String SUB_EXCEPTION_PREFIX = "_sub_exception_";
private static final String PRIVATE_DELIVERY_PREFIX = "_private_d_";
private static final String SUB_CHAIN = "_sub_chain";
private final Deque<CmpStep> executeSteps = new ConcurrentLinkedDeque<>();
private String executeStepsStr;
@ -261,6 +267,18 @@ public class Slot{
putMetaDataMap(EXCEPTION, e);
}
public Exception getSubException(String chainId) {
return (Exception) this.metaDataMap.get(SUB_EXCEPTION_PREFIX + chainId);
}
public void setSubException(String chainId, Exception e) {
putMetaDataMap(SUB_EXCEPTION_PREFIX + chainId, e);
}
public void removeSubException(String chainId){
metaDataMap.remove(SUB_EXCEPTION_PREFIX + chainId);
}
public List<Object> getContextBeanList(){
return this.contextBeanList;
}
@ -277,4 +295,19 @@ public class Slot{
Class<T> firstContextBeanClazz = (Class<T>) this.getContextBeanList().get(0).getClass();
return this.getContextBean(firstContextBeanClazz);
}
public void addSubChain(String chainId){
Set<String> subChainSet = (Set<String>) metaDataMap.getOrDefault(SUB_CHAIN, new ConcurrentHashSet<>());
subChainSet.add(chainId);
metaDataMap.putIfAbsent(SUB_CHAIN, subChainSet);
}
public boolean isSubChain(String chainId){
if (metaDataMap.containsKey(SUB_CHAIN)){
Set<String> subChainSet = (Set<String>) metaDataMap.get(SUB_CHAIN);
return subChainSet.contains(chainId);
}else{
return false;
}
}
}

View File

@ -11,6 +11,7 @@ import com.yomahub.liteflow.exception.ConfigErrorException;
import com.yomahub.liteflow.spi.PathContentParser;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.util.ResourceUtils;
import java.util.ArrayList;
@ -33,7 +34,7 @@ public class SpringPathContentParser implements PathContentParser {
if (FileUtil.isAbsolutePath(path) && FileUtil.isFile(path)){
locationPattern = ResourceUtils.FILE_URL_PREFIX + path;
} else {
if (!path.startsWith(ResourceUtils.CLASSPATH_URL_PREFIX)) {
if (!path.startsWith(ResourceUtils.CLASSPATH_URL_PREFIX) && !path.startsWith(ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX)) {
locationPattern = ResourceUtils.CLASSPATH_URL_PREFIX + path;
}else{
locationPattern = path;

View File

@ -1,20 +1,17 @@
package com.yomahub.liteflow.test.builder;
import com.yomahub.liteflow.builder.LiteFlowChainBuilder;
import com.yomahub.liteflow.builder.LiteFlowConditionBuilder;
import com.yomahub.liteflow.builder.LiteFlowNodeBuilder;
import com.yomahub.liteflow.builder.el.LiteFlowChainELBuilder;
import com.yomahub.liteflow.core.FlowExecutor;
import com.yomahub.liteflow.builder.entity.ExecutableEntity;
import com.yomahub.liteflow.flow.LiteflowResponse;
import com.yomahub.liteflow.enums.NodeTypeEnum;
import com.yomahub.liteflow.test.BaseTest;
import com.yomahub.liteflow.test.builder.cmp1.*;
import com.yomahub.liteflow.test.base.BaseELDeclSpringbootTest;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.test.context.TestPropertySource;
import org.springframework.test.context.junit4.SpringRunner;
import javax.annotation.Resource;
@ -25,6 +22,7 @@ import javax.annotation.Resource;
@RunWith(SpringRunner.class)
@SpringBootTest(classes = BuilderELDeclSpringbootTest1.class)
@EnableAutoConfiguration
@ComponentScan({"com.yomahub.liteflow.test.builder.cmp1"})
public class BuilderELDeclSpringbootTest1 extends BaseTest {
@Resource
@ -33,43 +31,6 @@ public class BuilderELDeclSpringbootTest1 extends BaseTest {
//基于普通组件的builder模式测试
@Test
public void testBuilder() throws Exception {
LiteFlowNodeBuilder.createNode().setId("a")
.setName("组件A")
.setType(NodeTypeEnum.COMMON)
.setClazz("com.yomahub.liteflow.test.builder.cmp1.ACmp")
.build();
LiteFlowNodeBuilder.createNode().setId("b")
.setName("组件B")
.setType(NodeTypeEnum.COMMON)
.setClazz("com.yomahub.liteflow.test.builder.cmp1.BCmp")
.build();
LiteFlowNodeBuilder.createNode().setId("c")
.setName("组件C")
.setType(NodeTypeEnum.COMMON)
.setClazz("com.yomahub.liteflow.test.builder.cmp1.CCmp")
.build();
LiteFlowNodeBuilder.createNode().setId("d")
.setName("组件D")
.setType(NodeTypeEnum.COMMON)
.setClazz("com.yomahub.liteflow.test.builder.cmp1.DCmp")
.build();
LiteFlowNodeBuilder.createNode().setId("e")
.setName("组件E")
.setType(NodeTypeEnum.SWITCH)
.setClazz("com.yomahub.liteflow.test.builder.cmp1.ECmp")
.build();
LiteFlowNodeBuilder.createNode().setId("f")
.setName("组件F")
.setType(NodeTypeEnum.COMMON)
.setClazz("com.yomahub.liteflow.test.builder.cmp1.FCmp")
.build();
LiteFlowNodeBuilder.createNode().setId("g")
.setName("组件G")
.setType(NodeTypeEnum.COMMON)
.setClazz("com.yomahub.liteflow.test.builder.cmp1.GCmp")
.build();
LiteFlowChainELBuilder.createChain().setChainName("chain2").setEL(
"THEN(c, d)"
).build();
@ -80,133 +41,22 @@ public class BuilderELDeclSpringbootTest1 extends BaseTest {
LiteflowResponse response = flowExecutor.execute2Resp("chain1");
Assert.assertTrue(response.isSuccess());
Assert.assertEquals("a[组件A]==>b[组件B]==>e[组件E]==>c[组件C]==>d[组件D]", response.getExecuteStepStr());
Assert.assertEquals("a==>b==>e==>c==>d", response.getExecuteStepStrWithoutTime());
}
//基于普通组件的builder模式测试
@Test
public void testBuilderForClassAndCode() throws Exception {
LiteFlowNodeBuilder.createNode().setId("a")
.setName("组件A")
.setType(NodeTypeEnum.COMMON)
.setClazz(ACmp.class)
.build();
LiteFlowNodeBuilder.createNode().setId("b")
.setName("组件B")
.setType(NodeTypeEnum.COMMON)
.setClazz(BCmp.class)
.build();
LiteFlowNodeBuilder.createNode().setId("c")
.setName("组件C")
.setType(NodeTypeEnum.COMMON)
.setClazz(CCmp.class)
.build();
LiteFlowNodeBuilder.createNode().setId("d")
.setName("组件D")
.setType(NodeTypeEnum.COMMON)
.setClazz(DCmp.class)
.build();
LiteFlowNodeBuilder.createNode().setId("e")
.setName("组件E")
.setType(NodeTypeEnum.SWITCH)
.setClazz(ECmp.class)
.build();
LiteFlowNodeBuilder.createNode().setId("f")
.setName("组件F")
.setType(NodeTypeEnum.COMMON)
.setClazz(FCmp.class)
.build();
LiteFlowNodeBuilder.createNode().setId("g")
.setName("组件G")
.setType(NodeTypeEnum.COMMON)
.setClazz(GCmp.class)
.build();
LiteFlowChainBuilder.createChain().setChainName("chain2").setCondition(
LiteFlowConditionBuilder.createThenCondition().setValue("c,d").build()
).build();
LiteFlowChainBuilder.createChain().setChainName("chain1").setCondition(
LiteFlowConditionBuilder
.createThenCondition()
.setValue("a,b").build()
).setCondition(
LiteFlowConditionBuilder.createWhenCondition()
.setValue("e(f|g|chain2)").build()
).build();
LiteflowResponse response = flowExecutor.execute2Resp("chain1");
Assert.assertTrue(response.isSuccess());
Assert.assertEquals("a[组件A]==>b[组件B]==>e[组件E]==>c[组件C]==>d[组件D]", response.getExecuteStepStr());
}
//基于普通组件的builder模式测试
@Test
public void testBuilderForConditionNode() throws Exception {
LiteFlowNodeBuilder.createNode().setId("a")
.setName("组件A")
.setType(NodeTypeEnum.COMMON)
.setClazz(ACmp.class)
.build();
LiteFlowNodeBuilder.createNode().setId("b")
.setName("组件B")
.setType(NodeTypeEnum.COMMON)
.setClazz(BCmp.class)
.build();
LiteFlowNodeBuilder.createNode().setId("c")
.setName("组件C")
.setType(NodeTypeEnum.COMMON)
.setClazz(CCmp.class)
.build();
LiteFlowNodeBuilder.createNode().setId("d")
.setName("组件D")
.setType(NodeTypeEnum.COMMON)
.setClazz(DCmp.class)
.build();
LiteFlowNodeBuilder.createNode().setId("e")
.setName("组件E")
.setType(NodeTypeEnum.SWITCH)
.setClazz(ECmp.class)
.build();
LiteFlowNodeBuilder.createNode().setId("f")
.setName("组件F")
.setType(NodeTypeEnum.COMMON)
.setClazz(FCmp.class)
.build();
LiteFlowNodeBuilder.createNode().setId("g")
.setName("组件G")
.setType(NodeTypeEnum.COMMON)
.setClazz(GCmp.class)
.build();
LiteFlowChainBuilder.createChain().setChainName("chain2").setCondition(
LiteFlowConditionBuilder.createThenCondition()
.setExecutable(new ExecutableEntity().setId("c"))
.setExecutable(new ExecutableEntity().setId("d"))
.build()
LiteFlowChainELBuilder.createChain().setChainName("chain2").setEL(
"THEN(c, d)"
).build();
LiteFlowChainBuilder.createChain().setChainName("chain1").setCondition(
LiteFlowConditionBuilder
.createThenCondition()
.setExecutable(new ExecutableEntity().setId("a").setTag("hello"))
.setExecutable(new ExecutableEntity().setId("b"))
.build()
).setCondition(
LiteFlowConditionBuilder.createWhenCondition()
.setExecutable(
new ExecutableEntity().setId("e")
.addNodeCondComponent(new ExecutableEntity().setId("f").setTag("FHello"))
.addNodeCondComponent(new ExecutableEntity().setId("g"))
.addNodeCondComponent(new ExecutableEntity().setId("chain2")
)).build()
LiteFlowChainELBuilder.createChain().setChainName("chain1").setEL(
"THEN(a.tag('hello'), b, WHEN(SWITCH(e).to(f.tag('FHello'), g, chain2)))"
).build();
LiteflowResponse response = flowExecutor.execute2Resp("chain1");
Assert.assertTrue(response.isSuccess());
Assert.assertEquals("a[组件A]==>b[组件B]==>e[组件E]==>c[组件C]==>d[组件D]", response.getExecuteStepStr());
Assert.assertEquals("a==>b==>e==>c==>d", response.getExecuteStepStr());
}
}

View File

@ -8,10 +8,12 @@
package com.yomahub.liteflow.test.builder.cmp1;
import com.yomahub.liteflow.annotation.LiteflowCmpDefine;
import com.yomahub.liteflow.annotation.LiteflowComponent;
import com.yomahub.liteflow.annotation.LiteflowMethod;
import com.yomahub.liteflow.core.NodeComponent;
import com.yomahub.liteflow.enums.LiteFlowMethodEnum;
@LiteflowComponent("a")
@LiteflowCmpDefine
public class ACmp{

View File

@ -8,10 +8,12 @@
package com.yomahub.liteflow.test.builder.cmp1;
import com.yomahub.liteflow.annotation.LiteflowCmpDefine;
import com.yomahub.liteflow.annotation.LiteflowComponent;
import com.yomahub.liteflow.annotation.LiteflowMethod;
import com.yomahub.liteflow.core.NodeComponent;
import com.yomahub.liteflow.enums.LiteFlowMethodEnum;
@LiteflowComponent("b")
@LiteflowCmpDefine
public class BCmp{

View File

@ -8,10 +8,12 @@
package com.yomahub.liteflow.test.builder.cmp1;
import com.yomahub.liteflow.annotation.LiteflowCmpDefine;
import com.yomahub.liteflow.annotation.LiteflowComponent;
import com.yomahub.liteflow.annotation.LiteflowMethod;
import com.yomahub.liteflow.core.NodeComponent;
import com.yomahub.liteflow.enums.LiteFlowMethodEnum;
@LiteflowComponent("c")
@LiteflowCmpDefine
public class CCmp{

View File

@ -8,10 +8,12 @@
package com.yomahub.liteflow.test.builder.cmp1;
import com.yomahub.liteflow.annotation.LiteflowCmpDefine;
import com.yomahub.liteflow.annotation.LiteflowComponent;
import com.yomahub.liteflow.annotation.LiteflowMethod;
import com.yomahub.liteflow.core.NodeComponent;
import com.yomahub.liteflow.enums.LiteFlowMethodEnum;
@LiteflowComponent("d")
@LiteflowCmpDefine
public class DCmp{

View File

@ -7,11 +7,13 @@
*/
package com.yomahub.liteflow.test.builder.cmp1;
import com.yomahub.liteflow.annotation.LiteflowComponent;
import com.yomahub.liteflow.annotation.LiteflowSwitchCmpDefine;
import com.yomahub.liteflow.annotation.LiteflowMethod;
import com.yomahub.liteflow.core.NodeComponent;
import com.yomahub.liteflow.enums.LiteFlowMethodEnum;
@LiteflowComponent("e")
@LiteflowSwitchCmpDefine
public class ECmp{

View File

@ -8,10 +8,12 @@
package com.yomahub.liteflow.test.builder.cmp1;
import com.yomahub.liteflow.annotation.LiteflowCmpDefine;
import com.yomahub.liteflow.annotation.LiteflowComponent;
import com.yomahub.liteflow.annotation.LiteflowMethod;
import com.yomahub.liteflow.core.NodeComponent;
import com.yomahub.liteflow.enums.LiteFlowMethodEnum;
@LiteflowComponent("f")
@LiteflowCmpDefine
public class FCmp{

View File

@ -8,10 +8,12 @@
package com.yomahub.liteflow.test.builder.cmp1;
import com.yomahub.liteflow.annotation.LiteflowCmpDefine;
import com.yomahub.liteflow.annotation.LiteflowComponent;
import com.yomahub.liteflow.annotation.LiteflowMethod;
import com.yomahub.liteflow.core.NodeComponent;
import com.yomahub.liteflow.enums.LiteFlowMethodEnum;
@LiteflowComponent("g")
@LiteflowCmpDefine
public class GCmp{

View File

@ -2,6 +2,6 @@
<!--这里只是内容,在这个测试用例中这个文件请移到/usr/local/flow.xml中-->
<flow>
<chain name="chain1">
<when value="a,b,c"/>
WHEN(a,b,c);
</chain>
</flow>

View File

@ -2,6 +2,6 @@
<!--这里只是内容,在这个测试用例中这个文件请移到/usr/local/flow.xml中-->
<flow>
<chain name="chain1">
<when value="a,b,c"/>
WHEN(a,b,c);
</chain>
</flow>

View File

@ -63,4 +63,11 @@ public class ImplicitSubFlowELSpringbootTest extends BaseTest {
//requestData的取值正确
Assert.assertEquals(10, set.size());
}
@Test
public void testImplicitSubFlow3() {
LiteflowResponse response = flowExecutor.execute2Resp("chain_r", "it's a request");
Assert.assertTrue(response.isSuccess());
}
}

View File

@ -19,13 +19,7 @@ public class PCmp extends NodeComponent {
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();
new Thread(() -> flowExecutor.invoke2RespInAsync("c2", "it's implicit subflow " + finalI, slotIndex)).start();
}
Thread.sleep(1000);
}

View File

@ -0,0 +1,12 @@
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

@ -0,0 +1,12 @@
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

@ -15,4 +15,12 @@
<chain name="c2">
THEN(q);
</chain>
<chain name="chain_r">
THEN(r);
</chain>
<chain name="chain_s">
THEN(s);
</chain>
</flow>