!237 [ISSUE #I7YYLF] 增加组件降级特性
Merge pull request !237 from DaleLee/issue/#I7YYLF
This commit is contained in:
commit
2b481fb983
|
@ -0,0 +1,23 @@
|
|||
package com.yomahub.liteflow.annotation;
|
||||
|
||||
import com.yomahub.liteflow.enums.NodeTypeEnum;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Inherited;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* 降级组件
|
||||
*
|
||||
* @author DaleLee
|
||||
* @since 2.11.1
|
||||
*/
|
||||
@Target(ElementType.TYPE)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Documented
|
||||
@Inherited
|
||||
public @interface FallbackCmp {
|
||||
}
|
|
@ -27,7 +27,7 @@ public class ForOperator extends BaseOperator<ForCondition> {
|
|||
Node node;
|
||||
if (objects[0] instanceof Node) {
|
||||
node = OperatorHelper.convert(objects[0], Node.class);
|
||||
if (!ListUtil.toList(NodeTypeEnum.FOR, NodeTypeEnum.FOR_SCRIPT).contains(node.getType())) {
|
||||
if (!ListUtil.toList(NodeTypeEnum.FOR, NodeTypeEnum.FOR_SCRIPT, NodeTypeEnum.FALLBACK).contains(node.getType())) {
|
||||
throw new QLException("The parameter must be for-node item");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,7 +15,7 @@ public class IteratorOperator extends BaseOperator<IteratorCondition> {
|
|||
OperatorHelper.checkObjectSizeEq(objects, 1);
|
||||
|
||||
Node node = OperatorHelper.convert(objects[0], Node.class);
|
||||
if (!ListUtil.toList(NodeTypeEnum.ITERATOR).contains(node.getType())) {
|
||||
if (!ListUtil.toList(NodeTypeEnum.ITERATOR, NodeTypeEnum.FALLBACK).contains(node.getType())) {
|
||||
throw new QLException("The parameter must be iterator-node item");
|
||||
}
|
||||
|
||||
|
|
|
@ -1,11 +1,10 @@
|
|||
package com.yomahub.liteflow.builder.el.operator;
|
||||
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
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.FlowBus;
|
||||
import com.yomahub.liteflow.flow.element.FallbackNodeProxy;
|
||||
import com.yomahub.liteflow.flow.element.Node;
|
||||
import com.yomahub.liteflow.property.LiteflowConfig;
|
||||
import com.yomahub.liteflow.property.LiteflowConfigGetter;
|
||||
|
@ -14,45 +13,29 @@ import com.yomahub.liteflow.property.LiteflowConfigGetter;
|
|||
* EL规则中的node的操作符
|
||||
*
|
||||
* @author Bryan.Zhang
|
||||
* @author DaleLee
|
||||
* @since 2.8.3
|
||||
*/
|
||||
public class NodeOperator extends BaseOperator<Node> {
|
||||
|
||||
@Override
|
||||
public Node build(Object[] objects) throws Exception {
|
||||
OperatorHelper.checkObjectSizeEqOne(objects);
|
||||
@Override
|
||||
public Node build(Object[] objects) throws Exception {
|
||||
OperatorHelper.checkObjectSizeEqOne(objects);
|
||||
String nodeId = OperatorHelper.convert(objects[0], String.class);
|
||||
|
||||
String nodeId = OperatorHelper.convert(objects[0], String.class);
|
||||
|
||||
if (FlowBus.containNode(nodeId)) {
|
||||
return FlowBus.getNode(nodeId);
|
||||
}
|
||||
else {
|
||||
LiteflowConfig liteflowConfig = LiteflowConfigGetter.get();
|
||||
if (StrUtil.isNotBlank(liteflowConfig.getSubstituteCmpClass())) {
|
||||
Node substituteNode = FlowBus.getNodeMap()
|
||||
.values()
|
||||
.stream()
|
||||
.filter(node -> node.getInstance()
|
||||
.getClass()
|
||||
.getName()
|
||||
.equals(liteflowConfig.getSubstituteCmpClass()))
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
if (ObjectUtil.isNotNull(substituteNode)) {
|
||||
return substituteNode;
|
||||
}
|
||||
else {
|
||||
String error = StrUtil.format("This node[{}] cannot be found", nodeId);
|
||||
throw new QLException(error);
|
||||
}
|
||||
}
|
||||
else {
|
||||
String error = StrUtil.format("This node[{}] cannot be found, or you can configure an substitute node",
|
||||
nodeId);
|
||||
throw new QLException(error);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (FlowBus.containNode(nodeId)) {
|
||||
// 找到对应节点
|
||||
return FlowBus.getNode(nodeId);
|
||||
} else {
|
||||
// 检查是否开启了组件降级功能
|
||||
LiteflowConfig liteflowConfig = LiteflowConfigGetter.get();
|
||||
Boolean enable = liteflowConfig.getFallbackCmpEnable();
|
||||
if (!enable) {
|
||||
throw new ELParseException("The fallback component is disabled");
|
||||
}
|
||||
// 生成代理节点
|
||||
return new FallbackNodeProxy(nodeId);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -21,7 +21,7 @@ public class SwitchOperator extends BaseOperator<SwitchCondition> {
|
|||
OperatorHelper.checkObjectSizeEqOne(objects);
|
||||
|
||||
Node switchNode = OperatorHelper.convert(objects[0], Node.class);
|
||||
if (!ListUtil.toList(NodeTypeEnum.SWITCH, NodeTypeEnum.SWITCH_SCRIPT).contains(switchNode.getType())) {
|
||||
if (!ListUtil.toList(NodeTypeEnum.SWITCH, NodeTypeEnum.SWITCH_SCRIPT, NodeTypeEnum.FALLBACK).contains(switchNode.getType())) {
|
||||
throw new QLException("The caller must be Switch item");
|
||||
}
|
||||
|
||||
|
|
|
@ -145,7 +145,8 @@ public class OperatorHelper {
|
|||
if (!(object instanceof Node && ListUtil.toList(
|
||||
NodeTypeEnum.IF, NodeTypeEnum.IF_SCRIPT,
|
||||
NodeTypeEnum.WHILE, NodeTypeEnum.WHILE_SCRIPT,
|
||||
NodeTypeEnum.BREAK, NodeTypeEnum.BREAK_SCRIPT).contains(((Node) object).getType())
|
||||
NodeTypeEnum.BREAK, NodeTypeEnum.BREAK_SCRIPT, NodeTypeEnum.FALLBACK)
|
||||
.contains(((Node) object).getType())
|
||||
|| object instanceof AndOrCondition || object instanceof NotCondition)) {
|
||||
throw new QLException("The first parameter must be boolean type Node or boolean type condition");
|
||||
}
|
||||
|
|
|
@ -34,6 +34,8 @@ public enum NodeTypeEnum {
|
|||
BREAK("break", "循环跳出", false, NodeBreakComponent.class),
|
||||
|
||||
ITERATOR("iterator", "循环迭代", false, NodeIteratorComponent.class),
|
||||
|
||||
FALLBACK("fallback", "降级", false, null),
|
||||
|
||||
SCRIPT("script", "脚本", true, ScriptCommonComponent.class),
|
||||
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
package com.yomahub.liteflow.exception;
|
||||
|
||||
/**
|
||||
* 没有找到降级组件异常
|
||||
*
|
||||
* @author DaleLee
|
||||
* @since 2.11.1
|
||||
*/
|
||||
public class FallbackCmpNotFoundException extends RuntimeException {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 异常信息
|
||||
*/
|
||||
private String message;
|
||||
|
||||
public FallbackCmpNotFoundException(String message) {
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMessage() {
|
||||
return message;
|
||||
}
|
||||
|
||||
public void setMessage(String message) {
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
}
|
|
@ -11,7 +11,11 @@ package com.yomahub.liteflow.flow;
|
|||
import cn.hutool.core.collection.ListUtil;
|
||||
import cn.hutool.core.map.MapUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.yomahub.liteflow.core.*;
|
||||
import com.yomahub.liteflow.annotation.FallbackCmp;
|
||||
import com.yomahub.liteflow.annotation.util.AnnoUtil;
|
||||
import com.yomahub.liteflow.core.ComponentInitializer;
|
||||
import com.yomahub.liteflow.core.NodeComponent;
|
||||
import com.yomahub.liteflow.core.ScriptComponent;
|
||||
import com.yomahub.liteflow.enums.FlowParserTypeEnum;
|
||||
import com.yomahub.liteflow.enums.NodeTypeEnum;
|
||||
import com.yomahub.liteflow.exception.ComponentCannotRegisterException;
|
||||
|
@ -31,6 +35,7 @@ import com.yomahub.liteflow.spi.holder.ContextAwareHolder;
|
|||
import com.yomahub.liteflow.spi.local.LocalContextAware;
|
||||
import com.yomahub.liteflow.util.CopyOnWriteHashMap;
|
||||
import com.yomahub.liteflow.util.LiteFlowProxyUtil;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
@ -41,6 +46,7 @@ import java.util.stream.Collectors;
|
|||
* 流程元数据类
|
||||
*
|
||||
* @author Bryan.Zhang
|
||||
* @author DaleLee
|
||||
*/
|
||||
public class FlowBus {
|
||||
|
||||
|
@ -50,6 +56,8 @@ public class FlowBus {
|
|||
|
||||
private static final Map<String, Node> nodeMap = new CopyOnWriteHashMap<>();
|
||||
|
||||
private static final Map<NodeTypeEnum, Node> fallbackNodeMap = new CopyOnWriteHashMap<>();
|
||||
|
||||
private FlowBus() {
|
||||
}
|
||||
|
||||
|
@ -92,8 +100,10 @@ public class FlowBus {
|
|||
throw new NullNodeTypeException(StrUtil.format("node type is null for node[{}]", nodeId));
|
||||
}
|
||||
|
||||
nodeMap.put(nodeId,
|
||||
new Node(ComponentInitializer.loadInstance().initComponent(nodeComponent, type, nodeComponent.getName(), nodeId)));
|
||||
Node node = new Node(ComponentInitializer.loadInstance()
|
||||
.initComponent(nodeComponent, type, nodeComponent.getName(), nodeId));
|
||||
nodeMap.put(nodeId, node);
|
||||
addFallbackNode(node);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -203,6 +213,7 @@ public class FlowBus {
|
|||
|
||||
String activeNodeId = StrUtil.isEmpty(cmpInstance.getNodeId()) ? nodeId : cmpInstance.getNodeId();
|
||||
nodeMap.put(activeNodeId, node);
|
||||
addFallbackNode(node);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -226,9 +237,14 @@ public class FlowBus {
|
|||
return chainMap;
|
||||
}
|
||||
|
||||
public static Node getFallBackNode(NodeTypeEnum nodeType) {
|
||||
return fallbackNodeMap.get(nodeType);
|
||||
}
|
||||
|
||||
public static void cleanCache() {
|
||||
chainMap.clear();
|
||||
nodeMap.clear();
|
||||
fallbackNodeMap.clear();
|
||||
cleanScriptCache();
|
||||
}
|
||||
|
||||
|
@ -269,4 +285,16 @@ public class FlowBus {
|
|||
Arrays.stream(chainIds).forEach(FlowBus::removeChain);
|
||||
}
|
||||
|
||||
// 判断是否是降级组件,如果是则添加到 fallbackNodeMap
|
||||
private static void addFallbackNode(Node node) {
|
||||
NodeComponent nodeComponent = node.getInstance();
|
||||
FallbackCmp fallbackCmp = AnnoUtil.getAnnotation(nodeComponent.getClass(), FallbackCmp.class);
|
||||
if (fallbackCmp == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
NodeTypeEnum nodeType = node.getType();
|
||||
fallbackNodeMap.put(nodeType, node);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -10,10 +10,9 @@ package com.yomahub.liteflow.flow.element;
|
|||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.collection.ListUtil;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import com.yomahub.liteflow.enums.ConditionTypeEnum;
|
||||
import com.yomahub.liteflow.enums.ExecuteTypeEnum;
|
||||
import com.yomahub.liteflow.exception.ChainEndException;
|
||||
import com.yomahub.liteflow.flow.element.Executable;
|
||||
import com.yomahub.liteflow.enums.ConditionTypeEnum;
|
||||
import com.yomahub.liteflow.flow.element.condition.ConditionKey;
|
||||
import com.yomahub.liteflow.slot.DataBus;
|
||||
import com.yomahub.liteflow.slot.Slot;
|
||||
|
@ -27,6 +26,7 @@ import java.util.Map;
|
|||
* Condition的抽象类
|
||||
*
|
||||
* @author Bryan.Zhang
|
||||
* @author DaleLee
|
||||
*/
|
||||
public abstract class Condition implements Executable{
|
||||
|
||||
|
@ -46,7 +46,10 @@ public abstract class Condition implements Executable{
|
|||
|
||||
@Override
|
||||
public void execute(Integer slotIndex) throws Exception {
|
||||
Slot slot = DataBus.getSlot(slotIndex);
|
||||
try {
|
||||
// 当前 Condition 入栈
|
||||
slot.pushCondition(this);
|
||||
executeCondition(slotIndex);
|
||||
}
|
||||
catch (ChainEndException e) {
|
||||
|
@ -55,7 +58,6 @@ public abstract class Condition implements Executable{
|
|||
throw e;
|
||||
}
|
||||
catch (Exception e) {
|
||||
Slot slot = DataBus.getSlot(slotIndex);
|
||||
String chainId = this.getCurrChainId();
|
||||
// 这里事先取到exception set到slot里,为了方便finally取到exception
|
||||
if (slot.isSubChain(chainId)) {
|
||||
|
@ -65,6 +67,9 @@ public abstract class Condition implements Executable{
|
|||
slot.setException(e);
|
||||
}
|
||||
throw e;
|
||||
} finally {
|
||||
// 当前 Condition 出栈
|
||||
slot.popCondition();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,188 @@
|
|||
package com.yomahub.liteflow.flow.element;
|
||||
|
||||
import cn.hutool.core.text.StrFormatter;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import com.yomahub.liteflow.enums.ConditionTypeEnum;
|
||||
import com.yomahub.liteflow.enums.NodeTypeEnum;
|
||||
import com.yomahub.liteflow.exception.FallbackCmpNotFoundException;
|
||||
import com.yomahub.liteflow.exception.FlowSystemException;
|
||||
import com.yomahub.liteflow.flow.FlowBus;
|
||||
import com.yomahub.liteflow.flow.element.condition.ConditionKey;
|
||||
import com.yomahub.liteflow.flow.element.condition.ForCondition;
|
||||
import com.yomahub.liteflow.flow.element.condition.IfCondition;
|
||||
import com.yomahub.liteflow.flow.element.condition.IteratorCondition;
|
||||
import com.yomahub.liteflow.flow.element.condition.LoopCondition;
|
||||
import com.yomahub.liteflow.flow.element.condition.SwitchCondition;
|
||||
import com.yomahub.liteflow.flow.element.condition.WhileCondition;
|
||||
import com.yomahub.liteflow.slot.DataBus;
|
||||
import com.yomahub.liteflow.slot.Slot;
|
||||
|
||||
/**
|
||||
* 降级组件代理
|
||||
*
|
||||
* @author DaleLee
|
||||
* @since 2.11.1
|
||||
*/
|
||||
public class FallbackNodeProxy extends Node {
|
||||
|
||||
// 原节点 id
|
||||
private String expectedNodeId;
|
||||
|
||||
// 降级节点
|
||||
private Node fallbackNode;
|
||||
|
||||
public FallbackNodeProxy() {
|
||||
this.setType(NodeTypeEnum.FALLBACK);
|
||||
}
|
||||
|
||||
public FallbackNodeProxy(String expectedNodeId) {
|
||||
this();
|
||||
this.expectedNodeId = expectedNodeId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(Integer slotIndex) throws Exception {
|
||||
loadFallBackNode(slotIndex);
|
||||
this.fallbackNode.setCurrChainId(this.getCurrChainId());
|
||||
this.fallbackNode.execute(slotIndex);
|
||||
}
|
||||
|
||||
private void loadFallBackNode(Integer slotIndex) throws Exception {
|
||||
if (ObjectUtil.isNotNull(this.fallbackNode)) {
|
||||
// 已经加载过了
|
||||
return;
|
||||
}
|
||||
Slot slot = DataBus.getSlot(slotIndex);
|
||||
Condition curCondition = slot.getCurrentCondition();
|
||||
if (ObjectUtil.isNull(curCondition)) {
|
||||
throw new FlowSystemException("The current executing condition could not be found.");
|
||||
}
|
||||
Node node = findFallbackNode(curCondition);
|
||||
if (ObjectUtil.isNull(node)) {
|
||||
throw new FallbackCmpNotFoundException(
|
||||
StrFormatter.format("No fallback component found for [{}] in chain[{}].", this.expectedNodeId,
|
||||
this.getCurrChainId()));
|
||||
}
|
||||
// 使用 node 的副本
|
||||
this.fallbackNode = node.copy();
|
||||
}
|
||||
|
||||
private Node findFallbackNode(Condition condition) {
|
||||
ConditionTypeEnum conditionType = condition.getConditionType();
|
||||
switch (conditionType) {
|
||||
case TYPE_THEN:
|
||||
case TYPE_WHEN:
|
||||
case TYPE_PRE:
|
||||
case TYPE_FINALLY:
|
||||
case TYPE_CATCH:
|
||||
return FlowBus.getFallBackNode(NodeTypeEnum.COMMON);
|
||||
case TYPE_IF:
|
||||
return findNodeInIf((IfCondition) condition);
|
||||
case TYPE_SWITCH:
|
||||
return findNodeInSwitch((SwitchCondition) condition);
|
||||
case TYPE_FOR:
|
||||
return findNodeInFor((ForCondition) condition);
|
||||
case TYPE_WHILE:
|
||||
return findNodeInWhile((WhileCondition) condition);
|
||||
case TYPE_ITERATOR:
|
||||
return findNodeInIterator((IteratorCondition) condition);
|
||||
case TYPE_NOT_OPT:
|
||||
case TYPE_AND_OR_OPT:
|
||||
return FlowBus.getFallBackNode(NodeTypeEnum.IF);
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private Node findNodeInIf(IfCondition ifCondition) {
|
||||
Executable ifItem = ifCondition.getIfItem();
|
||||
if (ifItem == this) {
|
||||
// 需要条件组件
|
||||
return FlowBus.getFallBackNode(NodeTypeEnum.IF);
|
||||
}
|
||||
|
||||
// 需要普通组件
|
||||
return FlowBus.getFallBackNode(NodeTypeEnum.COMMON);
|
||||
}
|
||||
|
||||
private Node findNodeInSwitch(SwitchCondition switchCondition) {
|
||||
Node switchNode = switchCondition.getSwitchNode();
|
||||
if (switchNode == this) {
|
||||
return FlowBus.getFallBackNode(NodeTypeEnum.SWITCH);
|
||||
}
|
||||
|
||||
return FlowBus.getFallBackNode(NodeTypeEnum.COMMON);
|
||||
}
|
||||
|
||||
private Node findNodeInFor(ForCondition forCondition) {
|
||||
Node forNode = forCondition.getForNode();
|
||||
if (forNode == this) {
|
||||
return FlowBus.getFallBackNode(NodeTypeEnum.FOR);
|
||||
}
|
||||
|
||||
return findNodeInLoop(forCondition);
|
||||
}
|
||||
|
||||
private Node findNodeInWhile(WhileCondition whileCondition) {
|
||||
Executable whileItem = whileCondition.getWhileItem();
|
||||
if (whileItem == this) {
|
||||
return FlowBus.getFallBackNode(NodeTypeEnum.WHILE);
|
||||
}
|
||||
|
||||
return findNodeInLoop(whileCondition);
|
||||
}
|
||||
|
||||
private Node findNodeInIterator(IteratorCondition iteratorCondition) {
|
||||
Node iteratorNode = iteratorCondition.getIteratorNode();
|
||||
if (iteratorNode == this) {
|
||||
return FlowBus.getFallBackNode(NodeTypeEnum.ITERATOR);
|
||||
}
|
||||
|
||||
return findNodeInLoop(iteratorCondition);
|
||||
}
|
||||
|
||||
private Node findNodeInLoop(LoopCondition loopCondition) {
|
||||
Executable breakItem = loopCondition.getExecutableOne(ConditionKey.BREAK_KEY);
|
||||
if (breakItem == this) {
|
||||
return FlowBus.getFallBackNode(NodeTypeEnum.BREAK);
|
||||
}
|
||||
|
||||
return FlowBus.getFallBackNode(NodeTypeEnum.COMMON);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T getItemResultMetaValue(Integer slotIndex) {
|
||||
return this.fallbackNode.getItemResultMetaValue(slotIndex);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAccess(Integer slotIndex) throws Exception {
|
||||
// 可能会先访问这个方法,所以在这里就要加载降级节点
|
||||
loadFallBackNode(slotIndex);
|
||||
return this.fallbackNode.isAccess(slotIndex);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getId() {
|
||||
return this.fallbackNode == null ? null : this.fallbackNode.getId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Node copy() {
|
||||
// 代理节点不复制
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public NodeTypeEnum getType() {
|
||||
return NodeTypeEnum.FALLBACK;
|
||||
}
|
||||
|
||||
public String getExpectedNodeId() {
|
||||
return expectedNodeId;
|
||||
}
|
||||
|
||||
public void setExpectedNodeId(String expectedNodeId) {
|
||||
this.expectedNodeId = expectedNodeId;
|
||||
}
|
||||
}
|
|
@ -97,9 +97,6 @@ public class LiteflowConfig {
|
|||
// 是否打印执行中的日志
|
||||
private Boolean printExecutionLog;
|
||||
|
||||
// 替补组件class路径
|
||||
private String substituteCmpClass;
|
||||
|
||||
// 规则文件/脚本文件变更监听
|
||||
private Boolean enableMonitorFile = Boolean.FALSE;
|
||||
|
||||
|
@ -111,6 +108,9 @@ public class LiteflowConfig {
|
|||
|
||||
//使用默认并行循环线程池时,最大队列数
|
||||
private Integer parallelQueueLimit;
|
||||
|
||||
// 是否启用组件降级
|
||||
private Boolean fallbackCmpEnable;
|
||||
|
||||
public Boolean getEnableMonitorFile() {
|
||||
return enableMonitorFile;
|
||||
|
@ -373,14 +373,6 @@ public class LiteflowConfig {
|
|||
this.printExecutionLog = printExecutionLog;
|
||||
}
|
||||
|
||||
public String getSubstituteCmpClass() {
|
||||
return substituteCmpClass;
|
||||
}
|
||||
|
||||
public void setSubstituteCmpClass(String substituteCmpClass) {
|
||||
this.substituteCmpClass = substituteCmpClass;
|
||||
}
|
||||
|
||||
public String getRuleSourceExtData() {
|
||||
return ruleSourceExtData;
|
||||
}
|
||||
|
@ -454,4 +446,16 @@ public class LiteflowConfig {
|
|||
public void setParallelLoopExecutorClass(String parallelLoopExecutorClass) {
|
||||
this.parallelLoopExecutorClass = parallelLoopExecutorClass;
|
||||
}
|
||||
|
||||
public Boolean getFallbackCmpEnable() {
|
||||
if (ObjectUtil.isNull(this.fallbackCmpEnable)) {
|
||||
return false;
|
||||
} else {
|
||||
return fallbackCmpEnable;
|
||||
}
|
||||
}
|
||||
|
||||
public void setFallbackCmpEnable(Boolean fallbackCmpEnable) {
|
||||
this.fallbackCmpEnable = fallbackCmpEnable;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,26 +13,29 @@ import cn.hutool.core.util.ObjectUtil;
|
|||
import cn.hutool.core.util.StrUtil;
|
||||
import com.yomahub.liteflow.exception.NoSuchContextBeanException;
|
||||
import com.yomahub.liteflow.exception.NullParamException;
|
||||
import com.yomahub.liteflow.flow.element.Condition;
|
||||
import com.yomahub.liteflow.flow.entity.CmpStep;
|
||||
import com.yomahub.liteflow.flow.id.IdGeneratorHolder;
|
||||
import com.yomahub.liteflow.log.LFLog;
|
||||
import com.yomahub.liteflow.log.LFLoggerManager;
|
||||
import com.yomahub.liteflow.property.LiteflowConfigGetter;
|
||||
|
||||
import java.util.Deque;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
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;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
/**
|
||||
* Slot的抽象类实现
|
||||
*
|
||||
* @author Bryan.Zhang
|
||||
* @author LeoLee
|
||||
* @author DaleLee
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public class Slot {
|
||||
|
@ -88,6 +91,8 @@ public class Slot {
|
|||
protected ConcurrentHashMap<String, Object> metaDataMap = new ConcurrentHashMap<>();
|
||||
|
||||
private List<Object> contextBeanList;
|
||||
|
||||
private static final ThreadLocal<Deque<Condition>> conditionStack = ThreadLocal.withInitial(LinkedList::new);
|
||||
|
||||
public Slot() {
|
||||
}
|
||||
|
@ -287,6 +292,18 @@ public class Slot {
|
|||
public Iterator<?> getIteratorResult(String key) {
|
||||
return getThreadMetaData(ITERATOR_PREFIX + key);
|
||||
}
|
||||
|
||||
public Condition getCurrentCondition() {
|
||||
return conditionStack.get().peek();
|
||||
}
|
||||
|
||||
public void pushCondition(Condition condition) {
|
||||
conditionStack.get().push(condition);
|
||||
}
|
||||
|
||||
public void popCondition() {
|
||||
conditionStack.get().pop();
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated 请使用 {@link #setChainId(String)}
|
||||
|
|
|
@ -46,10 +46,10 @@ public class LiteflowAutoConfiguration {
|
|||
liteflowConfig.setMainExecutorWorks(property.getMainExecutorWorks());
|
||||
liteflowConfig.setMainExecutorClass(property.getMainExecutorClass());
|
||||
liteflowConfig.setPrintExecutionLog(property.isPrintExecutionLog());
|
||||
liteflowConfig.setSubstituteCmpClass(property.getSubstituteCmpClass());
|
||||
liteflowConfig.setParallelMaxWorkers(property.getParallelMaxWorkers());
|
||||
liteflowConfig.setParallelQueueLimit(property.getParallelQueueLimit());
|
||||
liteflowConfig.setParallelLoopExecutorClass(property.getParallelLoopExecutorClass());
|
||||
liteflowConfig.setFallbackCmpEnable(property.isFallbackCmpEnable());
|
||||
return liteflowConfig;
|
||||
}
|
||||
|
||||
|
|
|
@ -67,9 +67,6 @@ public class LiteflowProperty {
|
|||
// 是否打印执行过程中的日志
|
||||
private boolean printExecutionLog;
|
||||
|
||||
// 替补组件的class路径
|
||||
private String substituteCmpClass;
|
||||
|
||||
//并行循环线程池类路径
|
||||
private String parallelLoopExecutorClass;
|
||||
|
||||
|
@ -78,6 +75,9 @@ public class LiteflowProperty {
|
|||
|
||||
//使用默认并行循环线程池时,最大队列数
|
||||
private Integer parallelQueueLimit;
|
||||
|
||||
// 是否启用组件降级
|
||||
private Boolean fallbackCmpEnable;
|
||||
|
||||
public boolean isEnable() {
|
||||
return enable;
|
||||
|
@ -212,14 +212,6 @@ public class LiteflowProperty {
|
|||
this.requestIdGeneratorClass = requestIdGeneratorClass;
|
||||
}
|
||||
|
||||
public String getSubstituteCmpClass() {
|
||||
return substituteCmpClass;
|
||||
}
|
||||
|
||||
public void setSubstituteCmpClass(String substituteCmpClass) {
|
||||
this.substituteCmpClass = substituteCmpClass;
|
||||
}
|
||||
|
||||
public String getRuleSourceExtData() {
|
||||
return ruleSourceExtData;
|
||||
}
|
||||
|
@ -251,4 +243,12 @@ public class LiteflowProperty {
|
|||
public void setParallelQueueLimit(Integer parallelQueueLimit) {
|
||||
this.parallelQueueLimit = parallelQueueLimit;
|
||||
}
|
||||
|
||||
public Boolean isFallbackCmpEnable() {
|
||||
return fallbackCmpEnable;
|
||||
}
|
||||
|
||||
public void setFallbackCmpEnable(Boolean fallbackCmpEnable) {
|
||||
this.fallbackCmpEnable = fallbackCmpEnable;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,8 +13,8 @@ liteflow.retry-count=0
|
|||
liteflow.support-multiple-type=false
|
||||
liteflow.node-executor-class=com.yomahub.liteflow.flow.executor.DefaultNodeExecutor
|
||||
liteflow.print-execution-log=true
|
||||
liteflow.substitute-cmp-class=
|
||||
liteflow.monitor.enable-log=false
|
||||
liteflow.monitor.queue-limit=200
|
||||
liteflow.monitor.delay=300000
|
||||
liteflow.monitor.period=300000
|
||||
liteflow.fallback-cmp-enable=false
|
||||
|
|
|
@ -74,9 +74,6 @@ public class LiteflowProperty {
|
|||
// 是否打印执行过程中的日志
|
||||
private boolean printExecutionLog;
|
||||
|
||||
// 替补组件的class路径
|
||||
private String substituteCmpClass;
|
||||
|
||||
// 规则文件/脚本文件变更监听
|
||||
private Boolean enableMonitorFile;
|
||||
|
||||
|
@ -87,6 +84,9 @@ public class LiteflowProperty {
|
|||
|
||||
//使用默认并行循环线程池时,最大队列数
|
||||
private Integer parallelQueueLimit;
|
||||
|
||||
// 是否启用组件降级
|
||||
private Boolean fallbackCmpEnable;
|
||||
|
||||
public Boolean getEnableMonitorFile() {
|
||||
return enableMonitorFile;
|
||||
|
@ -226,14 +226,6 @@ public class LiteflowProperty {
|
|||
this.requestIdGeneratorClass = requestIdGeneratorClass;
|
||||
}
|
||||
|
||||
public String getSubstituteCmpClass() {
|
||||
return substituteCmpClass;
|
||||
}
|
||||
|
||||
public void setSubstituteCmpClass(String substituteCmpClass) {
|
||||
this.substituteCmpClass = substituteCmpClass;
|
||||
}
|
||||
|
||||
public String getRuleSourceExtData() {
|
||||
return ruleSourceExtData;
|
||||
}
|
||||
|
@ -289,4 +281,12 @@ public class LiteflowProperty {
|
|||
public void setParallelQueueLimit(Integer parallelQueueLimit) {
|
||||
this.parallelQueueLimit = parallelQueueLimit;
|
||||
}
|
||||
|
||||
public Boolean isFallbackCmpEnable() {
|
||||
return fallbackCmpEnable;
|
||||
}
|
||||
|
||||
public void setFallbackCmpEnable(Boolean fallbackCmpEnable) {
|
||||
this.fallbackCmpEnable = fallbackCmpEnable;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -46,11 +46,11 @@ public class LiteflowPropertyAutoConfiguration {
|
|||
liteflowConfig.setMainExecutorWorks(property.getMainExecutorWorks());
|
||||
liteflowConfig.setMainExecutorClass(property.getMainExecutorClass());
|
||||
liteflowConfig.setPrintExecutionLog(property.isPrintExecutionLog());
|
||||
liteflowConfig.setSubstituteCmpClass(property.getSubstituteCmpClass());
|
||||
liteflowConfig.setEnableMonitorFile(property.getEnableMonitorFile());
|
||||
liteflowConfig.setParallelMaxWorkers(property.getParallelMaxWorkers());
|
||||
liteflowConfig.setParallelQueueLimit(property.getParallelQueueLimit());
|
||||
liteflowConfig.setParallelLoopExecutorClass(property.getParallelLoopExecutorClass());
|
||||
liteflowConfig.setFallbackCmpEnable(property.isFallbackCmpEnable());
|
||||
return liteflowConfig;
|
||||
}
|
||||
|
||||
|
|
|
@ -138,13 +138,6 @@
|
|||
"sourceType": "com.yomahub.liteflow.springboot.LiteflowProperty",
|
||||
"defaultValue": true
|
||||
},
|
||||
{
|
||||
"name": "liteflow.substitute-cmp-class",
|
||||
"type": "java.lang.String",
|
||||
"description": "substitute component class.",
|
||||
"sourceType": "com.yomahub.liteflow.springboot.LiteflowProperty",
|
||||
"defaultValue": ""
|
||||
},
|
||||
{
|
||||
"name": "liteflow.monitor.enable-log",
|
||||
"type": "java.lang.Boolean",
|
||||
|
@ -200,6 +193,13 @@
|
|||
"description": "Custom thread pool implement for parallel-loop executor.",
|
||||
"sourceType": "com.yomahub.liteflow.springboot.LiteflowProperty",
|
||||
"defaultValue": "com.yomahub.liteflow.thread.LiteFlowDefaultParallelLoopExecutorBuilder"
|
||||
},
|
||||
{
|
||||
"name": "liteflow.fallback-cmp-enable",
|
||||
"type": "java.lang.Boolean",
|
||||
"description": "Enable fallback component.",
|
||||
"sourceType": "com.yomahub.liteflow.springboot.LiteflowProperty",
|
||||
"defaultValue": false
|
||||
}
|
||||
]
|
||||
}
|
|
@ -0,0 +1,225 @@
|
|||
package com.yomahub.liteflow.test.fallback;
|
||||
|
||||
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.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.context.annotation.ComponentScan;
|
||||
import org.springframework.test.context.TestPropertySource;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.Future;
|
||||
|
||||
/**
|
||||
* SpringBoot 降级组件测试
|
||||
*
|
||||
* @author DaleLee
|
||||
* @since 2.11.1
|
||||
*/
|
||||
@TestPropertySource(value = "classpath:/fallback/application.properties")
|
||||
@SpringBootTest(classes = FallbackELDeclSpringbootTest.class)
|
||||
@EnableAutoConfiguration
|
||||
@ComponentScan({"com.yomahub.liteflow.test.fallback.cmp"})
|
||||
public class FallbackELDeclSpringbootTest extends BaseTest {
|
||||
|
||||
@Resource
|
||||
private FlowExecutor flowExecutor;
|
||||
|
||||
@Test
|
||||
public void testThen1() {
|
||||
LiteflowResponse response = flowExecutor.execute2Resp("then1", "arg");
|
||||
Assertions.assertTrue(response.isSuccess());
|
||||
Assertions.assertEquals("a==>c", response.getExecuteStepStrWithoutTime());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testThen2() {
|
||||
LiteflowResponse response = flowExecutor.execute2Resp("then2", "arg");
|
||||
Assertions.assertTrue(response.isSuccess());
|
||||
Assertions.assertEquals("c==>c==>c", response.getExecuteStepStrWithoutTime());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWhen1() {
|
||||
LiteflowResponse response = flowExecutor.execute2Resp("when1", "arg");
|
||||
Assertions.assertTrue(response.isSuccess());
|
||||
String executeStepStr = response.getExecuteStepStrWithoutTime();
|
||||
Assertions.assertTrue("b==>c".equals(executeStepStr) || "c==>b".equals(executeStepStr));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIf1() {
|
||||
LiteflowResponse response = flowExecutor.execute2Resp("if1", "arg");
|
||||
Assertions.assertTrue(response.isSuccess());
|
||||
Assertions.assertEquals("ifn2", response.getExecuteStepStrWithoutTime());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIf2() {
|
||||
LiteflowResponse response = flowExecutor.execute2Resp("if2", "arg");
|
||||
Assertions.assertTrue(response.isSuccess());
|
||||
Assertions.assertEquals("ifn1==>c", response.getExecuteStepStrWithoutTime());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFor1() {
|
||||
LiteflowResponse response = flowExecutor.execute2Resp("for1", "arg");
|
||||
Assertions.assertTrue(response.isSuccess());
|
||||
Assertions.assertEquals("for1==>a==>a==>a", response.getExecuteStepStrWithoutTime());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFor2() {
|
||||
LiteflowResponse response = flowExecutor.execute2Resp("for2", "arg");
|
||||
Assertions.assertTrue(response.isSuccess());
|
||||
Assertions.assertEquals("LOOP_3==>c==>c==>c", response.getExecuteStepStrWithoutTime());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWhile1() {
|
||||
LiteflowResponse response = flowExecutor.execute2Resp("while1", "arg");
|
||||
Assertions.assertTrue(response.isSuccess());
|
||||
Assertions.assertEquals("wn2", response.getExecuteStepStrWithoutTime());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWhile2() {
|
||||
LiteflowResponse response = flowExecutor.execute2Resp("while2", "arg");
|
||||
Assertions.assertTrue(response.isSuccess());
|
||||
Assertions.assertEquals("wn1==>c==>wn1==>c==>wn1==>c==>wn1", response.getExecuteStepStrWithoutTime());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIterator1() {
|
||||
LiteflowResponse response = flowExecutor.execute2Resp("iterator1", "arg");
|
||||
Assertions.assertTrue(response.isSuccess());
|
||||
Assertions.assertEquals("itn2", response.getExecuteStepStrWithoutTime());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIterator2() {
|
||||
LiteflowResponse response = flowExecutor.execute2Resp("iterator2", "arg");
|
||||
Assertions.assertTrue(response.isSuccess());
|
||||
Assertions.assertEquals("itn1==>c==>c==>c", response.getExecuteStepStrWithoutTime());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBreak1() {
|
||||
LiteflowResponse response = flowExecutor.execute2Resp("break1", "arg");
|
||||
Assertions.assertTrue(response.isSuccess());
|
||||
Assertions.assertEquals("LOOP_3==>a==>bn1", response.getExecuteStepStrWithoutTime());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBreak2() {
|
||||
LiteflowResponse response = flowExecutor.execute2Resp("break2", "arg");
|
||||
Assertions.assertTrue(response.isSuccess());
|
||||
Assertions.assertEquals("wn1==>a==>bn1", response.getExecuteStepStrWithoutTime());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBreak3() {
|
||||
LiteflowResponse response = flowExecutor.execute2Resp("break3", "arg");
|
||||
Assertions.assertTrue(response.isSuccess());
|
||||
Assertions.assertEquals("itn1==>a==>bn1", response.getExecuteStepStrWithoutTime());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSwitch1() {
|
||||
LiteflowResponse response = flowExecutor.execute2Resp("switch1", "arg");
|
||||
Assertions.assertTrue(response.isSuccess());
|
||||
Assertions.assertEquals("swn2==>b", response.getExecuteStepStrWithoutTime());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSwitch2() {
|
||||
LiteflowResponse response = flowExecutor.execute2Resp("switch2", "arg");
|
||||
Assertions.assertTrue(response.isSuccess());
|
||||
Assertions.assertEquals("swn1==>a", response.getExecuteStepStrWithoutTime());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAnd1() {
|
||||
LiteflowResponse response = flowExecutor.execute2Resp("and1", "arg");
|
||||
Assertions.assertTrue(response.isSuccess());
|
||||
Assertions.assertEquals("ifn2", response.getExecuteStepStrWithoutTime());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOr1() {
|
||||
LiteflowResponse response = flowExecutor.execute2Resp("or1", "arg");
|
||||
Assertions.assertTrue(response.isSuccess());
|
||||
Assertions.assertEquals("ifn2==>ifn1==>a", response.getExecuteStepStrWithoutTime());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNot1() {
|
||||
LiteflowResponse response = flowExecutor.execute2Resp("not1", "arg");
|
||||
Assertions.assertTrue(response.isSuccess());
|
||||
Assertions.assertEquals("ifn2==>a", response.getExecuteStepStrWithoutTime());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCatch1() {
|
||||
LiteflowResponse response = flowExecutor.execute2Resp("catch1", "arg");
|
||||
Assertions.assertTrue(response.isSuccess());
|
||||
Assertions.assertEquals("a==>d==>c", response.getExecuteStepStrWithoutTime());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMulti1() {
|
||||
LiteflowResponse response = flowExecutor.execute2Resp("multi1", "arg");
|
||||
Assertions.assertTrue(response.isSuccess());
|
||||
Assertions.assertEquals("a==>c==>ifn2", response.getExecuteStepStrWithoutTime());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMulti2() {
|
||||
LiteflowResponse response = flowExecutor.execute2Resp("multi2", "arg");
|
||||
Assertions.assertTrue(response.isSuccess());
|
||||
Assertions.assertEquals("ifn2==>ifn1==>a==>c", response.getExecuteStepStrWithoutTime());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMulti3() {
|
||||
LiteflowResponse response = flowExecutor.execute2Resp("multi3", "arg");
|
||||
Assertions.assertTrue(response.isSuccess());
|
||||
Assertions.assertEquals("for1==>b==>c==>b==>c==>b==>c", response.getExecuteStepStrWithoutTime());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConcurrent1() {
|
||||
LiteflowResponse response = flowExecutor.execute2Resp("concurrent1", "arg");
|
||||
Assertions.assertTrue(response.isSuccess());
|
||||
String stepStr = response.getExecuteStepStrWithoutTime();
|
||||
Assertions.assertTrue("c==>ifn2".equals(stepStr) || "ifn2==>c".equals(stepStr));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConcurrent2() {
|
||||
LiteflowResponse response = flowExecutor.execute2Resp("concurrent2", "arg");
|
||||
Assertions.assertTrue(response.isSuccess());
|
||||
String stepStr = response.getExecuteStepStrWithoutTime();
|
||||
Assertions.assertTrue("c==>ifn2".equals(stepStr) || "ifn2==>c".equals(stepStr));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConcurrent3() throws ExecutionException, InterruptedException {
|
||||
// 执行多条 chain
|
||||
Future<LiteflowResponse> future1 = flowExecutor.execute2Future("concurrent1", "arg", new Object());
|
||||
Future<LiteflowResponse> future2 = flowExecutor.execute2Future("concurrent2", "arg", new Object());
|
||||
Thread.sleep(1000);
|
||||
LiteflowResponse response1 = future1.get();
|
||||
LiteflowResponse response2 = future2.get();
|
||||
Assertions.assertTrue(response1.isSuccess());
|
||||
String stepStr1 = response1.getExecuteStepStrWithoutTime();
|
||||
Assertions.assertTrue("c==>ifn2".equals(stepStr1) || "ifn2==>c".equals(stepStr1));
|
||||
Assertions.assertTrue(response2.isSuccess());
|
||||
String stepStr2 = response2.getExecuteStepStrWithoutTime();
|
||||
Assertions.assertTrue("c==>ifn2".equals(stepStr2) || "ifn2==>c".equals(stepStr2));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
package com.yomahub.liteflow.test.fallback.cmp;
|
||||
|
||||
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")
|
||||
public class ACmp {
|
||||
|
||||
@LiteflowMethod(LiteFlowMethodEnum.PROCESS)
|
||||
public void process(NodeComponent bindCmp) {
|
||||
System.out.println("ACmp executed!");
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
package com.yomahub.liteflow.test.fallback.cmp;
|
||||
|
||||
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")
|
||||
public class BCmp {
|
||||
|
||||
@LiteflowMethod(LiteFlowMethodEnum.PROCESS)
|
||||
public void process(NodeComponent bindCmp) {
|
||||
System.out.println("BCmp executed!");
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
package com.yomahub.liteflow.test.fallback.cmp;
|
||||
|
||||
import com.yomahub.liteflow.annotation.FallbackCmp;
|
||||
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;
|
||||
import com.yomahub.liteflow.enums.NodeTypeEnum;
|
||||
|
||||
@LiteflowComponent("bn1")
|
||||
@LiteflowCmpDefine(NodeTypeEnum.BREAK)
|
||||
@FallbackCmp
|
||||
public class BreakCmp {
|
||||
|
||||
@LiteflowMethod(value = LiteFlowMethodEnum.PROCESS_BREAK)
|
||||
public boolean processBreak(NodeComponent bindCmp) throws Exception {
|
||||
return true;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
package com.yomahub.liteflow.test.fallback.cmp;
|
||||
|
||||
import com.yomahub.liteflow.annotation.FallbackCmp;
|
||||
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")
|
||||
@FallbackCmp
|
||||
public class CCmp {
|
||||
|
||||
@LiteflowMethod(LiteFlowMethodEnum.PROCESS)
|
||||
public void process(NodeComponent bindCmp) {
|
||||
System.out.println("CCmp executed!");
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
package com.yomahub.liteflow.test.fallback.cmp;
|
||||
|
||||
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")
|
||||
public class DCmp {
|
||||
|
||||
@LiteflowMethod(LiteFlowMethodEnum.PROCESS)
|
||||
public void process(NodeComponent bindCmp) throws Exception {
|
||||
throw new RuntimeException("component[d]");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
package com.yomahub.liteflow.test.fallback.cmp;
|
||||
|
||||
import com.yomahub.liteflow.annotation.FallbackCmp;
|
||||
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;
|
||||
import com.yomahub.liteflow.enums.NodeTypeEnum;
|
||||
|
||||
@LiteflowComponent("for1")
|
||||
@LiteflowCmpDefine(NodeTypeEnum.FOR)
|
||||
@FallbackCmp
|
||||
public class ForCmp {
|
||||
|
||||
@LiteflowMethod(value = LiteFlowMethodEnum.PROCESS_FOR)
|
||||
public int processFor(NodeComponent bindCmp) throws Exception {
|
||||
return 3;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
package com.yomahub.liteflow.test.fallback.cmp;
|
||||
|
||||
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;
|
||||
import com.yomahub.liteflow.enums.NodeTypeEnum;
|
||||
|
||||
@LiteflowComponent("ifn1")
|
||||
@LiteflowCmpDefine(NodeTypeEnum.IF)
|
||||
public class IfCmp1 {
|
||||
|
||||
@LiteflowMethod(value = LiteFlowMethodEnum.PROCESS_IF)
|
||||
public boolean processIf(NodeComponent bindCmp) throws Exception {
|
||||
return true;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
package com.yomahub.liteflow.test.fallback.cmp;
|
||||
|
||||
import com.yomahub.liteflow.annotation.FallbackCmp;
|
||||
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;
|
||||
import com.yomahub.liteflow.enums.NodeTypeEnum;
|
||||
|
||||
@LiteflowComponent("ifn2")
|
||||
@LiteflowCmpDefine(NodeTypeEnum.IF)
|
||||
@FallbackCmp
|
||||
public class IfCmp2 {
|
||||
|
||||
@LiteflowMethod(value = LiteFlowMethodEnum.PROCESS_IF)
|
||||
public boolean processIf(NodeComponent bindCmp) throws Exception {
|
||||
return false;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
package com.yomahub.liteflow.test.fallback.cmp;
|
||||
|
||||
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;
|
||||
import com.yomahub.liteflow.enums.NodeTypeEnum;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Iterator;
|
||||
|
||||
@LiteflowComponent("itn1")
|
||||
@LiteflowCmpDefine(NodeTypeEnum.ITERATOR)
|
||||
public class IteratorCmp1 {
|
||||
|
||||
@LiteflowMethod(value = LiteFlowMethodEnum.PROCESS_ITERATOR)
|
||||
public Iterator<?> processIterator(NodeComponent bindCmp) throws Exception {
|
||||
return Arrays.asList("a", "b", "c").iterator();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
package com.yomahub.liteflow.test.fallback.cmp;
|
||||
|
||||
import com.yomahub.liteflow.annotation.FallbackCmp;
|
||||
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;
|
||||
import com.yomahub.liteflow.enums.NodeTypeEnum;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
|
||||
@LiteflowComponent("itn2")
|
||||
@LiteflowCmpDefine(NodeTypeEnum.ITERATOR)
|
||||
@FallbackCmp
|
||||
public class IteratorCmp2 {
|
||||
|
||||
@LiteflowMethod(value = LiteFlowMethodEnum.PROCESS_ITERATOR)
|
||||
public Iterator<?> processIterator(NodeComponent bindCmp) throws Exception {
|
||||
return Collections.emptyIterator();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
package com.yomahub.liteflow.test.fallback.cmp;
|
||||
|
||||
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;
|
||||
import com.yomahub.liteflow.enums.NodeTypeEnum;
|
||||
|
||||
@LiteflowComponent("swn1")
|
||||
@LiteflowCmpDefine(NodeTypeEnum.SWITCH)
|
||||
public class SwitchCmp1 {
|
||||
|
||||
@LiteflowMethod(value = LiteFlowMethodEnum.PROCESS_SWITCH)
|
||||
public String processSwitch(NodeComponent bindCmp) throws Exception {
|
||||
return "a";
|
||||
}
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
package com.yomahub.liteflow.test.fallback.cmp;
|
||||
|
||||
import com.yomahub.liteflow.annotation.FallbackCmp;
|
||||
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;
|
||||
import com.yomahub.liteflow.enums.NodeTypeEnum;
|
||||
|
||||
@LiteflowComponent("swn2")
|
||||
@LiteflowCmpDefine(NodeTypeEnum.SWITCH)
|
||||
@FallbackCmp
|
||||
public class SwitchCmp2 {
|
||||
|
||||
@LiteflowMethod(value = LiteFlowMethodEnum.PROCESS_SWITCH)
|
||||
public String processSwitch(NodeComponent bindCmp) throws Exception {
|
||||
return "b";
|
||||
}
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
package com.yomahub.liteflow.test.fallback.cmp;
|
||||
|
||||
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;
|
||||
import com.yomahub.liteflow.enums.NodeTypeEnum;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
@LiteflowComponent("wn1")
|
||||
@LiteflowCmpDefine(NodeTypeEnum.WHILE)
|
||||
public class WhileCmp1 {
|
||||
private int count = 0;
|
||||
|
||||
// 执行过的 chain
|
||||
Set<String> executedChain = new HashSet<>();
|
||||
|
||||
@LiteflowMethod(value = LiteFlowMethodEnum.PROCESS_WHILE)
|
||||
public boolean processWhile(NodeComponent bindCmp) throws Exception {
|
||||
// 判断是否切换了 chain
|
||||
if (!executedChain.contains(bindCmp.getCurrChainId())) {
|
||||
count = 0;
|
||||
executedChain.add(bindCmp.getCurrChainId());
|
||||
}
|
||||
count++;
|
||||
return count <= 3;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
package com.yomahub.liteflow.test.fallback.cmp;
|
||||
|
||||
import com.yomahub.liteflow.annotation.FallbackCmp;
|
||||
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;
|
||||
import com.yomahub.liteflow.enums.NodeTypeEnum;
|
||||
|
||||
@LiteflowComponent("wn2")
|
||||
@LiteflowCmpDefine(NodeTypeEnum.WHILE)
|
||||
@FallbackCmp
|
||||
public class WhileCmp2 {
|
||||
|
||||
@LiteflowMethod(value = LiteFlowMethodEnum.PROCESS_WHILE)
|
||||
public boolean processWhile(NodeComponent bindCmp) throws Exception {
|
||||
return false;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,2 @@
|
|||
liteflow.rule-source=fallback/flow.el.xml
|
||||
liteflow.fallback-cmp-enable=true
|
|
@ -0,0 +1,136 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<flow>
|
||||
<!-- THEN 普通组件降级 -->
|
||||
<chain name="then1">
|
||||
THEN(a, node("x"));
|
||||
</chain>
|
||||
|
||||
<chain name="then2">
|
||||
THEN(PRE(node("x1")), node("x2"), FINALLY(node("x3")));
|
||||
</chain>
|
||||
|
||||
<!-- WHEN 普通组件降级 -->
|
||||
<chain name="when1">
|
||||
WHEN(b, node("x"));
|
||||
</chain>
|
||||
|
||||
<!-- IF 条件组件降级 -->
|
||||
<chain name="if1">
|
||||
IF(node("x"), a)
|
||||
</chain>
|
||||
|
||||
<!-- IF 普通组件降级 -->
|
||||
<chain name="if2">
|
||||
IF(ifn1, node("x"))
|
||||
</chain>
|
||||
|
||||
<!-- FOR 次数循环组件降级 -->
|
||||
<chain name="for1">
|
||||
FOR(node("x")).DO(a);
|
||||
</chain>
|
||||
|
||||
<!-- FOR 普通组件降级 -->
|
||||
<chain name="for2">
|
||||
FOR(3).DO(node("x"));
|
||||
</chain>
|
||||
|
||||
<!-- WHILE 条件循环组件降级 -->
|
||||
<chain name="while1">
|
||||
WHILE(node("x")).DO(a)
|
||||
</chain>
|
||||
|
||||
<!-- WHILE 普通组件降级 -->
|
||||
<chain name="while2">
|
||||
WHILE(wn1).DO(node("x"))
|
||||
</chain>
|
||||
|
||||
<!-- ITERATOR 迭代组件降级 -->
|
||||
<chain name="iterator1">
|
||||
ITERATOR(node("x")).DO(a)
|
||||
</chain>
|
||||
|
||||
<!-- ITERATOR 普通组件降级 -->
|
||||
<chain name="iterator2">
|
||||
ITERATOR(itn1).DO(node("x"))
|
||||
</chain>
|
||||
|
||||
<!-- BREAK 退出循环组件降级 -->
|
||||
<chain name="break1">
|
||||
FOR(3).DO(a).BREAK(node("x"));
|
||||
</chain>
|
||||
|
||||
<chain name="break2">
|
||||
WHILE(wn1).DO(a).BREAK(node("x"));
|
||||
</chain>
|
||||
|
||||
<chain name="break3">
|
||||
ITERATOR(itn1).DO(a).BREAK(node("x"));
|
||||
</chain>
|
||||
|
||||
<!-- SWITCH 选择组件降级 -->
|
||||
<chain name="switch1">
|
||||
SWITCH(node("x")).to(a,b);
|
||||
</chain>
|
||||
|
||||
<!-- SWITCH 普通组件降级 -->
|
||||
<chain name="switch2">
|
||||
SWITCH(swn1).to(node("x"),a);
|
||||
</chain>
|
||||
|
||||
<!-- AND 条件组件降级 -->
|
||||
<chain name="and1">
|
||||
IF(AND(node("x"),ifn1), a);
|
||||
</chain>
|
||||
|
||||
<!-- OR 条件组件降级 -->
|
||||
<chain name="or1">
|
||||
IF(OR(node("x"),ifn1), a);
|
||||
</chain>
|
||||
|
||||
<!-- NOT 条件组件降级 -->
|
||||
<chain name="not1">
|
||||
IF(NOT(node("x")), a);
|
||||
</chain>
|
||||
|
||||
<!-- CATCH 普通组件降级 -->
|
||||
<chain name="catch1">
|
||||
CATCH(THEN(a, d)).DO(node("x"))
|
||||
</chain>
|
||||
|
||||
<!-- 多个组件降级 -->
|
||||
<chain name="multi1">
|
||||
THEN(
|
||||
a,
|
||||
node("x1"),
|
||||
IF(node("x2"), b)
|
||||
);
|
||||
</chain>
|
||||
|
||||
<chain name="multi2">
|
||||
IF(
|
||||
OR(node("x1"), ifn1),
|
||||
THEN(a, node("x2"))
|
||||
);
|
||||
</chain>
|
||||
|
||||
<chain name="multi3">
|
||||
FOR(node("x1")).DO(
|
||||
THEN(b, node("x2"))
|
||||
);
|
||||
</chain>
|
||||
|
||||
<!-- 并发降级测试 -->
|
||||
<chain name="concurrent1">
|
||||
WHEN(
|
||||
THEN(node("x1")),
|
||||
IF(node("x2"), b)
|
||||
).maxWaitSeconds(10000);
|
||||
</chain>
|
||||
|
||||
<chain name="concurrent2">
|
||||
WHEN(
|
||||
node("x1"),
|
||||
IF(node("x2"), b)
|
||||
).maxWaitSeconds(10000);
|
||||
</chain>
|
||||
</flow>
|
|
@ -0,0 +1,225 @@
|
|||
package com.yomahub.liteflow.test.fallback;
|
||||
|
||||
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;
|
||||
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.Future;
|
||||
|
||||
/**
|
||||
* 非 Spring 环境下组件降级测试
|
||||
*
|
||||
* @author DaleLee
|
||||
* @since 2.11.1
|
||||
*/
|
||||
public class FallbackTest extends BaseTest {
|
||||
private static FlowExecutor flowExecutor;
|
||||
|
||||
@BeforeAll
|
||||
public static void init() {
|
||||
LiteflowConfig config = new LiteflowConfig();
|
||||
config.setRuleSource("fallback/flow.el.xml");
|
||||
config.setFallbackCmpEnable(true);
|
||||
flowExecutor = FlowExecutorHolder.loadInstance(config);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testThen1() {
|
||||
LiteflowResponse response = flowExecutor.execute2Resp("then1", "arg");
|
||||
Assertions.assertTrue(response.isSuccess());
|
||||
Assertions.assertEquals("a==>c", response.getExecuteStepStrWithoutTime());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testThen2() {
|
||||
LiteflowResponse response = flowExecutor.execute2Resp("then2", "arg");
|
||||
Assertions.assertTrue(response.isSuccess());
|
||||
Assertions.assertEquals("c==>c==>c", response.getExecuteStepStrWithoutTime());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWhen1() {
|
||||
LiteflowResponse response = flowExecutor.execute2Resp("when1", "arg");
|
||||
Assertions.assertTrue(response.isSuccess());
|
||||
String executeStepStr = response.getExecuteStepStrWithoutTime();
|
||||
Assertions.assertTrue("b==>c".equals(executeStepStr) || "c==>b".equals(executeStepStr));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIf1() {
|
||||
LiteflowResponse response = flowExecutor.execute2Resp("if1", "arg");
|
||||
Assertions.assertTrue(response.isSuccess());
|
||||
Assertions.assertEquals("ifn2", response.getExecuteStepStrWithoutTime());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIf2() {
|
||||
LiteflowResponse response = flowExecutor.execute2Resp("if2", "arg");
|
||||
Assertions.assertTrue(response.isSuccess());
|
||||
Assertions.assertEquals("ifn1==>c", response.getExecuteStepStrWithoutTime());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFor1() {
|
||||
LiteflowResponse response = flowExecutor.execute2Resp("for1", "arg");
|
||||
Assertions.assertTrue(response.isSuccess());
|
||||
Assertions.assertEquals("for1==>a==>a==>a", response.getExecuteStepStrWithoutTime());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFor2() {
|
||||
LiteflowResponse response = flowExecutor.execute2Resp("for2", "arg");
|
||||
Assertions.assertTrue(response.isSuccess());
|
||||
Assertions.assertEquals("LOOP_3==>c==>c==>c", response.getExecuteStepStrWithoutTime());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWhile1() {
|
||||
LiteflowResponse response = flowExecutor.execute2Resp("while1", "arg");
|
||||
Assertions.assertTrue(response.isSuccess());
|
||||
Assertions.assertEquals("wn2", response.getExecuteStepStrWithoutTime());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWhile2() {
|
||||
LiteflowResponse response = flowExecutor.execute2Resp("while2", "arg");
|
||||
Assertions.assertTrue(response.isSuccess());
|
||||
Assertions.assertEquals("wn1==>c==>wn1==>c==>wn1==>c==>wn1", response.getExecuteStepStrWithoutTime());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIterator1() {
|
||||
LiteflowResponse response = flowExecutor.execute2Resp("iterator1", "arg");
|
||||
Assertions.assertTrue(response.isSuccess());
|
||||
Assertions.assertEquals("itn2", response.getExecuteStepStrWithoutTime());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIterator2() {
|
||||
LiteflowResponse response = flowExecutor.execute2Resp("iterator2", "arg");
|
||||
Assertions.assertTrue(response.isSuccess());
|
||||
Assertions.assertEquals("itn1==>c==>c==>c", response.getExecuteStepStrWithoutTime());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBreak1() {
|
||||
LiteflowResponse response = flowExecutor.execute2Resp("break1", "arg");
|
||||
Assertions.assertTrue(response.isSuccess());
|
||||
Assertions.assertEquals("LOOP_3==>a==>bn1", response.getExecuteStepStrWithoutTime());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBreak2() {
|
||||
LiteflowResponse response = flowExecutor.execute2Resp("break2", "arg");
|
||||
Assertions.assertTrue(response.isSuccess());
|
||||
Assertions.assertEquals("wn1==>a==>bn1", response.getExecuteStepStrWithoutTime());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBreak3() {
|
||||
LiteflowResponse response = flowExecutor.execute2Resp("break3", "arg");
|
||||
Assertions.assertTrue(response.isSuccess());
|
||||
Assertions.assertEquals("itn1==>a==>bn1", response.getExecuteStepStrWithoutTime());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSwitch1() {
|
||||
LiteflowResponse response = flowExecutor.execute2Resp("switch1", "arg");
|
||||
Assertions.assertTrue(response.isSuccess());
|
||||
Assertions.assertEquals("swn2==>b", response.getExecuteStepStrWithoutTime());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSwitch2() {
|
||||
LiteflowResponse response = flowExecutor.execute2Resp("switch2", "arg");
|
||||
Assertions.assertTrue(response.isSuccess());
|
||||
Assertions.assertEquals("swn1==>a", response.getExecuteStepStrWithoutTime());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAnd1() {
|
||||
LiteflowResponse response = flowExecutor.execute2Resp("and1", "arg");
|
||||
Assertions.assertTrue(response.isSuccess());
|
||||
Assertions.assertEquals("ifn2", response.getExecuteStepStrWithoutTime());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOr1() {
|
||||
LiteflowResponse response = flowExecutor.execute2Resp("or1", "arg");
|
||||
Assertions.assertTrue(response.isSuccess());
|
||||
Assertions.assertEquals("ifn2==>ifn1==>a", response.getExecuteStepStrWithoutTime());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNot1() {
|
||||
LiteflowResponse response = flowExecutor.execute2Resp("not1", "arg");
|
||||
Assertions.assertTrue(response.isSuccess());
|
||||
Assertions.assertEquals("ifn2==>a", response.getExecuteStepStrWithoutTime());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCatch1() {
|
||||
LiteflowResponse response = flowExecutor.execute2Resp("catch1", "arg");
|
||||
Assertions.assertTrue(response.isSuccess());
|
||||
Assertions.assertEquals("a==>d==>c", response.getExecuteStepStrWithoutTime());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMulti1() {
|
||||
LiteflowResponse response = flowExecutor.execute2Resp("multi1", "arg");
|
||||
Assertions.assertTrue(response.isSuccess());
|
||||
Assertions.assertEquals("a==>c==>ifn2", response.getExecuteStepStrWithoutTime());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMulti2() {
|
||||
LiteflowResponse response = flowExecutor.execute2Resp("multi2", "arg");
|
||||
Assertions.assertTrue(response.isSuccess());
|
||||
Assertions.assertEquals("ifn2==>ifn1==>a==>c", response.getExecuteStepStrWithoutTime());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMulti3() {
|
||||
LiteflowResponse response = flowExecutor.execute2Resp("multi3", "arg");
|
||||
Assertions.assertTrue(response.isSuccess());
|
||||
Assertions.assertEquals("for1==>b==>c==>b==>c==>b==>c", response.getExecuteStepStrWithoutTime());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConcurrent1() {
|
||||
LiteflowResponse response = flowExecutor.execute2Resp("concurrent1", "arg");
|
||||
Assertions.assertTrue(response.isSuccess());
|
||||
String stepStr = response.getExecuteStepStrWithoutTime();
|
||||
Assertions.assertTrue("c==>ifn2".equals(stepStr) || "ifn2==>c".equals(stepStr));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConcurrent2() {
|
||||
LiteflowResponse response = flowExecutor.execute2Resp("concurrent2", "arg");
|
||||
Assertions.assertTrue(response.isSuccess());
|
||||
String stepStr = response.getExecuteStepStrWithoutTime();
|
||||
Assertions.assertTrue("c==>ifn2".equals(stepStr) || "ifn2==>c".equals(stepStr));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConcurrent3() throws ExecutionException, InterruptedException {
|
||||
// 执行多条 chain
|
||||
Future<LiteflowResponse> future1 = flowExecutor.execute2Future("concurrent1", "arg", new Object());
|
||||
Future<LiteflowResponse> future2 = flowExecutor.execute2Future("concurrent2", "arg", new Object());
|
||||
Thread.sleep(1000);
|
||||
LiteflowResponse response1 = future1.get();
|
||||
LiteflowResponse response2 = future2.get();
|
||||
Assertions.assertTrue(response1.isSuccess());
|
||||
String stepStr1 = response1.getExecuteStepStrWithoutTime();
|
||||
Assertions.assertTrue("c==>ifn2".equals(stepStr1) || "ifn2==>c".equals(stepStr1));
|
||||
Assertions.assertTrue(response2.isSuccess());
|
||||
String stepStr2 = response2.getExecuteStepStrWithoutTime();
|
||||
Assertions.assertTrue("c==>ifn2".equals(stepStr2) || "ifn2==>c".equals(stepStr2));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
package com.yomahub.liteflow.test.fallback.cmp;
|
||||
|
||||
import com.yomahub.liteflow.core.NodeComponent;
|
||||
|
||||
public class ACmp extends NodeComponent {
|
||||
|
||||
@Override
|
||||
public void process() {
|
||||
System.out.println("ACmp executed!");
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
package com.yomahub.liteflow.test.fallback.cmp;
|
||||
|
||||
import com.yomahub.liteflow.core.NodeComponent;
|
||||
|
||||
public class BCmp extends NodeComponent {
|
||||
|
||||
@Override
|
||||
public void process() {
|
||||
System.out.println("BCmp executed!");
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
package com.yomahub.liteflow.test.fallback.cmp;
|
||||
|
||||
import com.yomahub.liteflow.annotation.FallbackCmp;
|
||||
import com.yomahub.liteflow.core.NodeBreakComponent;
|
||||
|
||||
@FallbackCmp
|
||||
public class BreakCmp extends NodeBreakComponent {
|
||||
|
||||
@Override
|
||||
public boolean processBreak() throws Exception {
|
||||
return true;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
package com.yomahub.liteflow.test.fallback.cmp;
|
||||
|
||||
import com.yomahub.liteflow.annotation.FallbackCmp;
|
||||
import com.yomahub.liteflow.core.NodeComponent;
|
||||
|
||||
@FallbackCmp
|
||||
public class CCmp extends NodeComponent {
|
||||
|
||||
@Override
|
||||
public void process() {
|
||||
System.out.println("CCmp executed!");
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
package com.yomahub.liteflow.test.fallback.cmp;
|
||||
|
||||
import com.yomahub.liteflow.core.NodeComponent;
|
||||
|
||||
public class DCmp extends NodeComponent {
|
||||
|
||||
@Override
|
||||
public void process() throws Exception {
|
||||
throw new RuntimeException("component[d]");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
package com.yomahub.liteflow.test.fallback.cmp;
|
||||
|
||||
import com.yomahub.liteflow.annotation.FallbackCmp;
|
||||
import com.yomahub.liteflow.core.NodeForComponent;
|
||||
|
||||
@FallbackCmp
|
||||
public class ForCmp extends NodeForComponent {
|
||||
|
||||
@Override
|
||||
public int processFor() throws Exception {
|
||||
return 3;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
package com.yomahub.liteflow.test.fallback.cmp;
|
||||
|
||||
import com.yomahub.liteflow.core.NodeIfComponent;
|
||||
|
||||
public class IfCmp1 extends NodeIfComponent {
|
||||
|
||||
@Override
|
||||
public boolean processIf() throws Exception {
|
||||
return true;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
package com.yomahub.liteflow.test.fallback.cmp;
|
||||
|
||||
import com.yomahub.liteflow.annotation.FallbackCmp;
|
||||
import com.yomahub.liteflow.core.NodeIfComponent;
|
||||
|
||||
@FallbackCmp
|
||||
public class IfCmp2 extends NodeIfComponent {
|
||||
|
||||
@Override
|
||||
public boolean processIf() throws Exception {
|
||||
return false;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
package com.yomahub.liteflow.test.fallback.cmp;
|
||||
|
||||
import com.yomahub.liteflow.core.NodeIteratorComponent;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Iterator;
|
||||
|
||||
public class IteratorCmp1 extends NodeIteratorComponent {
|
||||
|
||||
@Override
|
||||
public Iterator<?> processIterator() throws Exception {
|
||||
return Arrays.asList("a", "b", "c").iterator();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
package com.yomahub.liteflow.test.fallback.cmp;
|
||||
|
||||
import com.yomahub.liteflow.annotation.FallbackCmp;
|
||||
import com.yomahub.liteflow.core.NodeIteratorComponent;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
|
||||
@FallbackCmp
|
||||
public class IteratorCmp2 extends NodeIteratorComponent {
|
||||
|
||||
@Override
|
||||
public Iterator<?> processIterator() throws Exception {
|
||||
return Collections.emptyIterator();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
package com.yomahub.liteflow.test.fallback.cmp;
|
||||
|
||||
import com.yomahub.liteflow.core.NodeSwitchComponent;
|
||||
|
||||
public class SwitchCmp1 extends NodeSwitchComponent {
|
||||
|
||||
@Override
|
||||
public String processSwitch() throws Exception {
|
||||
return "a";
|
||||
}
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
package com.yomahub.liteflow.test.fallback.cmp;
|
||||
|
||||
import com.yomahub.liteflow.annotation.FallbackCmp;
|
||||
import com.yomahub.liteflow.core.NodeSwitchComponent;
|
||||
|
||||
@FallbackCmp
|
||||
public class SwitchCmp2 extends NodeSwitchComponent {
|
||||
|
||||
@Override
|
||||
public String processSwitch() throws Exception {
|
||||
return "b";
|
||||
}
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
package com.yomahub.liteflow.test.fallback.cmp;
|
||||
|
||||
import com.yomahub.liteflow.core.NodeWhileComponent;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
public class WhileCmp1 extends NodeWhileComponent {
|
||||
private int count = 0;
|
||||
|
||||
// 执行过的 chain
|
||||
Set<String> executedChain = new HashSet<>();
|
||||
|
||||
@Override
|
||||
public boolean processWhile() throws Exception {
|
||||
// 判断是否切换了 chain
|
||||
if (!executedChain.contains(this.getCurrChainId())) {
|
||||
count = 0;
|
||||
executedChain.add(this.getCurrChainId());
|
||||
}
|
||||
count++;
|
||||
return count <= 3;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
package com.yomahub.liteflow.test.fallback.cmp;
|
||||
|
||||
import com.yomahub.liteflow.annotation.FallbackCmp;
|
||||
import com.yomahub.liteflow.core.NodeWhileComponent;
|
||||
|
||||
@FallbackCmp
|
||||
public class WhileCmp2 extends NodeWhileComponent {
|
||||
|
||||
@Override
|
||||
public boolean processWhile() throws Exception {
|
||||
return false;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,153 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<flow>
|
||||
<nodes>
|
||||
<node id = "a" class="com.yomahub.liteflow.test.fallback.cmp.ACmp"/>
|
||||
<node id = "b" class="com.yomahub.liteflow.test.fallback.cmp.BCmp"/>
|
||||
<node id = "c" class="com.yomahub.liteflow.test.fallback.cmp.CCmp"/>
|
||||
<node id = "d" class="com.yomahub.liteflow.test.fallback.cmp.DCmp"/>
|
||||
<node id = "ifn1" class="com.yomahub.liteflow.test.fallback.cmp.IfCmp1"/>
|
||||
<node id = "ifn2" class="com.yomahub.liteflow.test.fallback.cmp.IfCmp2"/>
|
||||
<node id = "swn1" class="com.yomahub.liteflow.test.fallback.cmp.SwitchCmp1"/>
|
||||
<node id = "swn2" class="com.yomahub.liteflow.test.fallback.cmp.SwitchCmp2"/>
|
||||
<node id = "for1" class="com.yomahub.liteflow.test.fallback.cmp.ForCmp"/>
|
||||
<node id = "wn1" class="com.yomahub.liteflow.test.fallback.cmp.WhileCmp1"/>
|
||||
<node id = "wn2" class="com.yomahub.liteflow.test.fallback.cmp.WhileCmp2"/>
|
||||
<node id = "itn1" class="com.yomahub.liteflow.test.fallback.cmp.IteratorCmp1"/>
|
||||
<node id = "itn2" class="com.yomahub.liteflow.test.fallback.cmp.IteratorCmp2"/>
|
||||
<node id = "bn1" class="com.yomahub.liteflow.test.fallback.cmp.BreakCmp"/>
|
||||
</nodes>
|
||||
|
||||
<!-- THEN 普通组件降级 -->
|
||||
<chain name="then1">
|
||||
THEN(a, node("x"));
|
||||
</chain>
|
||||
|
||||
<chain name="then2">
|
||||
THEN(PRE(node("x1")), node("x2"), FINALLY(node("x3")));
|
||||
</chain>
|
||||
|
||||
<!-- WHEN 普通组件降级 -->
|
||||
<chain name="when1">
|
||||
WHEN(b, node("x"));
|
||||
</chain>
|
||||
|
||||
<!-- IF 条件组件降级 -->
|
||||
<chain name="if1">
|
||||
IF(node("x"), a)
|
||||
</chain>
|
||||
|
||||
<!-- IF 普通组件降级 -->
|
||||
<chain name="if2">
|
||||
IF(ifn1, node("x"))
|
||||
</chain>
|
||||
|
||||
<!-- FOR 次数循环组件降级 -->
|
||||
<chain name="for1">
|
||||
FOR(node("x")).DO(a);
|
||||
</chain>
|
||||
|
||||
<!-- FOR 普通组件降级 -->
|
||||
<chain name="for2">
|
||||
FOR(3).DO(node("x"));
|
||||
</chain>
|
||||
|
||||
<!-- WHILE 条件循环组件降级 -->
|
||||
<chain name="while1">
|
||||
WHILE(node("x")).DO(a)
|
||||
</chain>
|
||||
|
||||
<!-- WHILE 普通组件降级 -->
|
||||
<chain name="while2">
|
||||
WHILE(wn1).DO(node("x"))
|
||||
</chain>
|
||||
|
||||
<!-- ITERATOR 迭代组件降级 -->
|
||||
<chain name="iterator1">
|
||||
ITERATOR(node("x")).DO(a)
|
||||
</chain>
|
||||
|
||||
<!-- ITERATOR 普通组件降级 -->
|
||||
<chain name="iterator2">
|
||||
ITERATOR(itn1).DO(node("x"))
|
||||
</chain>
|
||||
|
||||
<!-- BREAK 退出循环组件降级 -->
|
||||
<chain name="break1">
|
||||
FOR(3).DO(a).BREAK(node("x"));
|
||||
</chain>
|
||||
|
||||
<chain name="break2">
|
||||
WHILE(wn1).DO(a).BREAK(node("x"));
|
||||
</chain>
|
||||
|
||||
<chain name="break3">
|
||||
ITERATOR(itn1).DO(a).BREAK(node("x"));
|
||||
</chain>
|
||||
|
||||
<!-- SWITCH 选择组件降级 -->
|
||||
<chain name="switch1">
|
||||
SWITCH(node("x")).to(a,b);
|
||||
</chain>
|
||||
|
||||
<!-- SWITCH 普通组件降级 -->
|
||||
<chain name="switch2">
|
||||
SWITCH(swn1).to(node("x"),a);
|
||||
</chain>
|
||||
|
||||
<!-- AND 条件组件降级 -->
|
||||
<chain name="and1">
|
||||
IF(AND(node("x"),ifn1), a);
|
||||
</chain>
|
||||
|
||||
<!-- OR 条件组件降级 -->
|
||||
<chain name="or1">
|
||||
IF(OR(node("x"),ifn1), a);
|
||||
</chain>
|
||||
|
||||
<!-- NOT 条件组件降级 -->
|
||||
<chain name="not1">
|
||||
IF(NOT(node("x")), a);
|
||||
</chain>
|
||||
|
||||
<!-- CATCH 普通组件降级 -->
|
||||
<chain name="catch1">
|
||||
CATCH(THEN(a, d)).DO(node("x"))
|
||||
</chain>
|
||||
|
||||
<!-- 多个组件降级 -->
|
||||
<chain name="multi1">
|
||||
THEN(
|
||||
a,
|
||||
node("x1"),
|
||||
IF(node("x2"), b)
|
||||
);
|
||||
</chain>
|
||||
|
||||
<chain name="multi2">
|
||||
IF(
|
||||
OR(node("x1"), ifn1),
|
||||
THEN(a, node("x2"))
|
||||
);
|
||||
</chain>
|
||||
|
||||
<chain name="multi3">
|
||||
FOR(node("x1")).DO(
|
||||
THEN(b, node("x2"))
|
||||
);
|
||||
</chain>
|
||||
|
||||
<!-- 并发降级测试 -->
|
||||
<chain name="concurrent1">
|
||||
WHEN(
|
||||
THEN(node("x1")),
|
||||
IF(node("x2"), b)
|
||||
).maxWaitSeconds(10000);
|
||||
</chain>
|
||||
|
||||
<chain name="concurrent2">
|
||||
WHEN(
|
||||
node("x1"),
|
||||
IF(node("x2"), b)
|
||||
).maxWaitSeconds(10000);
|
||||
</chain>
|
||||
</flow>
|
|
@ -0,0 +1,222 @@
|
|||
package com.yomahub.liteflow.test.fallback;
|
||||
|
||||
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.Inject;
|
||||
import org.noear.solon.test.SolonJUnit5Extension;
|
||||
import org.noear.solon.test.annotation.TestPropertySource;
|
||||
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.Future;
|
||||
|
||||
/**
|
||||
* Solon 降级组件测试
|
||||
*
|
||||
* @author DaleLee
|
||||
* @since 2.11.1
|
||||
*/
|
||||
@ExtendWith(SolonJUnit5Extension.class)
|
||||
@TestPropertySource("classpath:/fallback/application.properties")
|
||||
public class FallbackELSolonTest extends BaseTest {
|
||||
|
||||
@Inject
|
||||
private FlowExecutor flowExecutor;
|
||||
|
||||
@Test
|
||||
public void testThen1() {
|
||||
LiteflowResponse response = flowExecutor.execute2Resp("then1", "arg");
|
||||
Assertions.assertTrue(response.isSuccess());
|
||||
Assertions.assertEquals("a==>c", response.getExecuteStepStrWithoutTime());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testThen2() {
|
||||
LiteflowResponse response = flowExecutor.execute2Resp("then2", "arg");
|
||||
Assertions.assertTrue(response.isSuccess());
|
||||
Assertions.assertEquals("c==>c==>c", response.getExecuteStepStrWithoutTime());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWhen1() {
|
||||
LiteflowResponse response = flowExecutor.execute2Resp("when1", "arg");
|
||||
Assertions.assertTrue(response.isSuccess());
|
||||
String executeStepStr = response.getExecuteStepStrWithoutTime();
|
||||
Assertions.assertTrue("b==>c".equals(executeStepStr) || "c==>b".equals(executeStepStr));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIf1() {
|
||||
LiteflowResponse response = flowExecutor.execute2Resp("if1", "arg");
|
||||
Assertions.assertTrue(response.isSuccess());
|
||||
Assertions.assertEquals("ifn2", response.getExecuteStepStrWithoutTime());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIf2() {
|
||||
LiteflowResponse response = flowExecutor.execute2Resp("if2", "arg");
|
||||
Assertions.assertTrue(response.isSuccess());
|
||||
Assertions.assertEquals("ifn1==>c", response.getExecuteStepStrWithoutTime());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFor1() {
|
||||
LiteflowResponse response = flowExecutor.execute2Resp("for1", "arg");
|
||||
Assertions.assertTrue(response.isSuccess());
|
||||
Assertions.assertEquals("for1==>a==>a==>a", response.getExecuteStepStrWithoutTime());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFor2() {
|
||||
LiteflowResponse response = flowExecutor.execute2Resp("for2", "arg");
|
||||
Assertions.assertTrue(response.isSuccess());
|
||||
Assertions.assertEquals("LOOP_3==>c==>c==>c", response.getExecuteStepStrWithoutTime());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWhile1() {
|
||||
LiteflowResponse response = flowExecutor.execute2Resp("while1", "arg");
|
||||
Assertions.assertTrue(response.isSuccess());
|
||||
Assertions.assertEquals("wn2", response.getExecuteStepStrWithoutTime());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWhile2() {
|
||||
LiteflowResponse response = flowExecutor.execute2Resp("while2", "arg");
|
||||
Assertions.assertTrue(response.isSuccess());
|
||||
Assertions.assertEquals("wn1==>c==>wn1==>c==>wn1==>c==>wn1", response.getExecuteStepStrWithoutTime());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIterator1() {
|
||||
LiteflowResponse response = flowExecutor.execute2Resp("iterator1", "arg");
|
||||
Assertions.assertTrue(response.isSuccess());
|
||||
Assertions.assertEquals("itn2", response.getExecuteStepStrWithoutTime());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIterator2() {
|
||||
LiteflowResponse response = flowExecutor.execute2Resp("iterator2", "arg");
|
||||
Assertions.assertTrue(response.isSuccess());
|
||||
Assertions.assertEquals("itn1==>c==>c==>c", response.getExecuteStepStrWithoutTime());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBreak1() {
|
||||
LiteflowResponse response = flowExecutor.execute2Resp("break1", "arg");
|
||||
Assertions.assertTrue(response.isSuccess());
|
||||
Assertions.assertEquals("LOOP_3==>a==>bn1", response.getExecuteStepStrWithoutTime());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBreak2() {
|
||||
LiteflowResponse response = flowExecutor.execute2Resp("break2", "arg");
|
||||
Assertions.assertTrue(response.isSuccess());
|
||||
Assertions.assertEquals("wn1==>a==>bn1", response.getExecuteStepStrWithoutTime());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBreak3() {
|
||||
LiteflowResponse response = flowExecutor.execute2Resp("break3", "arg");
|
||||
Assertions.assertTrue(response.isSuccess());
|
||||
Assertions.assertEquals("itn1==>a==>bn1", response.getExecuteStepStrWithoutTime());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSwitch1() {
|
||||
LiteflowResponse response = flowExecutor.execute2Resp("switch1", "arg");
|
||||
Assertions.assertTrue(response.isSuccess());
|
||||
Assertions.assertEquals("swn2==>b", response.getExecuteStepStrWithoutTime());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSwitch2() {
|
||||
LiteflowResponse response = flowExecutor.execute2Resp("switch2", "arg");
|
||||
Assertions.assertTrue(response.isSuccess());
|
||||
Assertions.assertEquals("swn1==>a", response.getExecuteStepStrWithoutTime());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAnd1() {
|
||||
LiteflowResponse response = flowExecutor.execute2Resp("and1", "arg");
|
||||
Assertions.assertTrue(response.isSuccess());
|
||||
Assertions.assertEquals("ifn2", response.getExecuteStepStrWithoutTime());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOr1() {
|
||||
LiteflowResponse response = flowExecutor.execute2Resp("or1", "arg");
|
||||
Assertions.assertTrue(response.isSuccess());
|
||||
Assertions.assertEquals("ifn2==>ifn1==>a", response.getExecuteStepStrWithoutTime());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNot1() {
|
||||
LiteflowResponse response = flowExecutor.execute2Resp("not1", "arg");
|
||||
Assertions.assertTrue(response.isSuccess());
|
||||
Assertions.assertEquals("ifn2==>a", response.getExecuteStepStrWithoutTime());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCatch1() {
|
||||
LiteflowResponse response = flowExecutor.execute2Resp("catch1", "arg");
|
||||
Assertions.assertTrue(response.isSuccess());
|
||||
Assertions.assertEquals("a==>d==>c", response.getExecuteStepStrWithoutTime());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMulti1() {
|
||||
LiteflowResponse response = flowExecutor.execute2Resp("multi1", "arg");
|
||||
Assertions.assertTrue(response.isSuccess());
|
||||
Assertions.assertEquals("a==>c==>ifn2", response.getExecuteStepStrWithoutTime());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMulti2() {
|
||||
LiteflowResponse response = flowExecutor.execute2Resp("multi2", "arg");
|
||||
Assertions.assertTrue(response.isSuccess());
|
||||
Assertions.assertEquals("ifn2==>ifn1==>a==>c", response.getExecuteStepStrWithoutTime());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMulti3() {
|
||||
LiteflowResponse response = flowExecutor.execute2Resp("multi3", "arg");
|
||||
Assertions.assertTrue(response.isSuccess());
|
||||
Assertions.assertEquals("for1==>b==>c==>b==>c==>b==>c", response.getExecuteStepStrWithoutTime());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConcurrent1() {
|
||||
LiteflowResponse response = flowExecutor.execute2Resp("concurrent1", "arg");
|
||||
Assertions.assertTrue(response.isSuccess());
|
||||
String stepStr = response.getExecuteStepStrWithoutTime();
|
||||
Assertions.assertTrue("c==>ifn2".equals(stepStr) || "ifn2==>c".equals(stepStr));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConcurrent2() {
|
||||
LiteflowResponse response = flowExecutor.execute2Resp("concurrent2", "arg");
|
||||
Assertions.assertTrue(response.isSuccess());
|
||||
String stepStr = response.getExecuteStepStrWithoutTime();
|
||||
Assertions.assertTrue("c==>ifn2".equals(stepStr) || "ifn2==>c".equals(stepStr));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConcurrent3() throws ExecutionException, InterruptedException {
|
||||
// 执行多条 chain
|
||||
Future<LiteflowResponse> future1 = flowExecutor.execute2Future("concurrent1", "arg", new Object());
|
||||
Future<LiteflowResponse> future2 = flowExecutor.execute2Future("concurrent2", "arg", new Object());
|
||||
Thread.sleep(1000);
|
||||
LiteflowResponse response1 = future1.get();
|
||||
LiteflowResponse response2 = future2.get();
|
||||
Assertions.assertTrue(response1.isSuccess());
|
||||
String stepStr1 = response1.getExecuteStepStrWithoutTime();
|
||||
Assertions.assertTrue("c==>ifn2".equals(stepStr1) || "ifn2==>c".equals(stepStr1));
|
||||
Assertions.assertTrue(response2.isSuccess());
|
||||
String stepStr2 = response2.getExecuteStepStrWithoutTime();
|
||||
Assertions.assertTrue("c==>ifn2".equals(stepStr2) || "ifn2==>c".equals(stepStr2));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
package com.yomahub.liteflow.test.fallback.cmp;
|
||||
|
||||
import com.yomahub.liteflow.annotation.LiteflowComponent;
|
||||
import com.yomahub.liteflow.core.NodeComponent;
|
||||
|
||||
@LiteflowComponent("a")
|
||||
public class ACmp extends NodeComponent {
|
||||
|
||||
@Override
|
||||
public void process() {
|
||||
System.out.println("ACmp executed!");
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
package com.yomahub.liteflow.test.fallback.cmp;
|
||||
|
||||
import com.yomahub.liteflow.annotation.LiteflowComponent;
|
||||
import com.yomahub.liteflow.core.NodeComponent;
|
||||
|
||||
@LiteflowComponent("b")
|
||||
public class BCmp extends NodeComponent {
|
||||
|
||||
@Override
|
||||
public void process() {
|
||||
System.out.println("BCmp executed!");
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
package com.yomahub.liteflow.test.fallback.cmp;
|
||||
|
||||
import com.yomahub.liteflow.annotation.FallbackCmp;
|
||||
import com.yomahub.liteflow.annotation.LiteflowComponent;
|
||||
import com.yomahub.liteflow.core.NodeBreakComponent;
|
||||
|
||||
@LiteflowComponent("bn1")
|
||||
@FallbackCmp
|
||||
public class BreakCmp extends NodeBreakComponent {
|
||||
|
||||
@Override
|
||||
public boolean processBreak() throws Exception {
|
||||
return true;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
package com.yomahub.liteflow.test.fallback.cmp;
|
||||
|
||||
import com.yomahub.liteflow.annotation.FallbackCmp;
|
||||
import com.yomahub.liteflow.annotation.LiteflowComponent;
|
||||
import com.yomahub.liteflow.core.NodeComponent;
|
||||
|
||||
@LiteflowComponent("c")
|
||||
@FallbackCmp
|
||||
public class CCmp extends NodeComponent {
|
||||
|
||||
@Override
|
||||
public void process() {
|
||||
System.out.println("CCmp executed!");
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
package com.yomahub.liteflow.test.fallback.cmp;
|
||||
|
||||
import com.yomahub.liteflow.annotation.LiteflowComponent;
|
||||
import com.yomahub.liteflow.core.NodeComponent;
|
||||
|
||||
@LiteflowComponent("d")
|
||||
public class DCmp extends NodeComponent {
|
||||
|
||||
@Override
|
||||
public void process() throws Exception {
|
||||
throw new RuntimeException("component[d]");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
package com.yomahub.liteflow.test.fallback.cmp;
|
||||
|
||||
import com.yomahub.liteflow.annotation.FallbackCmp;
|
||||
import com.yomahub.liteflow.annotation.LiteflowComponent;
|
||||
import com.yomahub.liteflow.core.NodeForComponent;
|
||||
|
||||
@LiteflowComponent("for1")
|
||||
@FallbackCmp
|
||||
public class ForCmp extends NodeForComponent {
|
||||
|
||||
@Override
|
||||
public int processFor() throws Exception {
|
||||
return 3;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
package com.yomahub.liteflow.test.fallback.cmp;
|
||||
|
||||
import com.yomahub.liteflow.annotation.LiteflowComponent;
|
||||
import com.yomahub.liteflow.core.NodeIfComponent;
|
||||
|
||||
@LiteflowComponent("ifn1")
|
||||
public class IfCmp1 extends NodeIfComponent {
|
||||
|
||||
@Override
|
||||
public boolean processIf() throws Exception {
|
||||
return true;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
package com.yomahub.liteflow.test.fallback.cmp;
|
||||
|
||||
import com.yomahub.liteflow.annotation.FallbackCmp;
|
||||
import com.yomahub.liteflow.annotation.LiteflowComponent;
|
||||
import com.yomahub.liteflow.core.NodeIfComponent;
|
||||
|
||||
@LiteflowComponent("ifn2")
|
||||
@FallbackCmp
|
||||
public class IfCmp2 extends NodeIfComponent {
|
||||
|
||||
@Override
|
||||
public boolean processIf() throws Exception {
|
||||
return false;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
package com.yomahub.liteflow.test.fallback.cmp;
|
||||
|
||||
import com.yomahub.liteflow.annotation.LiteflowComponent;
|
||||
import com.yomahub.liteflow.core.NodeIteratorComponent;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Iterator;
|
||||
|
||||
@LiteflowComponent("itn1")
|
||||
public class IteratorCmp1 extends NodeIteratorComponent {
|
||||
|
||||
@Override
|
||||
public Iterator<?> processIterator() throws Exception {
|
||||
return Arrays.asList("a", "b", "c").iterator();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
package com.yomahub.liteflow.test.fallback.cmp;
|
||||
|
||||
import com.yomahub.liteflow.annotation.FallbackCmp;
|
||||
import com.yomahub.liteflow.annotation.LiteflowComponent;
|
||||
import com.yomahub.liteflow.core.NodeIteratorComponent;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
|
||||
@LiteflowComponent("itn2")
|
||||
@FallbackCmp
|
||||
public class IteratorCmp2 extends NodeIteratorComponent {
|
||||
|
||||
@Override
|
||||
public Iterator<?> processIterator() throws Exception {
|
||||
return Collections.emptyIterator();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
package com.yomahub.liteflow.test.fallback.cmp;
|
||||
|
||||
import com.yomahub.liteflow.annotation.LiteflowComponent;
|
||||
import com.yomahub.liteflow.core.NodeSwitchComponent;
|
||||
|
||||
@LiteflowComponent("swn1")
|
||||
public class SwitchCmp1 extends NodeSwitchComponent {
|
||||
|
||||
@Override
|
||||
public String processSwitch() throws Exception {
|
||||
return "a";
|
||||
}
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
package com.yomahub.liteflow.test.fallback.cmp;
|
||||
|
||||
import com.yomahub.liteflow.annotation.FallbackCmp;
|
||||
import com.yomahub.liteflow.annotation.LiteflowComponent;
|
||||
import com.yomahub.liteflow.core.NodeSwitchComponent;
|
||||
|
||||
@LiteflowComponent("swn2")
|
||||
@FallbackCmp
|
||||
public class SwitchCmp2 extends NodeSwitchComponent {
|
||||
|
||||
@Override
|
||||
public String processSwitch() throws Exception {
|
||||
return "b";
|
||||
}
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
package com.yomahub.liteflow.test.fallback.cmp;
|
||||
|
||||
import com.yomahub.liteflow.annotation.LiteflowComponent;
|
||||
import com.yomahub.liteflow.core.NodeWhileComponent;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
@LiteflowComponent("wn1")
|
||||
public class WhileCmp1 extends NodeWhileComponent {
|
||||
private int count = 0;
|
||||
|
||||
// 执行过的 chain
|
||||
Set<String> executedChain = new HashSet<>();
|
||||
|
||||
@Override
|
||||
public boolean processWhile() throws Exception {
|
||||
// 判断是否切换了 chain
|
||||
if (!executedChain.contains(this.getCurrChainId())) {
|
||||
count = 0;
|
||||
executedChain.add(this.getCurrChainId());
|
||||
}
|
||||
count++;
|
||||
return count <= 3;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
package com.yomahub.liteflow.test.fallback.cmp;
|
||||
|
||||
import com.yomahub.liteflow.annotation.FallbackCmp;
|
||||
import com.yomahub.liteflow.annotation.LiteflowComponent;
|
||||
import com.yomahub.liteflow.core.NodeWhileComponent;
|
||||
|
||||
@LiteflowComponent("wn2")
|
||||
@FallbackCmp
|
||||
public class WhileCmp2 extends NodeWhileComponent {
|
||||
|
||||
@Override
|
||||
public boolean processWhile() throws Exception {
|
||||
return false;
|
||||
}
|
||||
}
|
|
@ -1,46 +0,0 @@
|
|||
package com.yomahub.liteflow.test.substituteNode;
|
||||
|
||||
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.Inject;
|
||||
import org.noear.solon.test.SolonJUnit5Extension;
|
||||
import org.noear.solon.test.annotation.TestPropertySource;
|
||||
|
||||
/**
|
||||
* springboot环境EL替补节点的测试
|
||||
*
|
||||
* @author Bryan.Zhang
|
||||
*/
|
||||
@ExtendWith(SolonJUnit5Extension.class)
|
||||
@TestPropertySource("classpath:/substituteNode/application.properties")
|
||||
public class SubstituteSpringbootTest extends BaseTest {
|
||||
|
||||
@Inject
|
||||
private FlowExecutor flowExecutor;
|
||||
|
||||
// 最简单的情况
|
||||
@Test
|
||||
public void testSub1() throws Exception {
|
||||
LiteflowResponse response = flowExecutor.execute2Resp("chain1", "arg");
|
||||
Assertions.assertTrue(response.isSuccess());
|
||||
}
|
||||
|
||||
// 有替补节点
|
||||
@Test
|
||||
public void testSub2() throws Exception {
|
||||
LiteflowResponse response = flowExecutor.execute2Resp("chain2", "arg");
|
||||
Assertions.assertTrue(response.isSuccess());
|
||||
}
|
||||
|
||||
// 测试特殊命名的节点
|
||||
@Test
|
||||
public void testSub3() throws Exception {
|
||||
LiteflowResponse response = flowExecutor.execute2Resp("chain3", "arg");
|
||||
Assertions.assertTrue(response.isSuccess());
|
||||
}
|
||||
|
||||
}
|
|
@ -1,21 +0,0 @@
|
|||
/**
|
||||
* <p>Title: liteflow</p>
|
||||
* <p>Description: 轻量级的组件式流程框架</p>
|
||||
* @author Bryan.Zhang
|
||||
* @email weenyc31@163.com
|
||||
* @Date 2020/4/1
|
||||
*/
|
||||
package com.yomahub.liteflow.test.substituteNode.cmp;
|
||||
|
||||
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("ACmp executed!");
|
||||
}
|
||||
|
||||
}
|
|
@ -1,21 +0,0 @@
|
|||
/**
|
||||
* <p>Title: liteflow</p>
|
||||
* <p>Description: 轻量级的组件式流程框架</p>
|
||||
* @author Bryan.Zhang
|
||||
* @email weenyc31@163.com
|
||||
* @Date 2020/4/1
|
||||
*/
|
||||
package com.yomahub.liteflow.test.substituteNode.cmp;
|
||||
|
||||
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("BCmp executed!");
|
||||
}
|
||||
|
||||
}
|
|
@ -1,21 +0,0 @@
|
|||
/**
|
||||
* <p>Title: liteflow</p>
|
||||
* <p>Description: 轻量级的组件式流程框架</p>
|
||||
* @author Bryan.Zhang
|
||||
* @email weenyc31@163.com
|
||||
* @Date 2020/4/1
|
||||
*/
|
||||
package com.yomahub.liteflow.test.substituteNode.cmp;
|
||||
|
||||
import com.yomahub.liteflow.core.NodeComponent;
|
||||
import org.noear.solon.annotation.Component;
|
||||
|
||||
@Component("c")
|
||||
public class CCmp extends NodeComponent {
|
||||
|
||||
@Override
|
||||
public void process() {
|
||||
System.out.println("CCmp executed!");
|
||||
}
|
||||
|
||||
}
|
|
@ -1,21 +0,0 @@
|
|||
/**
|
||||
* <p>Title: liteflow</p>
|
||||
* <p>Description: 轻量级的组件式流程框架</p>
|
||||
* @author Bryan.Zhang
|
||||
* @email weenyc31@163.com
|
||||
* @Date 2020/4/1
|
||||
*/
|
||||
package com.yomahub.liteflow.test.substituteNode.cmp;
|
||||
|
||||
import com.yomahub.liteflow.core.NodeComponent;
|
||||
import org.noear.solon.annotation.Component;
|
||||
|
||||
@Component("88-ffc")
|
||||
public class DCmp extends NodeComponent {
|
||||
|
||||
@Override
|
||||
public void process() {
|
||||
System.out.println("DCmp executed!");
|
||||
}
|
||||
|
||||
}
|
|
@ -1,21 +0,0 @@
|
|||
/**
|
||||
* <p>Title: liteflow</p>
|
||||
* <p>Description: 轻量级的组件式流程框架</p>
|
||||
* @author Bryan.Zhang
|
||||
* @email weenyc31@163.com
|
||||
* @Date 2020/4/1
|
||||
*/
|
||||
package com.yomahub.liteflow.test.substituteNode.cmp;
|
||||
|
||||
import com.yomahub.liteflow.core.NodeComponent;
|
||||
import org.noear.solon.annotation.Component;
|
||||
|
||||
@Component("sub")
|
||||
public class SubCmp extends NodeComponent {
|
||||
|
||||
@Override
|
||||
public void process() {
|
||||
System.out.println("SubCmp executed!");
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,2 @@
|
|||
liteflow.rule-source=fallback/flow.el.xml
|
||||
liteflow.fallback-cmp-enable=true
|
|
@ -0,0 +1,136 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<flow>
|
||||
<!-- THEN 普通组件降级 -->
|
||||
<chain name="then1">
|
||||
THEN(a, node("x"));
|
||||
</chain>
|
||||
|
||||
<chain name="then2">
|
||||
THEN(PRE(node("x1")), node("x2"), FINALLY(node("x3")));
|
||||
</chain>
|
||||
|
||||
<!-- WHEN 普通组件降级 -->
|
||||
<chain name="when1">
|
||||
WHEN(b, node("x"));
|
||||
</chain>
|
||||
|
||||
<!-- IF 条件组件降级 -->
|
||||
<chain name="if1">
|
||||
IF(node("x"), a)
|
||||
</chain>
|
||||
|
||||
<!-- IF 普通组件降级 -->
|
||||
<chain name="if2">
|
||||
IF(ifn1, node("x"))
|
||||
</chain>
|
||||
|
||||
<!-- FOR 次数循环组件降级 -->
|
||||
<chain name="for1">
|
||||
FOR(node("x")).DO(a);
|
||||
</chain>
|
||||
|
||||
<!-- FOR 普通组件降级 -->
|
||||
<chain name="for2">
|
||||
FOR(3).DO(node("x"));
|
||||
</chain>
|
||||
|
||||
<!-- WHILE 条件循环组件降级 -->
|
||||
<chain name="while1">
|
||||
WHILE(node("x")).DO(a)
|
||||
</chain>
|
||||
|
||||
<!-- WHILE 普通组件降级 -->
|
||||
<chain name="while2">
|
||||
WHILE(wn1).DO(node("x"))
|
||||
</chain>
|
||||
|
||||
<!-- ITERATOR 迭代组件降级 -->
|
||||
<chain name="iterator1">
|
||||
ITERATOR(node("x")).DO(a)
|
||||
</chain>
|
||||
|
||||
<!-- ITERATOR 普通组件降级 -->
|
||||
<chain name="iterator2">
|
||||
ITERATOR(itn1).DO(node("x"))
|
||||
</chain>
|
||||
|
||||
<!-- BREAK 退出循环组件降级 -->
|
||||
<chain name="break1">
|
||||
FOR(3).DO(a).BREAK(node("x"));
|
||||
</chain>
|
||||
|
||||
<chain name="break2">
|
||||
WHILE(wn1).DO(a).BREAK(node("x"));
|
||||
</chain>
|
||||
|
||||
<chain name="break3">
|
||||
ITERATOR(itn1).DO(a).BREAK(node("x"));
|
||||
</chain>
|
||||
|
||||
<!-- SWITCH 选择组件降级 -->
|
||||
<chain name="switch1">
|
||||
SWITCH(node("x")).to(a,b);
|
||||
</chain>
|
||||
|
||||
<!-- SWITCH 普通组件降级 -->
|
||||
<chain name="switch2">
|
||||
SWITCH(swn1).to(node("x"),a);
|
||||
</chain>
|
||||
|
||||
<!-- AND 条件组件降级 -->
|
||||
<chain name="and1">
|
||||
IF(AND(node("x"),ifn1), a);
|
||||
</chain>
|
||||
|
||||
<!-- OR 条件组件降级 -->
|
||||
<chain name="or1">
|
||||
IF(OR(node("x"),ifn1), a);
|
||||
</chain>
|
||||
|
||||
<!-- NOT 条件组件降级 -->
|
||||
<chain name="not1">
|
||||
IF(NOT(node("x")), a);
|
||||
</chain>
|
||||
|
||||
<!-- CATCH 普通组件降级 -->
|
||||
<chain name="catch1">
|
||||
CATCH(THEN(a, d)).DO(node("x"))
|
||||
</chain>
|
||||
|
||||
<!-- 多个组件降级 -->
|
||||
<chain name="multi1">
|
||||
THEN(
|
||||
a,
|
||||
node("x1"),
|
||||
IF(node("x2"), b)
|
||||
);
|
||||
</chain>
|
||||
|
||||
<chain name="multi2">
|
||||
IF(
|
||||
OR(node("x1"), ifn1),
|
||||
THEN(a, node("x2"))
|
||||
);
|
||||
</chain>
|
||||
|
||||
<chain name="multi3">
|
||||
FOR(node("x1")).DO(
|
||||
THEN(b, node("x2"))
|
||||
);
|
||||
</chain>
|
||||
|
||||
<!-- 并发降级测试 -->
|
||||
<chain name="concurrent1">
|
||||
WHEN(
|
||||
THEN(node("x1")),
|
||||
IF(node("x2"), b)
|
||||
).maxWaitSeconds(10000);
|
||||
</chain>
|
||||
|
||||
<chain name="concurrent2">
|
||||
WHEN(
|
||||
node("x1"),
|
||||
IF(node("x2"), b)
|
||||
).maxWaitSeconds(10000);
|
||||
</chain>
|
||||
</flow>
|
|
@ -1,2 +0,0 @@
|
|||
liteflow.rule-source=substituteNode/flow.el.xml
|
||||
liteflow.substitute-cmp-class=com.yomahub.liteflow.test.substituteNode.cmp.SubCmp
|
|
@ -1,14 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<flow>
|
||||
<chain name="chain1">
|
||||
THEN(node("a"), node("b"), node("c"));
|
||||
</chain>
|
||||
|
||||
<chain name="chain2">
|
||||
THEN(node("a"), node("b"), node("93-nodeTEST"));
|
||||
</chain>
|
||||
|
||||
<chain name="chain3">
|
||||
THEN(a, b, node("88-ffc"));
|
||||
</chain>
|
||||
</flow>
|
|
@ -0,0 +1,225 @@
|
|||
package com.yomahub.liteflow.test.fallback;
|
||||
|
||||
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.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.context.annotation.ComponentScan;
|
||||
import org.springframework.test.context.TestPropertySource;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.Future;
|
||||
|
||||
/**
|
||||
* SpringBoot 降级组件测试
|
||||
*
|
||||
* @author DaleLee
|
||||
* @since 2.11.1
|
||||
*/
|
||||
@TestPropertySource(value = "classpath:/fallback/application.properties")
|
||||
@SpringBootTest(classes = FallbackELSpringbootTest.class)
|
||||
@EnableAutoConfiguration
|
||||
@ComponentScan({"com.yomahub.liteflow.test.fallback.cmp"})
|
||||
public class FallbackELSpringbootTest extends BaseTest {
|
||||
|
||||
@Resource
|
||||
private FlowExecutor flowExecutor;
|
||||
|
||||
@Test
|
||||
public void testThen1() {
|
||||
LiteflowResponse response = flowExecutor.execute2Resp("then1", "arg");
|
||||
Assertions.assertTrue(response.isSuccess());
|
||||
Assertions.assertEquals("a==>c", response.getExecuteStepStrWithoutTime());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testThen2() {
|
||||
LiteflowResponse response = flowExecutor.execute2Resp("then2", "arg");
|
||||
Assertions.assertTrue(response.isSuccess());
|
||||
Assertions.assertEquals("c==>c==>c", response.getExecuteStepStrWithoutTime());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWhen1() {
|
||||
LiteflowResponse response = flowExecutor.execute2Resp("when1", "arg");
|
||||
Assertions.assertTrue(response.isSuccess());
|
||||
String executeStepStr = response.getExecuteStepStrWithoutTime();
|
||||
Assertions.assertTrue("b==>c".equals(executeStepStr) || "c==>b".equals(executeStepStr));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIf1() {
|
||||
LiteflowResponse response = flowExecutor.execute2Resp("if1", "arg");
|
||||
Assertions.assertTrue(response.isSuccess());
|
||||
Assertions.assertEquals("ifn2", response.getExecuteStepStrWithoutTime());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIf2() {
|
||||
LiteflowResponse response = flowExecutor.execute2Resp("if2", "arg");
|
||||
Assertions.assertTrue(response.isSuccess());
|
||||
Assertions.assertEquals("ifn1==>c", response.getExecuteStepStrWithoutTime());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFor1() {
|
||||
LiteflowResponse response = flowExecutor.execute2Resp("for1", "arg");
|
||||
Assertions.assertTrue(response.isSuccess());
|
||||
Assertions.assertEquals("for1==>a==>a==>a", response.getExecuteStepStrWithoutTime());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFor2() {
|
||||
LiteflowResponse response = flowExecutor.execute2Resp("for2", "arg");
|
||||
Assertions.assertTrue(response.isSuccess());
|
||||
Assertions.assertEquals("LOOP_3==>c==>c==>c", response.getExecuteStepStrWithoutTime());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWhile1() {
|
||||
LiteflowResponse response = flowExecutor.execute2Resp("while1", "arg");
|
||||
Assertions.assertTrue(response.isSuccess());
|
||||
Assertions.assertEquals("wn2", response.getExecuteStepStrWithoutTime());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWhile2() {
|
||||
LiteflowResponse response = flowExecutor.execute2Resp("while2", "arg");
|
||||
Assertions.assertTrue(response.isSuccess());
|
||||
Assertions.assertEquals("wn1==>c==>wn1==>c==>wn1==>c==>wn1", response.getExecuteStepStrWithoutTime());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIterator1() {
|
||||
LiteflowResponse response = flowExecutor.execute2Resp("iterator1", "arg");
|
||||
Assertions.assertTrue(response.isSuccess());
|
||||
Assertions.assertEquals("itn2", response.getExecuteStepStrWithoutTime());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIterator2() {
|
||||
LiteflowResponse response = flowExecutor.execute2Resp("iterator2", "arg");
|
||||
Assertions.assertTrue(response.isSuccess());
|
||||
Assertions.assertEquals("itn1==>c==>c==>c", response.getExecuteStepStrWithoutTime());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBreak1() {
|
||||
LiteflowResponse response = flowExecutor.execute2Resp("break1", "arg");
|
||||
Assertions.assertTrue(response.isSuccess());
|
||||
Assertions.assertEquals("LOOP_3==>a==>bn1", response.getExecuteStepStrWithoutTime());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBreak2() {
|
||||
LiteflowResponse response = flowExecutor.execute2Resp("break2", "arg");
|
||||
Assertions.assertTrue(response.isSuccess());
|
||||
Assertions.assertEquals("wn1==>a==>bn1", response.getExecuteStepStrWithoutTime());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBreak3() {
|
||||
LiteflowResponse response = flowExecutor.execute2Resp("break3", "arg");
|
||||
Assertions.assertTrue(response.isSuccess());
|
||||
Assertions.assertEquals("itn1==>a==>bn1", response.getExecuteStepStrWithoutTime());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSwitch1() {
|
||||
LiteflowResponse response = flowExecutor.execute2Resp("switch1", "arg");
|
||||
Assertions.assertTrue(response.isSuccess());
|
||||
Assertions.assertEquals("swn2==>b", response.getExecuteStepStrWithoutTime());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSwitch2() {
|
||||
LiteflowResponse response = flowExecutor.execute2Resp("switch2", "arg");
|
||||
Assertions.assertTrue(response.isSuccess());
|
||||
Assertions.assertEquals("swn1==>a", response.getExecuteStepStrWithoutTime());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAnd1() {
|
||||
LiteflowResponse response = flowExecutor.execute2Resp("and1", "arg");
|
||||
Assertions.assertTrue(response.isSuccess());
|
||||
Assertions.assertEquals("ifn2", response.getExecuteStepStrWithoutTime());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOr1() {
|
||||
LiteflowResponse response = flowExecutor.execute2Resp("or1", "arg");
|
||||
Assertions.assertTrue(response.isSuccess());
|
||||
Assertions.assertEquals("ifn2==>ifn1==>a", response.getExecuteStepStrWithoutTime());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNot1() {
|
||||
LiteflowResponse response = flowExecutor.execute2Resp("not1", "arg");
|
||||
Assertions.assertTrue(response.isSuccess());
|
||||
Assertions.assertEquals("ifn2==>a", response.getExecuteStepStrWithoutTime());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCatch1() {
|
||||
LiteflowResponse response = flowExecutor.execute2Resp("catch1", "arg");
|
||||
Assertions.assertTrue(response.isSuccess());
|
||||
Assertions.assertEquals("a==>d==>c", response.getExecuteStepStrWithoutTime());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMulti1() {
|
||||
LiteflowResponse response = flowExecutor.execute2Resp("multi1", "arg");
|
||||
Assertions.assertTrue(response.isSuccess());
|
||||
Assertions.assertEquals("a==>c==>ifn2", response.getExecuteStepStrWithoutTime());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMulti2() {
|
||||
LiteflowResponse response = flowExecutor.execute2Resp("multi2", "arg");
|
||||
Assertions.assertTrue(response.isSuccess());
|
||||
Assertions.assertEquals("ifn2==>ifn1==>a==>c", response.getExecuteStepStrWithoutTime());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMulti3() {
|
||||
LiteflowResponse response = flowExecutor.execute2Resp("multi3", "arg");
|
||||
Assertions.assertTrue(response.isSuccess());
|
||||
Assertions.assertEquals("for1==>b==>c==>b==>c==>b==>c", response.getExecuteStepStrWithoutTime());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConcurrent1() {
|
||||
LiteflowResponse response = flowExecutor.execute2Resp("concurrent1", "arg");
|
||||
Assertions.assertTrue(response.isSuccess());
|
||||
String stepStr = response.getExecuteStepStrWithoutTime();
|
||||
Assertions.assertTrue("c==>ifn2".equals(stepStr) || "ifn2==>c".equals(stepStr));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConcurrent2() {
|
||||
LiteflowResponse response = flowExecutor.execute2Resp("concurrent2", "arg");
|
||||
Assertions.assertTrue(response.isSuccess());
|
||||
String stepStr = response.getExecuteStepStrWithoutTime();
|
||||
Assertions.assertTrue("c==>ifn2".equals(stepStr) || "ifn2==>c".equals(stepStr));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConcurrent3() throws ExecutionException, InterruptedException {
|
||||
// 执行多条 chain
|
||||
Future<LiteflowResponse> future1 = flowExecutor.execute2Future("concurrent1", "arg", new Object());
|
||||
Future<LiteflowResponse> future2 = flowExecutor.execute2Future("concurrent2", "arg", new Object());
|
||||
Thread.sleep(1000);
|
||||
LiteflowResponse response1 = future1.get();
|
||||
LiteflowResponse response2 = future2.get();
|
||||
Assertions.assertTrue(response1.isSuccess());
|
||||
String stepStr1 = response1.getExecuteStepStrWithoutTime();
|
||||
Assertions.assertTrue("c==>ifn2".equals(stepStr1) || "ifn2==>c".equals(stepStr1));
|
||||
Assertions.assertTrue(response2.isSuccess());
|
||||
String stepStr2 = response2.getExecuteStepStrWithoutTime();
|
||||
Assertions.assertTrue("c==>ifn2".equals(stepStr2) || "ifn2==>c".equals(stepStr2));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
package com.yomahub.liteflow.test.fallback.cmp;
|
||||
|
||||
import com.yomahub.liteflow.annotation.LiteflowComponent;
|
||||
import com.yomahub.liteflow.core.NodeComponent;
|
||||
|
||||
@LiteflowComponent("a")
|
||||
public class ACmp extends NodeComponent {
|
||||
|
||||
@Override
|
||||
public void process() {
|
||||
System.out.println("ACmp executed!");
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
package com.yomahub.liteflow.test.fallback.cmp;
|
||||
|
||||
import com.yomahub.liteflow.annotation.LiteflowComponent;
|
||||
import com.yomahub.liteflow.core.NodeComponent;
|
||||
import com.yomahub.liteflow.test.customNodes.domain.DemoDomain;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
@LiteflowComponent("b")
|
||||
public class BCmp extends NodeComponent {
|
||||
|
||||
@Override
|
||||
public void process() {
|
||||
System.out.println("BCmp executed!");
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
package com.yomahub.liteflow.test.fallback.cmp;
|
||||
|
||||
import com.yomahub.liteflow.annotation.FallbackCmp;
|
||||
import com.yomahub.liteflow.annotation.LiteflowComponent;
|
||||
import com.yomahub.liteflow.core.NodeBreakComponent;
|
||||
|
||||
@LiteflowComponent("bn1")
|
||||
@FallbackCmp
|
||||
public class BreakCmp extends NodeBreakComponent {
|
||||
|
||||
@Override
|
||||
public boolean processBreak() throws Exception {
|
||||
return true;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
package com.yomahub.liteflow.test.fallback.cmp;
|
||||
|
||||
import com.yomahub.liteflow.annotation.FallbackCmp;
|
||||
import com.yomahub.liteflow.annotation.LiteflowComponent;
|
||||
import com.yomahub.liteflow.core.NodeComponent;
|
||||
import com.yomahub.liteflow.slot.DefaultContext;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@LiteflowComponent("c")
|
||||
@FallbackCmp
|
||||
public class CCmp extends NodeComponent {
|
||||
|
||||
@Override
|
||||
public void process() {
|
||||
System.out.println("CCmp executed!");
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
package com.yomahub.liteflow.test.fallback.cmp;
|
||||
|
||||
import com.yomahub.liteflow.annotation.LiteflowComponent;
|
||||
import com.yomahub.liteflow.core.NodeComponent;
|
||||
|
||||
@LiteflowComponent("d")
|
||||
public class DCmp extends NodeComponent {
|
||||
|
||||
@Override
|
||||
public void process() throws Exception {
|
||||
throw new RuntimeException("component[d]");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
package com.yomahub.liteflow.test.fallback.cmp;
|
||||
|
||||
import com.yomahub.liteflow.annotation.FallbackCmp;
|
||||
import com.yomahub.liteflow.annotation.LiteflowComponent;
|
||||
import com.yomahub.liteflow.core.NodeForComponent;
|
||||
|
||||
@LiteflowComponent("for1")
|
||||
@FallbackCmp
|
||||
public class ForCmp extends NodeForComponent {
|
||||
|
||||
@Override
|
||||
public int processFor() throws Exception {
|
||||
return 3;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
package com.yomahub.liteflow.test.fallback.cmp;
|
||||
|
||||
import com.yomahub.liteflow.annotation.LiteflowComponent;
|
||||
import com.yomahub.liteflow.core.NodeIfComponent;
|
||||
|
||||
@LiteflowComponent("ifn1")
|
||||
public class IfCmp1 extends NodeIfComponent {
|
||||
|
||||
@Override
|
||||
public boolean processIf() throws Exception {
|
||||
return true;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
package com.yomahub.liteflow.test.fallback.cmp;
|
||||
|
||||
import com.yomahub.liteflow.annotation.FallbackCmp;
|
||||
import com.yomahub.liteflow.annotation.LiteflowComponent;
|
||||
import com.yomahub.liteflow.core.NodeIfComponent;
|
||||
|
||||
@LiteflowComponent("ifn2")
|
||||
@FallbackCmp
|
||||
public class IfCmp2 extends NodeIfComponent {
|
||||
|
||||
@Override
|
||||
public boolean processIf() throws Exception {
|
||||
return false;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
package com.yomahub.liteflow.test.fallback.cmp;
|
||||
|
||||
import com.yomahub.liteflow.annotation.LiteflowComponent;
|
||||
import com.yomahub.liteflow.core.NodeIteratorComponent;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Iterator;
|
||||
|
||||
@LiteflowComponent("itn1")
|
||||
public class IteratorCmp1 extends NodeIteratorComponent {
|
||||
|
||||
@Override
|
||||
public Iterator<?> processIterator() throws Exception {
|
||||
return Arrays.asList("a", "b", "c").iterator();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
package com.yomahub.liteflow.test.fallback.cmp;
|
||||
|
||||
import com.yomahub.liteflow.annotation.FallbackCmp;
|
||||
import com.yomahub.liteflow.annotation.LiteflowComponent;
|
||||
import com.yomahub.liteflow.core.NodeIteratorComponent;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
|
||||
@LiteflowComponent("itn2")
|
||||
@FallbackCmp
|
||||
public class IteratorCmp2 extends NodeIteratorComponent {
|
||||
|
||||
@Override
|
||||
public Iterator<?> processIterator() throws Exception {
|
||||
return Collections.emptyIterator();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
package com.yomahub.liteflow.test.fallback.cmp;
|
||||
|
||||
import com.yomahub.liteflow.annotation.LiteflowComponent;
|
||||
import com.yomahub.liteflow.core.NodeSwitchComponent;
|
||||
|
||||
@LiteflowComponent("swn1")
|
||||
public class SwitchCmp1 extends NodeSwitchComponent {
|
||||
|
||||
@Override
|
||||
public String processSwitch() throws Exception {
|
||||
return "a";
|
||||
}
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
package com.yomahub.liteflow.test.fallback.cmp;
|
||||
|
||||
import com.yomahub.liteflow.annotation.FallbackCmp;
|
||||
import com.yomahub.liteflow.annotation.LiteflowComponent;
|
||||
import com.yomahub.liteflow.core.NodeSwitchComponent;
|
||||
|
||||
@LiteflowComponent("swn2")
|
||||
@FallbackCmp
|
||||
public class SwitchCmp2 extends NodeSwitchComponent {
|
||||
|
||||
@Override
|
||||
public String processSwitch() throws Exception {
|
||||
return "b";
|
||||
}
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
package com.yomahub.liteflow.test.fallback.cmp;
|
||||
|
||||
import com.yomahub.liteflow.annotation.LiteflowComponent;
|
||||
import com.yomahub.liteflow.core.NodeWhileComponent;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
@LiteflowComponent("wn1")
|
||||
public class WhileCmp1 extends NodeWhileComponent {
|
||||
private int count = 0;
|
||||
|
||||
// 执行过的 chain
|
||||
Set<String> executedChain = new HashSet<>();
|
||||
|
||||
@Override
|
||||
public boolean processWhile() throws Exception {
|
||||
// 判断是否切换了 chain
|
||||
if (!executedChain.contains(this.getCurrChainId())) {
|
||||
count = 0;
|
||||
executedChain.add(this.getCurrChainId());
|
||||
}
|
||||
count++;
|
||||
return count <= 3;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
package com.yomahub.liteflow.test.fallback.cmp;
|
||||
|
||||
import com.yomahub.liteflow.annotation.FallbackCmp;
|
||||
import com.yomahub.liteflow.annotation.LiteflowComponent;
|
||||
import com.yomahub.liteflow.core.NodeWhileComponent;
|
||||
|
||||
@LiteflowComponent("wn2")
|
||||
@FallbackCmp
|
||||
public class WhileCmp2 extends NodeWhileComponent {
|
||||
|
||||
@Override
|
||||
public boolean processWhile() throws Exception {
|
||||
return false;
|
||||
}
|
||||
}
|
|
@ -1,50 +0,0 @@
|
|||
package com.yomahub.liteflow.test.substituteNode;
|
||||
|
||||
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.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.context.annotation.ComponentScan;
|
||||
import org.springframework.test.context.TestPropertySource;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
/**
|
||||
* springboot环境EL替补节点的测试
|
||||
*
|
||||
* @author Bryan.Zhang
|
||||
*/
|
||||
@TestPropertySource(value = "classpath:/substituteNode/application.properties")
|
||||
@SpringBootTest(classes = SubstituteSpringbootTest.class)
|
||||
@EnableAutoConfiguration
|
||||
@ComponentScan({ "com.yomahub.liteflow.test.substituteNode.cmp" })
|
||||
public class SubstituteSpringbootTest extends BaseTest {
|
||||
|
||||
@Resource
|
||||
private FlowExecutor flowExecutor;
|
||||
|
||||
// 最简单的情况
|
||||
@Test
|
||||
public void testSub1() throws Exception {
|
||||
LiteflowResponse response = flowExecutor.execute2Resp("chain1", "arg");
|
||||
Assertions.assertTrue(response.isSuccess());
|
||||
}
|
||||
|
||||
// 有替补节点
|
||||
@Test
|
||||
public void testSub2() throws Exception {
|
||||
LiteflowResponse response = flowExecutor.execute2Resp("chain2", "arg");
|
||||
Assertions.assertTrue(response.isSuccess());
|
||||
}
|
||||
|
||||
// 测试特殊命名的节点
|
||||
@Test
|
||||
public void testSub3() throws Exception {
|
||||
LiteflowResponse response = flowExecutor.execute2Resp("chain3", "arg");
|
||||
Assertions.assertTrue(response.isSuccess());
|
||||
}
|
||||
|
||||
}
|
|
@ -1,21 +0,0 @@
|
|||
/**
|
||||
* <p>Title: liteflow</p>
|
||||
* <p>Description: 轻量级的组件式流程框架</p>
|
||||
* @author Bryan.Zhang
|
||||
* @email weenyc31@163.com
|
||||
* @Date 2020/4/1
|
||||
*/
|
||||
package com.yomahub.liteflow.test.substituteNode.cmp;
|
||||
|
||||
import com.yomahub.liteflow.core.NodeComponent;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component("a")
|
||||
public class ACmp extends NodeComponent {
|
||||
|
||||
@Override
|
||||
public void process() {
|
||||
System.out.println("ACmp executed!");
|
||||
}
|
||||
|
||||
}
|
|
@ -1,21 +0,0 @@
|
|||
/**
|
||||
* <p>Title: liteflow</p>
|
||||
* <p>Description: 轻量级的组件式流程框架</p>
|
||||
* @author Bryan.Zhang
|
||||
* @email weenyc31@163.com
|
||||
* @Date 2020/4/1
|
||||
*/
|
||||
package com.yomahub.liteflow.test.substituteNode.cmp;
|
||||
|
||||
import com.yomahub.liteflow.core.NodeComponent;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component("b")
|
||||
public class BCmp extends NodeComponent {
|
||||
|
||||
@Override
|
||||
public void process() {
|
||||
System.out.println("BCmp executed!");
|
||||
}
|
||||
|
||||
}
|
|
@ -1,21 +0,0 @@
|
|||
/**
|
||||
* <p>Title: liteflow</p>
|
||||
* <p>Description: 轻量级的组件式流程框架</p>
|
||||
* @author Bryan.Zhang
|
||||
* @email weenyc31@163.com
|
||||
* @Date 2020/4/1
|
||||
*/
|
||||
package com.yomahub.liteflow.test.substituteNode.cmp;
|
||||
|
||||
import com.yomahub.liteflow.core.NodeComponent;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component("c")
|
||||
public class CCmp extends NodeComponent {
|
||||
|
||||
@Override
|
||||
public void process() {
|
||||
System.out.println("CCmp executed!");
|
||||
}
|
||||
|
||||
}
|
|
@ -1,21 +0,0 @@
|
|||
/**
|
||||
* <p>Title: liteflow</p>
|
||||
* <p>Description: 轻量级的组件式流程框架</p>
|
||||
* @author Bryan.Zhang
|
||||
* @email weenyc31@163.com
|
||||
* @Date 2020/4/1
|
||||
*/
|
||||
package com.yomahub.liteflow.test.substituteNode.cmp;
|
||||
|
||||
import com.yomahub.liteflow.core.NodeComponent;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component("88-ffc")
|
||||
public class DCmp extends NodeComponent {
|
||||
|
||||
@Override
|
||||
public void process() {
|
||||
System.out.println("DCmp executed!");
|
||||
}
|
||||
|
||||
}
|
|
@ -1,21 +0,0 @@
|
|||
/**
|
||||
* <p>Title: liteflow</p>
|
||||
* <p>Description: 轻量级的组件式流程框架</p>
|
||||
* @author Bryan.Zhang
|
||||
* @email weenyc31@163.com
|
||||
* @Date 2020/4/1
|
||||
*/
|
||||
package com.yomahub.liteflow.test.substituteNode.cmp;
|
||||
|
||||
import com.yomahub.liteflow.core.NodeComponent;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component("sub")
|
||||
public class SubCmp extends NodeComponent {
|
||||
|
||||
@Override
|
||||
public void process() {
|
||||
System.out.println("SubCmp executed!");
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,2 @@
|
|||
liteflow.rule-source=fallback/flow.el.xml
|
||||
liteflow.fallback-cmp-enable=true
|
|
@ -0,0 +1,136 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<flow>
|
||||
<!-- THEN 普通组件降级 -->
|
||||
<chain name="then1">
|
||||
THEN(a, node("x"));
|
||||
</chain>
|
||||
|
||||
<chain name="then2">
|
||||
THEN(PRE(node("x1")), node("x2"), FINALLY(node("x3")));
|
||||
</chain>
|
||||
|
||||
<!-- WHEN 普通组件降级 -->
|
||||
<chain name="when1">
|
||||
WHEN(b, node("x"));
|
||||
</chain>
|
||||
|
||||
<!-- IF 条件组件降级 -->
|
||||
<chain name="if1">
|
||||
IF(node("x"), a)
|
||||
</chain>
|
||||
|
||||
<!-- IF 普通组件降级 -->
|
||||
<chain name="if2">
|
||||
IF(ifn1, node("x"))
|
||||
</chain>
|
||||
|
||||
<!-- FOR 次数循环组件降级 -->
|
||||
<chain name="for1">
|
||||
FOR(node("x")).DO(a);
|
||||
</chain>
|
||||
|
||||
<!-- FOR 普通组件降级 -->
|
||||
<chain name="for2">
|
||||
FOR(3).DO(node("x"));
|
||||
</chain>
|
||||
|
||||
<!-- WHILE 条件循环组件降级 -->
|
||||
<chain name="while1">
|
||||
WHILE(node("x")).DO(a)
|
||||
</chain>
|
||||
|
||||
<!-- WHILE 普通组件降级 -->
|
||||
<chain name="while2">
|
||||
WHILE(wn1).DO(node("x"))
|
||||
</chain>
|
||||
|
||||
<!-- ITERATOR 迭代组件降级 -->
|
||||
<chain name="iterator1">
|
||||
ITERATOR(node("x")).DO(a)
|
||||
</chain>
|
||||
|
||||
<!-- ITERATOR 普通组件降级 -->
|
||||
<chain name="iterator2">
|
||||
ITERATOR(itn1).DO(node("x"))
|
||||
</chain>
|
||||
|
||||
<!-- BREAK 退出循环组件降级 -->
|
||||
<chain name="break1">
|
||||
FOR(3).DO(a).BREAK(node("x"));
|
||||
</chain>
|
||||
|
||||
<chain name="break2">
|
||||
WHILE(wn1).DO(a).BREAK(node("x"));
|
||||
</chain>
|
||||
|
||||
<chain name="break3">
|
||||
ITERATOR(itn1).DO(a).BREAK(node("x"));
|
||||
</chain>
|
||||
|
||||
<!-- SWITCH 选择组件降级 -->
|
||||
<chain name="switch1">
|
||||
SWITCH(node("x")).to(a,b);
|
||||
</chain>
|
||||
|
||||
<!-- SWITCH 普通组件降级 -->
|
||||
<chain name="switch2">
|
||||
SWITCH(swn1).to(node("x"),a);
|
||||
</chain>
|
||||
|
||||
<!-- AND 条件组件降级 -->
|
||||
<chain name="and1">
|
||||
IF(AND(node("x"),ifn1), a);
|
||||
</chain>
|
||||
|
||||
<!-- OR 条件组件降级 -->
|
||||
<chain name="or1">
|
||||
IF(OR(node("x"),ifn1), a);
|
||||
</chain>
|
||||
|
||||
<!-- NOT 条件组件降级 -->
|
||||
<chain name="not1">
|
||||
IF(NOT(node("x")), a);
|
||||
</chain>
|
||||
|
||||
<!-- CATCH 普通组件降级 -->
|
||||
<chain name="catch1">
|
||||
CATCH(THEN(a, d)).DO(node("x"))
|
||||
</chain>
|
||||
|
||||
<!-- 多个组件降级 -->
|
||||
<chain name="multi1">
|
||||
THEN(
|
||||
a,
|
||||
node("x1"),
|
||||
IF(node("x2"), b)
|
||||
);
|
||||
</chain>
|
||||
|
||||
<chain name="multi2">
|
||||
IF(
|
||||
OR(node("x1"), ifn1),
|
||||
THEN(a, node("x2"))
|
||||
);
|
||||
</chain>
|
||||
|
||||
<chain name="multi3">
|
||||
FOR(node("x1")).DO(
|
||||
THEN(b, node("x2"))
|
||||
);
|
||||
</chain>
|
||||
|
||||
<!-- 并发降级测试 -->
|
||||
<chain name="concurrent1">
|
||||
WHEN(
|
||||
THEN(node("x1")),
|
||||
IF(node("x2"), b)
|
||||
).maxWaitSeconds(10000);
|
||||
</chain>
|
||||
|
||||
<chain name="concurrent2">
|
||||
WHEN(
|
||||
node("x1"),
|
||||
IF(node("x2"), b)
|
||||
).maxWaitSeconds(10000);
|
||||
</chain>
|
||||
</flow>
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue