From cdbc5aca7d44ded48c6d48ebe7b40212332f84fc Mon Sep 17 00:00:00 2001 From: Dale Lee <1658850308@qq.com> Date: Sun, 24 Sep 2023 15:58:04 +0800 Subject: [PATCH 1/8] =?UTF-8?q?feature=20#I7YYLE=20=E5=AE=9E=E7=8E=B0?= =?UTF-8?q?=E7=BB=84=E4=BB=B6=E9=99=8D=E7=BA=A7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../liteflow/annotation/FallbackCmp.java | 27 + .../builder/el/operator/NodeOperator.java | 42 +- .../FallbackCmpNotFoundException.java | 30 ++ .../com/yomahub/liteflow/flow/FlowBus.java | 473 +++++++++--------- .../liteflow/flow/element/Condition.java | 261 +++++----- .../flow/element/FallbackNodeProxy.java | 178 +++++++ .../java/com/yomahub/liteflow/slot/Slot.java | 16 +- .../test/fallback/FallbackSpringbootTest.java | 30 ++ .../liteflow/test/fallback/cmp/ACmp.java | 21 + .../liteflow/test/fallback/cmp/BCmp.java | 24 + .../liteflow/test/fallback/cmp/CCmp.java | 23 + .../resources/fallback/application.properties | 1 + .../src/test/resources/fallback/flow.el.xml | 11 + 13 files changed, 751 insertions(+), 386 deletions(-) create mode 100644 liteflow-core/src/main/java/com/yomahub/liteflow/annotation/FallbackCmp.java create mode 100644 liteflow-core/src/main/java/com/yomahub/liteflow/exception/FallbackCmpNotFoundException.java create mode 100644 liteflow-core/src/main/java/com/yomahub/liteflow/flow/element/FallbackNodeProxy.java create mode 100644 liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/fallback/FallbackSpringbootTest.java create mode 100644 liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/fallback/cmp/ACmp.java create mode 100644 liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/fallback/cmp/BCmp.java create mode 100644 liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/fallback/cmp/CCmp.java create mode 100644 liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/fallback/application.properties create mode 100644 liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/fallback/flow.el.xml diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/annotation/FallbackCmp.java b/liteflow-core/src/main/java/com/yomahub/liteflow/annotation/FallbackCmp.java new file mode 100644 index 000000000..caf9deed6 --- /dev/null +++ b/liteflow-core/src/main/java/com/yomahub/liteflow/annotation/FallbackCmp.java @@ -0,0 +1,27 @@ +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 + */ +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.RUNTIME) +@Documented +@Inherited +public @interface FallbackCmp { + + /** + * 节点类型 + * @return NodeTypeEnum + */ + NodeTypeEnum type() default NodeTypeEnum.COMMON; +} diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/NodeOperator.java b/liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/NodeOperator.java index 825b6a758..2013b3b4e 100644 --- a/liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/NodeOperator.java +++ b/liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/NodeOperator.java @@ -2,10 +2,16 @@ package com.yomahub.liteflow.builder.el.operator; import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.StrUtil; +import com.ql.util.express.ArraySwap; +import com.ql.util.express.IExpressContext; +import com.ql.util.express.InstructionSetContext; +import com.ql.util.express.OperateData; 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.core.NodeComponent; 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; @@ -17,41 +23,19 @@ import com.yomahub.liteflow.property.LiteflowConfigGetter; * @since 2.8.3 */ public class NodeOperator extends BaseOperator { - + @Override public Node build(Object[] objects) throws Exception { + OperatorHelper.checkObjectSizeEqOne(objects); - 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); - } + } else { + // 生成代理节点 + return new FallbackNodeProxy(nodeId); } } diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/exception/FallbackCmpNotFoundException.java b/liteflow-core/src/main/java/com/yomahub/liteflow/exception/FallbackCmpNotFoundException.java new file mode 100644 index 000000000..a334ea60f --- /dev/null +++ b/liteflow-core/src/main/java/com/yomahub/liteflow/exception/FallbackCmpNotFoundException.java @@ -0,0 +1,30 @@ +package com.yomahub.liteflow.exception; + +/** + * 没有找到降级组件异常 + * + * @author DaleLee + */ +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; + } + +} diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/flow/FlowBus.java b/liteflow-core/src/main/java/com/yomahub/liteflow/flow/FlowBus.java index 1f8d1954d..218502db0 100644 --- a/liteflow-core/src/main/java/com/yomahub/liteflow/flow/FlowBus.java +++ b/liteflow-core/src/main/java/com/yomahub/liteflow/flow/FlowBus.java @@ -6,11 +6,14 @@ * @email weenyc31@163.com * @Date 2020/4/1 */ + 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.annotation.FallbackCmp; +import com.yomahub.liteflow.annotation.util.AnnoUtil; import com.yomahub.liteflow.core.*; import com.yomahub.liteflow.enums.FlowParserTypeEnum; import com.yomahub.liteflow.enums.NodeTypeEnum; @@ -31,6 +34,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; @@ -43,230 +47,247 @@ import java.util.stream.Collectors; * @author Bryan.Zhang */ public class FlowBus { - - private static final LFLog LOG = LFLoggerManager.getLogger(FlowBus.class); - - private static final Map chainMap = new CopyOnWriteHashMap<>(); - - private static final Map nodeMap = new CopyOnWriteHashMap<>(); - - private FlowBus() { - } - - public static Chain getChain(String id) { - return chainMap.get(id); - } - - // 这一方法主要用于第一阶段chain的预装载 - public static void addChain(String chainName) { - if (!chainMap.containsKey(chainName)) { - chainMap.put(chainName, new Chain(chainName)); - } - } - - // 这个方法主要用于第二阶段的替换chain - public static void addChain(Chain chain) { - chainMap.put(chain.getChainId(), chain); - } - - public static boolean containChain(String chainId) { - return chainMap.containsKey(chainId); - } - - public static boolean needInit() { - return MapUtil.isEmpty(chainMap); - } - - public static boolean containNode(String nodeId) { - return nodeMap.containsKey(nodeId); - } - - /** - * 添加已托管的节点(如:Spring、Solon 管理的节点) - * */ - public static void addManagedNode(String nodeId, NodeComponent nodeComponent) { - // 根据class来猜测类型 - NodeTypeEnum type = NodeTypeEnum.guessType(nodeComponent.getClass()); - - if (type == null) { - 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 - * @param nodeId 节点id - * @param name 节点名称 - * @param type 节点类型 - * @param cmpClazz 节点组件类 - */ - public static void addNode(String nodeId, String name, NodeTypeEnum type, Class cmpClazz) { - addNode(nodeId, name, type, cmpClazz, null, null); - } - - /** - * 添加 node - * @param nodeId 节点id - * @param name 节点名称 - * @param nodeType 节点类型 - * @param cmpClazzStr 节点组件类路径 - */ - public static void addNode(String nodeId, String name, NodeTypeEnum nodeType, String cmpClazzStr) { - Class cmpClazz; - try { - cmpClazz = Class.forName(cmpClazzStr); - } - catch (Exception e) { - throw new ComponentCannotRegisterException(e.getMessage()); - } - addNode(nodeId, name, nodeType, cmpClazz, null, null); - } - - /** - * 添加脚本 node - * @param nodeId 节点id - * @param name 节点名称 - * @param nodeType 节点类型 - * @param script 脚本 - */ - public static void addScriptNode(String nodeId, String name, NodeTypeEnum nodeType, String script, - String language) { - addNode(nodeId, name, nodeType, ScriptComponent.ScriptComponentClassMap.get(nodeType), script, language); - } - - private static void addNode(String nodeId, String name, NodeTypeEnum type, Class cmpClazz, String script, - String language) { - try { - // 判断此类是否是声明式的组件,如果是声明式的组件,就用动态代理生成实例 - // 如果不是声明式的,就用传统的方式进行判断 - List cmpInstances = new ArrayList<>(); - if (LiteFlowProxyUtil.isDeclareCmp(cmpClazz)) { - // 这里的逻辑要仔细看下 - // 如果是spring体系,把原始的类往spring上下文中进行注册,那么会走到ComponentScanner中 - // 由于ComponentScanner中已经对原始类进行了动态代理,出来的对象已经变成了动态代理类,所以这时候的bean已经是NodeComponent的子类了 - // 所以spring体系下,无需再对这个bean做二次代理 - // 但是在非spring体系下,这个bean依旧是原来那个bean,所以需要对这个bean做一次代理 - // 这里用ContextAware的spi机制来判断是否spring体系 - ContextAware contextAware = ContextAwareHolder.loadContextAware(); - Object bean = ContextAwareHolder.loadContextAware().registerBean(nodeId, cmpClazz); - if (LocalContextAware.class.isAssignableFrom(contextAware.getClass())) { - cmpInstances = LiteFlowProxyUtil.proxy2NodeComponent(bean, nodeId); - } - else { - cmpInstances = ListUtil.toList((NodeComponent) bean); - } - } - else { - // 以node方式配置,本质上是为了适配无spring的环境,如果有spring环境,其实不用这么配置 - // 这里的逻辑是判断是否能从spring上下文中取到,如果没有spring,则就是new instance了 - // 如果是script类型的节点,因为class只有一个,所以也不能注册进spring上下文,注册的时候需要new Instance - if (!type.isScript()) { - cmpInstances = ListUtil - .toList((NodeComponent) ContextAwareHolder.loadContextAware().registerOrGet(nodeId, cmpClazz)); - } - // 去除null元素 - cmpInstances.remove(null); - // 如果为空 - if (cmpInstances.isEmpty()) { - NodeComponent cmpInstance = (NodeComponent) cmpClazz.newInstance(); - cmpInstances.add(cmpInstance); - } - } - // 进行初始化component - cmpInstances = cmpInstances.stream() - .map(cmpInstance -> ComponentInitializer.loadInstance() - .initComponent(cmpInstance, type, name, - cmpInstance.getNodeId() == null ? nodeId : cmpInstance.getNodeId())) - .collect(Collectors.toList()); - - // 初始化Node,把component放到Node里去 - List nodes = cmpInstances.stream().map(Node::new).collect(Collectors.toList()); - - for (int i = 0; i < nodes.size(); i++) { - Node node = nodes.get(i); - NodeComponent cmpInstance = cmpInstances.get(i); - // 如果是脚本节点,则还要加载script脚本 - if (type.isScript()) { - if (StrUtil.isNotBlank(script)) { - node.setScript(script); - node.setLanguage(language); - ((ScriptComponent) cmpInstance).loadScript(script, language); - } - else { - String errorMsg = StrUtil.format("script for node[{}] is empty", nodeId); - throw new ScriptLoadException(errorMsg); - } - } - - String activeNodeId = StrUtil.isEmpty(cmpInstance.getNodeId()) ? nodeId : cmpInstance.getNodeId(); - nodeMap.put(activeNodeId, node); - } - - } - catch (Exception e) { - String error = StrUtil.format("component[{}] register error", - StrUtil.isEmpty(name) ? nodeId : StrUtil.format("{}({})", nodeId, name)); - LOG.error(e.getMessage()); - throw new ComponentCannotRegisterException(StrUtil.format("{} {}", error, e.getMessage())); - } - } - - public static Node getNode(String nodeId) { - return nodeMap.get(nodeId); - } - - public static Map getNodeMap() { - return nodeMap; - } - - public static Map getChainMap() { - return chainMap; - } - - public static void cleanCache() { - chainMap.clear(); - nodeMap.clear(); - cleanScriptCache(); - } - - public static void cleanScriptCache() { - // 如果引入了脚本组件SPI,则还需要清理脚本的缓存 - try { - ScriptExecutorFactory.loadInstance().cleanScriptCache(); - } - catch (ScriptSpiException ignored) { - } - } - - public static void refreshFlowMetaData(FlowParserTypeEnum type, String content) throws Exception { - if (type.equals(FlowParserTypeEnum.TYPE_EL_XML)) { - new LocalXmlFlowELParser().parse(content); - } - else if (type.equals(FlowParserTypeEnum.TYPE_EL_JSON)) { - new LocalJsonFlowELParser().parse(content); - } - else if (type.equals(FlowParserTypeEnum.TYPE_EL_YML)) { - new LocalYmlFlowELParser().parse(content); - } - } - - public static boolean removeChain(String chainId) { - if (containChain(chainId)) { - chainMap.remove(chainId); - return true; - } - else { - String errMsg = StrUtil.format("cannot find the chain[{}]", chainId); - LOG.error(errMsg); - return false; - } - } - - public static void removeChain(String... chainIds) { - Arrays.stream(chainIds).forEach(FlowBus::removeChain); - } - + + private static final LFLog LOG = LFLoggerManager.getLogger(FlowBus.class); + + private static final Map chainMap = new CopyOnWriteHashMap<>(); + + private static final Map nodeMap = new CopyOnWriteHashMap<>(); + + private static final Map fallbackNodeMap = new CopyOnWriteHashMap<>(); + + private FlowBus() { + } + + public static Chain getChain(String id) { + return chainMap.get(id); + } + + // 这一方法主要用于第一阶段chain的预装载 + public static void addChain(String chainName) { + if (!chainMap.containsKey(chainName)) { + chainMap.put(chainName, new Chain(chainName)); + } + } + + // 这个方法主要用于第二阶段的替换chain + public static void addChain(Chain chain) { + chainMap.put(chain.getChainId(), chain); + } + + public static boolean containChain(String chainId) { + return chainMap.containsKey(chainId); + } + + public static boolean needInit() { + return MapUtil.isEmpty(chainMap); + } + + public static boolean containNode(String nodeId) { + return nodeMap.containsKey(nodeId); + } + + /** + * 添加已托管的节点(如:Spring、Solon 管理的节点) + */ + public static void addManagedNode(String nodeId, NodeComponent nodeComponent) { + // 根据class来猜测类型 + NodeTypeEnum type = NodeTypeEnum.guessType(nodeComponent.getClass()); + + if (type == null) { + throw new NullNodeTypeException(StrUtil.format("node type is null for node[{}]", nodeId)); + } + + Node node = new Node(ComponentInitializer.loadInstance() + .initComponent(nodeComponent, type, nodeComponent.getName(), nodeId)); + nodeMap.put(nodeId, node); + addFallbackNode(node); + } + + /** + * 添加 node + * + * @param nodeId 节点id + * @param name 节点名称 + * @param type 节点类型 + * @param cmpClazz 节点组件类 + */ + public static void addNode(String nodeId, String name, NodeTypeEnum type, Class cmpClazz) { + addNode(nodeId, name, type, cmpClazz, null, null); + } + + /** + * 添加 node + * + * @param nodeId 节点id + * @param name 节点名称 + * @param nodeType 节点类型 + * @param cmpClazzStr 节点组件类路径 + */ + public static void addNode(String nodeId, String name, NodeTypeEnum nodeType, String cmpClazzStr) { + Class cmpClazz; + try { + cmpClazz = Class.forName(cmpClazzStr); + } catch (Exception e) { + throw new ComponentCannotRegisterException(e.getMessage()); + } + addNode(nodeId, name, nodeType, cmpClazz, null, null); + } + + /** + * 添加脚本 node + * + * @param nodeId 节点id + * @param name 节点名称 + * @param nodeType 节点类型 + * @param script 脚本 + */ + public static void addScriptNode(String nodeId, String name, NodeTypeEnum nodeType, String script, + String language) { + addNode(nodeId, name, nodeType, ScriptComponent.ScriptComponentClassMap.get(nodeType), script, language); + } + + private static void addNode(String nodeId, String name, NodeTypeEnum type, Class cmpClazz, String script, + String language) { + try { + // 判断此类是否是声明式的组件,如果是声明式的组件,就用动态代理生成实例 + // 如果不是声明式的,就用传统的方式进行判断 + List cmpInstances = new ArrayList<>(); + if (LiteFlowProxyUtil.isDeclareCmp(cmpClazz)) { + // 这里的逻辑要仔细看下 + // 如果是spring体系,把原始的类往spring上下文中进行注册,那么会走到ComponentScanner中 + // 由于ComponentScanner中已经对原始类进行了动态代理,出来的对象已经变成了动态代理类,所以这时候的bean已经是NodeComponent的子类了 + // 所以spring体系下,无需再对这个bean做二次代理 + // 但是在非spring体系下,这个bean依旧是原来那个bean,所以需要对这个bean做一次代理 + // 这里用ContextAware的spi机制来判断是否spring体系 + ContextAware contextAware = ContextAwareHolder.loadContextAware(); + Object bean = ContextAwareHolder.loadContextAware().registerBean(nodeId, cmpClazz); + if (LocalContextAware.class.isAssignableFrom(contextAware.getClass())) { + cmpInstances = LiteFlowProxyUtil.proxy2NodeComponent(bean, nodeId); + } else { + cmpInstances = ListUtil.toList((NodeComponent) bean); + } + } else { + // 以node方式配置,本质上是为了适配无spring的环境,如果有spring环境,其实不用这么配置 + // 这里的逻辑是判断是否能从spring上下文中取到,如果没有spring,则就是new instance了 + // 如果是script类型的节点,因为class只有一个,所以也不能注册进spring上下文,注册的时候需要new Instance + if (!type.isScript()) { + cmpInstances = ListUtil.toList( + (NodeComponent) ContextAwareHolder.loadContextAware().registerOrGet(nodeId, cmpClazz)); + } + // 去除null元素 + cmpInstances.remove(null); + // 如果为空 + if (cmpInstances.isEmpty()) { + NodeComponent cmpInstance = (NodeComponent) cmpClazz.newInstance(); + cmpInstances.add(cmpInstance); + } + } + // 进行初始化component + cmpInstances = cmpInstances.stream().map(cmpInstance -> ComponentInitializer.loadInstance() + .initComponent(cmpInstance, type, name, + cmpInstance.getNodeId() == null ? nodeId : cmpInstance.getNodeId())) + .collect(Collectors.toList()); + + // 初始化Node,把component放到Node里去 + List nodes = cmpInstances.stream().map(Node::new).collect(Collectors.toList()); + + for (int i = 0; i < nodes.size(); i++) { + Node node = nodes.get(i); + NodeComponent cmpInstance = cmpInstances.get(i); + // 如果是脚本节点,则还要加载script脚本 + if (type.isScript()) { + if (StrUtil.isNotBlank(script)) { + node.setScript(script); + node.setLanguage(language); + ((ScriptComponent) cmpInstance).loadScript(script, language); + } else { + String errorMsg = StrUtil.format("script for node[{}] is empty", nodeId); + throw new ScriptLoadException(errorMsg); + } + } + + String activeNodeId = StrUtil.isEmpty(cmpInstance.getNodeId()) ? nodeId : cmpInstance.getNodeId(); + nodeMap.put(activeNodeId, node); + addFallbackNode(node); + } + + } catch (Exception e) { + String error = StrUtil.format("component[{}] register error", + StrUtil.isEmpty(name) ? nodeId : StrUtil.format("{}({})", nodeId, name)); + LOG.error(e.getMessage()); + throw new ComponentCannotRegisterException(StrUtil.format("{} {}", error, e.getMessage())); + } + } + + public static Node getNode(String nodeId) { + return nodeMap.get(nodeId); + } + + public static Map getNodeMap() { + return nodeMap; + } + + public static Map getChainMap() { + return chainMap; + } + + public static Node getFallBackNode(NodeTypeEnum nodeType) { + return fallbackNodeMap.get(nodeType); + } + + public static void cleanCache() { + chainMap.clear(); + nodeMap.clear(); + fallbackNodeMap.clear(); + cleanScriptCache(); + } + + public static void cleanScriptCache() { + // 如果引入了脚本组件SPI,则还需要清理脚本的缓存 + try { + ScriptExecutorFactory.loadInstance().cleanScriptCache(); + } catch (ScriptSpiException ignored) { + } + } + + public static void refreshFlowMetaData(FlowParserTypeEnum type, String content) throws Exception { + if (type.equals(FlowParserTypeEnum.TYPE_EL_XML)) { + new LocalXmlFlowELParser().parse(content); + } else if (type.equals(FlowParserTypeEnum.TYPE_EL_JSON)) { + new LocalJsonFlowELParser().parse(content); + } else if (type.equals(FlowParserTypeEnum.TYPE_EL_YML)) { + new LocalYmlFlowELParser().parse(content); + } + } + + public static boolean removeChain(String chainId) { + if (containChain(chainId)) { + chainMap.remove(chainId); + return true; + } else { + String errMsg = StrUtil.format("cannot find the chain[{}]", chainId); + LOG.error(errMsg); + return false; + } + } + + public static void removeChain(String... chainIds) { + Arrays.stream(chainIds).forEach(FlowBus::removeChain); + } + + 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(); + if (nodeType == null) { + nodeType = fallbackCmp.type(); + } + fallbackNodeMap.put(nodeType, node); + } + } diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/flow/element/Condition.java b/liteflow-core/src/main/java/com/yomahub/liteflow/flow/element/Condition.java index 60ccafe18..b485151fe 100644 --- a/liteflow-core/src/main/java/com/yomahub/liteflow/flow/element/Condition.java +++ b/liteflow-core/src/main/java/com/yomahub/liteflow/flow/element/Condition.java @@ -1,10 +1,12 @@ /** *

Title: liteflow

*

Description: 轻量级的组件式流程框架

+ * * @author Bryan.Zhang * @email weenyc31@163.com * @Date 2020/4/1 */ + package com.yomahub.liteflow.flow.element; import cn.hutool.core.collection.CollUtil; @@ -12,7 +14,6 @@ import cn.hutool.core.collection.ListUtil; import cn.hutool.core.util.ObjectUtil; 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; @@ -28,133 +29,133 @@ import java.util.Map; * * @author Bryan.Zhang */ -public abstract class Condition implements Executable{ - - private String id; - - private String tag; - - /** - * 可执行元素的集合 - */ - private final Map> executableGroup = new HashMap<>(); - - /** - * 当前所在的ChainName 如果对于子流程来说,那这个就是子流程所在的Chain - */ - private String currChainId; - - @Override - public void execute(Integer slotIndex) throws Exception { - try { - executeCondition(slotIndex); - } - catch (ChainEndException e) { - // 这里单独catch ChainEndException是因为ChainEndException是用户自己setIsEnd抛出的异常 - // 是属于正常逻辑,所以会在FlowExecutor中判断。这里不作为异常处理 - throw e; - } - catch (Exception e) { - Slot slot = DataBus.getSlot(slotIndex); - String chainId = this.getCurrChainId(); - // 这里事先取到exception set到slot里,为了方便finally取到exception - if (slot.isSubChain(chainId)) { - slot.setSubException(chainId, e); - } - else { - slot.setException(e); - } - throw e; - } - } - - public abstract void executeCondition(Integer slotIndex) throws Exception; - - @Override - public ExecuteTypeEnum getExecuteType() { - return ExecuteTypeEnum.CONDITION; - } - - public List getExecutableList() { - return getExecutableList(ConditionKey.DEFAULT_KEY); - } - - public List getExecutableList(String groupKey) { - List executableList = this.executableGroup.get(groupKey); - if (CollUtil.isEmpty(executableList)) { - executableList = new ArrayList<>(); - } - return executableList; - } - - public Executable getExecutableOne(String groupKey) { - List list = getExecutableList(groupKey); - if (CollUtil.isEmpty(list)) { - return null; - } - else { - return list.get(0); - } - } - - public void setExecutableList(List executableList) { - this.executableGroup.put(ConditionKey.DEFAULT_KEY, executableList); - } - - public void addExecutable(Executable executable) { - addExecutable(ConditionKey.DEFAULT_KEY, executable); - } - - public void addExecutable(String groupKey, Executable executable) { - if (ObjectUtil.isNull(executable)) { - return; - } - List executableList = this.executableGroup.get(groupKey); - if (CollUtil.isEmpty(executableList)) { - this.executableGroup.put(groupKey, ListUtil.toList(executable)); - } - else { - this.executableGroup.get(groupKey).add(executable); - } - } - - public abstract ConditionTypeEnum getConditionType(); - - public String getId() { - return id; - } - - public void setId(String id) { - this.id = id; - } - - @Override - public String getTag() { - return tag; - } - - public void setTag(String tag) { - this.tag = tag; - } - - /** - * 请使用 {@link #setCurrChainId(String)} - */ - @Deprecated - public String getCurrChainName() { - return currChainId; - } - - public String getCurrChainId() { - return currChainId; - } - - @Override - public void setCurrChainId(String currChainId) { - this.currChainId = currChainId; - } - - public Map> getExecutableGroup() { - return executableGroup; - } +public abstract class Condition implements Executable { + + private String id; + + private String tag; + + /** + * 可执行元素的集合 + */ + private final Map> executableGroup = new HashMap<>(); + + /** + * 当前所在的ChainName 如果对于子流程来说,那这个就是子流程所在的Chain + */ + private String currChainId; + + @Override + public void execute(Integer slotIndex) throws Exception { + // 当前 Condition 入栈 + Slot slot = DataBus.getSlot(slotIndex); + try { + slot.pushCondition(this); + executeCondition(slotIndex); + } catch (ChainEndException e) { + // 这里单独catch ChainEndException是因为ChainEndException是用户自己setIsEnd抛出的异常 + // 是属于正常逻辑,所以会在FlowExecutor中判断。这里不作为异常处理 + throw e; + } catch (Exception e) { + String chainId = this.getCurrChainId(); + // 这里事先取到exception set到slot里,为了方便finally取到exception + if (slot.isSubChain(chainId)) { + slot.setSubException(chainId, e); + } else { + slot.setException(e); + } + throw e; + } finally { + // 当前 Condition 出栈 + slot.popCondition(); + } + } + + public abstract void executeCondition(Integer slotIndex) throws Exception; + + @Override + public ExecuteTypeEnum getExecuteType() { + return ExecuteTypeEnum.CONDITION; + } + + public List getExecutableList() { + return getExecutableList(ConditionKey.DEFAULT_KEY); + } + + public List getExecutableList(String groupKey) { + List executableList = this.executableGroup.get(groupKey); + if (CollUtil.isEmpty(executableList)) { + executableList = new ArrayList<>(); + } + return executableList; + } + + public Executable getExecutableOne(String groupKey) { + List list = getExecutableList(groupKey); + if (CollUtil.isEmpty(list)) { + return null; + } else { + return list.get(0); + } + } + + public void setExecutableList(List executableList) { + this.executableGroup.put(ConditionKey.DEFAULT_KEY, executableList); + } + + public void addExecutable(Executable executable) { + addExecutable(ConditionKey.DEFAULT_KEY, executable); + } + + public void addExecutable(String groupKey, Executable executable) { + if (ObjectUtil.isNull(executable)) { + return; + } + List executableList = this.executableGroup.get(groupKey); + if (CollUtil.isEmpty(executableList)) { + this.executableGroup.put(groupKey, ListUtil.toList(executable)); + } else { + this.executableGroup.get(groupKey).add(executable); + } + } + + public abstract ConditionTypeEnum getConditionType(); + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + @Override + public String getTag() { + return tag; + } + + public void setTag(String tag) { + this.tag = tag; + } + + /** + * 请使用 {@link #setCurrChainId(String)} + */ + @Deprecated + public String getCurrChainName() { + return currChainId; + } + + public String getCurrChainId() { + return currChainId; + } + + @Override + public void setCurrChainId(String currChainId) { + this.currChainId = currChainId; + } + + public Map> getExecutableGroup() { + return executableGroup; + } } diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/flow/element/FallbackNodeProxy.java b/liteflow-core/src/main/java/com/yomahub/liteflow/flow/element/FallbackNodeProxy.java new file mode 100644 index 000000000..13b1cc03d --- /dev/null +++ b/liteflow-core/src/main/java/com/yomahub/liteflow/flow/element/FallbackNodeProxy.java @@ -0,0 +1,178 @@ +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; + +public class FallbackNodeProxy extends Node { + + private String originalNodeId; + + private Node fallbackNode;` + + public FallbackNodeProxy() { + } + + public FallbackNodeProxy(String originalNodeId) { + this.originalNodeId = originalNodeId; + } + + @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.isNotNull(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 {}.", + this.originalNodeId, 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); + } + + Executable breakItem = whileCondition.getExecutableOne(ConditionKey.BREAK_KEY); + if (breakItem == this) { + return FlowBus.getFallBackNode(NodeTypeEnum.BREAK); + } + + return findNodeInLoop(whileCondition); + } + + 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); + } + + private Node findNodeInIterator(IteratorCondition iteratorCondition) { + Node iteratorNode = iteratorCondition.getIteratorNode(); + if (iteratorNode == this) { + return FlowBus.getFallBackNode(NodeTypeEnum.ITERATOR); + } + + return FlowBus.getFallBackNode(NodeTypeEnum.COMMON); + } + + @Override + public T getItemResultMetaValue(Integer slotIndex) { + return this.fallbackNode.getItemResultMetaValue(slotIndex); + } + + @Override + public boolean isAccess(Integer slotIndex) throws Exception { + // WHEN 可能会先访问这个方法,所以在这里就要加载降级节点 + loadFallBackNode(slotIndex); + return this.fallbackNode.isAccess(slotIndex); + } + + @Override + public String getId() { + return this.fallbackNode.getId(); + } + + @Override + public Node copy() { + // 代理节点不复制 + return this; + } + + public String getOriginalNodeId() { + return originalNodeId; + } + + public void setOriginalNodeId(String originalNodeId) { + this.originalNodeId = originalNodeId; + } +} diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/slot/Slot.java b/liteflow-core/src/main/java/com/yomahub/liteflow/slot/Slot.java index 3a2516266..8b3275187 100644 --- a/liteflow-core/src/main/java/com/yomahub/liteflow/slot/Slot.java +++ b/liteflow-core/src/main/java/com/yomahub/liteflow/slot/Slot.java @@ -13,6 +13,7 @@ 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; @@ -26,7 +27,6 @@ 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的抽象类实现 @@ -88,6 +88,8 @@ public class Slot { protected ConcurrentHashMap metaDataMap = new ConcurrentHashMap<>(); private List contextBeanList; + + private final Deque conditionStack = new ConcurrentLinkedDeque<>(); public Slot() { } @@ -287,6 +289,18 @@ public class Slot { public Iterator getIteratorResult(String key) { return getThreadMetaData(ITERATOR_PREFIX + key); } + + public Condition getCurrentCondition() { + return this.conditionStack.peek(); + } + + public void pushCondition(Condition condition) { + this.conditionStack.push(condition); + } + + public void popCondition() { + this.conditionStack.pop(); + } /** * @deprecated 请使用 {@link #setChainId(String)} diff --git a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/fallback/FallbackSpringbootTest.java b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/fallback/FallbackSpringbootTest.java new file mode 100644 index 000000000..c1c4ecdcb --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/fallback/FallbackSpringbootTest.java @@ -0,0 +1,30 @@ +package com.yomahub.liteflow.test.fallback; + +import com.yomahub.liteflow.core.FlowExecutor; +import com.yomahub.liteflow.test.execute2Future.Executor2FutureELSpringbootTest; +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; + +@TestPropertySource(value = "classpath:/fallback/application.properties") +@SpringBootTest(classes = FallbackSpringbootTest.class) +@EnableAutoConfiguration +@ComponentScan({ "com.yomahub.liteflow.test.fallback.cmp" }) +public class FallbackSpringbootTest { + @Resource + private FlowExecutor flowExecutor; + + @Test + public void test1() { + flowExecutor.execute2Resp("chain1"); + } + + @Test + public void test2() { + flowExecutor.execute2Resp("chain2"); + } +} diff --git a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/fallback/cmp/ACmp.java b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/fallback/cmp/ACmp.java new file mode 100644 index 000000000..05102a985 --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/fallback/cmp/ACmp.java @@ -0,0 +1,21 @@ +/** + *

Title: liteflow

+ *

Description: 轻量级的组件式流程框架

+ * @author Bryan.Zhang + * @email weenyc31@163.com + * @Date 2020/4/1 + */ +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!"); + } + +} diff --git a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/fallback/cmp/BCmp.java b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/fallback/cmp/BCmp.java new file mode 100644 index 000000000..c634c78fc --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/fallback/cmp/BCmp.java @@ -0,0 +1,24 @@ +/** + *

Title: liteflow

+ *

Description: 轻量级的组件式流程框架

+ * @author Bryan.Zhang + * @email weenyc31@163.com + * @Date 2020/4/1 + */ +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!"); + } + +} diff --git a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/fallback/cmp/CCmp.java b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/fallback/cmp/CCmp.java new file mode 100644 index 000000000..3ec079168 --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/fallback/cmp/CCmp.java @@ -0,0 +1,23 @@ +/** + *

Title: liteflow

+ *

Description: 轻量级的组件式流程框架

+ * @author Bryan.Zhang + * @email weenyc31@163.com + * @Date 2020/4/1 + */ +package com.yomahub.liteflow.test.fallback.cmp; + +import com.yomahub.liteflow.annotation.FallbackCmp; +import com.yomahub.liteflow.core.NodeComponent; +import org.springframework.stereotype.Component; + +@Component("c") +@FallbackCmp +public class CCmp extends NodeComponent { + + @Override + public void process() { + System.out.println("CCmp executed!"); + } + +} diff --git a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/fallback/application.properties b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/fallback/application.properties new file mode 100644 index 000000000..6e04fd049 --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/fallback/application.properties @@ -0,0 +1 @@ +liteflow.rule-source=fallback/flow.el.xml \ No newline at end of file diff --git a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/fallback/flow.el.xml b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/fallback/flow.el.xml new file mode 100644 index 000000000..b4334e016 --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/fallback/flow.el.xml @@ -0,0 +1,11 @@ + + + + THEN(a, node("d")); + + + + THEN(a, WHEN(b,node("d"))); + + + \ No newline at end of file From 51fe4f5b420be142c0e91442ef6566a6f9bf5b29 Mon Sep 17 00:00:00 2001 From: Dale Lee <1658850308@qq.com> Date: Sun, 1 Oct 2023 15:34:37 +0800 Subject: [PATCH 2/8] =?UTF-8?q?feature=20#I7YYLE=20=E6=B7=BB=E5=8A=A0=20Sp?= =?UTF-8?q?ring=20Boot=20=E7=8E=AF=E5=A2=83=E4=B8=8B=E5=8D=95=E5=85=83?= =?UTF-8?q?=E6=B5=8B=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../builder/el/operator/ForOperator.java | 2 +- .../builder/el/operator/IteratorOperator.java | 32 ++-- .../builder/el/operator/SwitchOperator.java | 32 ++-- .../el/operator/base/OperatorHelper.java | 3 +- .../yomahub/liteflow/enums/NodeTypeEnum.java | 2 + .../flow/element/FallbackNodeProxy.java | 58 +++--- .../test/fallback/FallbackSpringbootTest.java | 166 +++++++++++++++++- .../liteflow/test/fallback/cmp/BreakCmp.java | 15 ++ .../liteflow/test/fallback/cmp/CCmp.java | 4 +- .../liteflow/test/fallback/cmp/DCmp.java | 13 ++ .../liteflow/test/fallback/cmp/ForCmp.java | 15 ++ .../liteflow/test/fallback/cmp/IfCmp1.java | 13 ++ .../liteflow/test/fallback/cmp/IfCmp2.java | 15 ++ .../test/fallback/cmp/IteratorCmp1.java | 16 ++ .../test/fallback/cmp/IteratorCmp2.java | 18 ++ .../test/fallback/cmp/SwitchCmp1.java | 13 ++ .../test/fallback/cmp/SwitchCmp2.java | 15 ++ .../liteflow/test/fallback/cmp/WhileCmp1.java | 26 +++ .../liteflow/test/fallback/cmp/WhileCmp2.java | 15 ++ .../src/test/resources/fallback/flow.el.xml | 117 +++++++++++- 20 files changed, 518 insertions(+), 72 deletions(-) create mode 100644 liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/fallback/cmp/BreakCmp.java create mode 100644 liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/fallback/cmp/DCmp.java create mode 100644 liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/fallback/cmp/ForCmp.java create mode 100644 liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/fallback/cmp/IfCmp1.java create mode 100644 liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/fallback/cmp/IfCmp2.java create mode 100644 liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/fallback/cmp/IteratorCmp1.java create mode 100644 liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/fallback/cmp/IteratorCmp2.java create mode 100644 liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/fallback/cmp/SwitchCmp1.java create mode 100644 liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/fallback/cmp/SwitchCmp2.java create mode 100644 liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/fallback/cmp/WhileCmp1.java create mode 100644 liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/fallback/cmp/WhileCmp2.java diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/ForOperator.java b/liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/ForOperator.java index 44bccfa92..e87f9c279 100644 --- a/liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/ForOperator.java +++ b/liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/ForOperator.java @@ -27,7 +27,7 @@ public class ForOperator extends BaseOperator { 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"); } } diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/IteratorOperator.java b/liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/IteratorOperator.java index c96379808..468b36188 100644 --- a/liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/IteratorOperator.java +++ b/liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/IteratorOperator.java @@ -9,20 +9,20 @@ import com.yomahub.liteflow.flow.element.Node; import com.yomahub.liteflow.flow.element.condition.IteratorCondition; public class IteratorOperator extends BaseOperator { - - @Override - public IteratorCondition build(Object[] objects) throws Exception { - OperatorHelper.checkObjectSizeEq(objects, 1); - - Node node = OperatorHelper.convert(objects[0], Node.class); - if (!ListUtil.toList(NodeTypeEnum.ITERATOR).contains(node.getType())) { - throw new QLException("The parameter must be iterator-node item"); - } - - IteratorCondition iteratorCondition = new IteratorCondition(); - iteratorCondition.setIteratorNode(node); - - return iteratorCondition; - } - + + @Override + public IteratorCondition build(Object[] objects) throws Exception { + OperatorHelper.checkObjectSizeEq(objects, 1); + + Node node = OperatorHelper.convert(objects[0], Node.class); + if (!ListUtil.toList(NodeTypeEnum.ITERATOR, NodeTypeEnum.FALLBACK).contains(node.getType())) { + throw new QLException("The parameter must be iterator-node item"); + } + + IteratorCondition iteratorCondition = new IteratorCondition(); + iteratorCondition.setIteratorNode(node); + + return iteratorCondition; + } + } diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/SwitchOperator.java b/liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/SwitchOperator.java index aa1d4c199..5dee3ebd1 100644 --- a/liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/SwitchOperator.java +++ b/liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/SwitchOperator.java @@ -15,20 +15,20 @@ import com.yomahub.liteflow.flow.element.condition.SwitchCondition; * @since 2.8.0 */ public class SwitchOperator extends BaseOperator { - - @Override - public SwitchCondition build(Object[] objects) throws Exception { - OperatorHelper.checkObjectSizeEqOne(objects); - - Node switchNode = OperatorHelper.convert(objects[0], Node.class); - if (!ListUtil.toList(NodeTypeEnum.SWITCH, NodeTypeEnum.SWITCH_SCRIPT).contains(switchNode.getType())) { - throw new QLException("The caller must be Switch item"); - } - - SwitchCondition switchCondition = new SwitchCondition(); - switchCondition.setSwitchNode(switchNode); - - return switchCondition; - } - + + @Override + public SwitchCondition build(Object[] objects) throws Exception { + OperatorHelper.checkObjectSizeEqOne(objects); + + Node switchNode = OperatorHelper.convert(objects[0], Node.class); + if (!ListUtil.toList(NodeTypeEnum.SWITCH, NodeTypeEnum.SWITCH_SCRIPT, NodeTypeEnum.FALLBACK) + .contains(switchNode.getType())) { + throw new QLException("The caller must be Switch item"); + } + + SwitchCondition switchCondition = new SwitchCondition(); + switchCondition.setSwitchNode(switchNode); + + return switchCondition; + } } diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/base/OperatorHelper.java b/liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/base/OperatorHelper.java index 0a181205e..298cdc254 100644 --- a/liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/base/OperatorHelper.java +++ b/liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/base/OperatorHelper.java @@ -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"); } diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/enums/NodeTypeEnum.java b/liteflow-core/src/main/java/com/yomahub/liteflow/enums/NodeTypeEnum.java index 93ee30ea9..18370814e 100644 --- a/liteflow-core/src/main/java/com/yomahub/liteflow/enums/NodeTypeEnum.java +++ b/liteflow-core/src/main/java/com/yomahub/liteflow/enums/NodeTypeEnum.java @@ -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), diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/flow/element/FallbackNodeProxy.java b/liteflow-core/src/main/java/com/yomahub/liteflow/flow/element/FallbackNodeProxy.java index 13b1cc03d..465962216 100644 --- a/liteflow-core/src/main/java/com/yomahub/liteflow/flow/element/FallbackNodeProxy.java +++ b/liteflow-core/src/main/java/com/yomahub/liteflow/flow/element/FallbackNodeProxy.java @@ -19,15 +19,19 @@ import com.yomahub.liteflow.slot.Slot; public class FallbackNodeProxy extends Node { - private String originalNodeId; + // 原节点 id + private String expectedNodeId; - private Node fallbackNode;` + // 降级节点 + private Node fallbackNode; public FallbackNodeProxy() { + this.setType(NodeTypeEnum.FALLBACK); } - public FallbackNodeProxy(String originalNodeId) { - this.originalNodeId = originalNodeId; + public FallbackNodeProxy(String expectedNodeId) { + this(); + this.expectedNodeId = expectedNodeId; } @Override @@ -44,14 +48,14 @@ public class FallbackNodeProxy extends Node { } Slot slot = DataBus.getSlot(slotIndex); Condition curCondition = slot.getCurrentCondition(); - if (ObjectUtil.isNotNull(curCondition)) { + 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 {}.", - this.originalNodeId, this.getCurrChainId())); + StrFormatter.format("No fallback component found for [{}] in chain[{}].", this.expectedNodeId, + this.getCurrChainId())); } // 使用 node 的副本 this.fallbackNode = node.copy(); @@ -119,29 +123,24 @@ public class FallbackNodeProxy extends Node { return FlowBus.getFallBackNode(NodeTypeEnum.WHILE); } - Executable breakItem = whileCondition.getExecutableOne(ConditionKey.BREAK_KEY); - if (breakItem == this) { - return FlowBus.getFallBackNode(NodeTypeEnum.BREAK); - } - return findNodeInLoop(whileCondition); } - 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); - } - 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); } @@ -152,14 +151,14 @@ public class FallbackNodeProxy extends Node { @Override public boolean isAccess(Integer slotIndex) throws Exception { - // WHEN 可能会先访问这个方法,所以在这里就要加载降级节点 + // 可能会先访问这个方法,所以在这里就要加载降级节点 loadFallBackNode(slotIndex); return this.fallbackNode.isAccess(slotIndex); } @Override public String getId() { - return this.fallbackNode.getId(); + return this.fallbackNode == null ? null : this.fallbackNode.getId(); } @Override @@ -168,11 +167,16 @@ public class FallbackNodeProxy extends Node { return this; } - public String getOriginalNodeId() { - return originalNodeId; + @Override + public NodeTypeEnum getType() { + return NodeTypeEnum.FALLBACK; } - public void setOriginalNodeId(String originalNodeId) { - this.originalNodeId = originalNodeId; + public String getExpectedNodeId() { + return expectedNodeId; + } + + public void setExpectedNodeId(String expectedNodeId) { + this.expectedNodeId = expectedNodeId; } } diff --git a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/fallback/FallbackSpringbootTest.java b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/fallback/FallbackSpringbootTest.java index c1c4ecdcb..8f49d79fe 100644 --- a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/fallback/FallbackSpringbootTest.java +++ b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/fallback/FallbackSpringbootTest.java @@ -1,7 +1,8 @@ package com.yomahub.liteflow.test.fallback; import com.yomahub.liteflow.core.FlowExecutor; -import com.yomahub.liteflow.test.execute2Future.Executor2FutureELSpringbootTest; +import com.yomahub.liteflow.flow.LiteflowResponse; +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; @@ -13,18 +14,171 @@ import javax.annotation.Resource; @TestPropertySource(value = "classpath:/fallback/application.properties") @SpringBootTest(classes = FallbackSpringbootTest.class) @EnableAutoConfiguration -@ComponentScan({ "com.yomahub.liteflow.test.fallback.cmp" }) +@ComponentScan({"com.yomahub.liteflow.test.fallback.cmp"}) public class FallbackSpringbootTest { + @Resource private FlowExecutor flowExecutor; @Test - public void test1() { - flowExecutor.execute2Resp("chain1"); + public void testThen1() { + LiteflowResponse response = flowExecutor.execute2Resp("then1", "arg"); + Assertions.assertTrue(response.isSuccess()); + Assertions.assertEquals("a==>c", response.getExecuteStepStrWithoutTime()); } @Test - public void test2() { - flowExecutor.execute2Resp("chain2"); + 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()); } } diff --git a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/fallback/cmp/BreakCmp.java b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/fallback/cmp/BreakCmp.java new file mode 100644 index 000000000..ec23619ff --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/fallback/cmp/BreakCmp.java @@ -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; + } +} diff --git a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/fallback/cmp/CCmp.java b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/fallback/cmp/CCmp.java index 3ec079168..8340fd0c3 100644 --- a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/fallback/cmp/CCmp.java +++ b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/fallback/cmp/CCmp.java @@ -8,10 +8,12 @@ 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; -@Component("c") +@LiteflowComponent("c") @FallbackCmp public class CCmp extends NodeComponent { diff --git a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/fallback/cmp/DCmp.java b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/fallback/cmp/DCmp.java new file mode 100644 index 000000000..d036751c5 --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/fallback/cmp/DCmp.java @@ -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]"); + } +} diff --git a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/fallback/cmp/ForCmp.java b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/fallback/cmp/ForCmp.java new file mode 100644 index 000000000..a0f47f408 --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/fallback/cmp/ForCmp.java @@ -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; + } +} diff --git a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/fallback/cmp/IfCmp1.java b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/fallback/cmp/IfCmp1.java new file mode 100644 index 000000000..d95597e20 --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/fallback/cmp/IfCmp1.java @@ -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; + } +} diff --git a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/fallback/cmp/IfCmp2.java b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/fallback/cmp/IfCmp2.java new file mode 100644 index 000000000..2626056c2 --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/fallback/cmp/IfCmp2.java @@ -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; + } +} diff --git a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/fallback/cmp/IteratorCmp1.java b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/fallback/cmp/IteratorCmp1.java new file mode 100644 index 000000000..02a9f1ca7 --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/fallback/cmp/IteratorCmp1.java @@ -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(); + } +} diff --git a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/fallback/cmp/IteratorCmp2.java b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/fallback/cmp/IteratorCmp2.java new file mode 100644 index 000000000..9d0a7eabc --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/fallback/cmp/IteratorCmp2.java @@ -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(); + } +} diff --git a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/fallback/cmp/SwitchCmp1.java b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/fallback/cmp/SwitchCmp1.java new file mode 100644 index 000000000..e98fa71e7 --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/fallback/cmp/SwitchCmp1.java @@ -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"; + } +} diff --git a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/fallback/cmp/SwitchCmp2.java b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/fallback/cmp/SwitchCmp2.java new file mode 100644 index 000000000..d8146c0f1 --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/fallback/cmp/SwitchCmp2.java @@ -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"; + } +} diff --git a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/fallback/cmp/WhileCmp1.java b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/fallback/cmp/WhileCmp1.java new file mode 100644 index 000000000..c355e7383 --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/fallback/cmp/WhileCmp1.java @@ -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 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; + } +} diff --git a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/fallback/cmp/WhileCmp2.java b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/fallback/cmp/WhileCmp2.java new file mode 100644 index 000000000..b198faa0e --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/fallback/cmp/WhileCmp2.java @@ -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; + } +} diff --git a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/fallback/flow.el.xml b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/fallback/flow.el.xml index b4334e016..66e6da96c 100644 --- a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/fallback/flow.el.xml +++ b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/fallback/flow.el.xml @@ -1,11 +1,120 @@ - - THEN(a, node("d")); + + + THEN(a, node("x")); - - THEN(a, WHEN(b,node("d"))); + + THEN(PRE(node("x1")), node("x2"), FINALLY(node("x3"))); + + + + WHEN(b, node("x")); + + + IF(node("x"), a) + + + + + IF(ifn1, node("x")) + + + + + FOR(node("x")).DO(a); + + + + + FOR(3).DO(node("x")); + + + + + WHILE(node("x")).DO(a) + + + + + WHILE(wn1).DO(node("x")) + + + + + ITERATOR(node("x")).DO(a) + + + + + ITERATOR(itn1).DO(node("x")) + + + + + FOR(3).DO(a).BREAK(node("x")); + + + + WHILE(wn1).DO(a).BREAK(node("x")); + + + + ITERATOR(itn1).DO(a).BREAK(node("x")); + + + + + SWITCH(node("x")).to(a,b); + + + + + SWITCH(swn1).to(node("x"),a); + + + + + IF(AND(node("x"),ifn1), a); + + + + + IF(OR(node("x"),ifn1), a); + + + + + IF(NOT(node("x")), a); + + + + + CATCH(THEN(a, d)).DO(node("x")) + + + + + THEN( + a, + node("x1"), + IF(node("x2"), b) + ); + + + + IF( + OR(node("x1"), ifn1), + THEN(a, node("x2")) + ); + + + + FOR(node("x1")).DO( + THEN(b, node("x2")) + ); + \ No newline at end of file From 0df89cb9b5913c617c4d434699da9cfc7c2cd74f Mon Sep 17 00:00:00 2001 From: Dale Lee <1658850308@qq.com> Date: Sun, 1 Oct 2023 16:54:35 +0800 Subject: [PATCH 3/8] =?UTF-8?q?feature=20#I7YYLE=20=E6=B7=BB=E5=8A=A0?= =?UTF-8?q?=E7=BB=84=E4=BB=B6=E9=99=8D=E7=BA=A7=E5=90=AF=E5=8A=A8=E9=85=8D?= =?UTF-8?q?=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../builder/el/operator/NodeOperator.java | 9 ++++++- .../liteflow/property/LiteflowConfig.java | 26 +++++++++++-------- .../config/LiteflowAutoConfiguration.java | 2 +- .../solon/config/LiteflowProperty.java | 22 ++++++++-------- .../liteflow/springboot/LiteflowProperty.java | 22 ++++++++-------- .../LiteflowPropertyAutoConfiguration.java | 2 +- ...itional-spring-configuration-metadata.json | 14 +++++----- .../resources/fallback/application.properties | 3 ++- 8 files changed, 56 insertions(+), 44 deletions(-) diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/NodeOperator.java b/liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/NodeOperator.java index 2013b3b4e..007223126 100644 --- a/liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/NodeOperator.java +++ b/liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/NodeOperator.java @@ -10,6 +10,7 @@ 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.core.NodeComponent; +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; @@ -26,7 +27,13 @@ public class NodeOperator extends BaseOperator { @Override public Node build(Object[] objects) throws Exception { - + // 检查是否开启了组件降级功能 + LiteflowConfig liteflowConfig = LiteflowConfigGetter.get(); + Boolean enable = liteflowConfig.getFallbackCmpEnable(); + if (!enable) { + throw new ELParseException("The fallback component is disabled"); + } + OperatorHelper.checkObjectSizeEqOne(objects); String nodeId = OperatorHelper.convert(objects[0], String.class); diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/property/LiteflowConfig.java b/liteflow-core/src/main/java/com/yomahub/liteflow/property/LiteflowConfig.java index 814ccf49a..c0cbf0391 100644 --- a/liteflow-core/src/main/java/com/yomahub/liteflow/property/LiteflowConfig.java +++ b/liteflow-core/src/main/java/com/yomahub/liteflow/property/LiteflowConfig.java @@ -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; + } } diff --git a/liteflow-solon-plugin/src/main/java/com/yomahub/liteflow/solon/config/LiteflowAutoConfiguration.java b/liteflow-solon-plugin/src/main/java/com/yomahub/liteflow/solon/config/LiteflowAutoConfiguration.java index 082f41ea5..f8ccebff6 100644 --- a/liteflow-solon-plugin/src/main/java/com/yomahub/liteflow/solon/config/LiteflowAutoConfiguration.java +++ b/liteflow-solon-plugin/src/main/java/com/yomahub/liteflow/solon/config/LiteflowAutoConfiguration.java @@ -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; } diff --git a/liteflow-solon-plugin/src/main/java/com/yomahub/liteflow/solon/config/LiteflowProperty.java b/liteflow-solon-plugin/src/main/java/com/yomahub/liteflow/solon/config/LiteflowProperty.java index 2454ba472..6790bcd57 100644 --- a/liteflow-solon-plugin/src/main/java/com/yomahub/liteflow/solon/config/LiteflowProperty.java +++ b/liteflow-solon-plugin/src/main/java/com/yomahub/liteflow/solon/config/LiteflowProperty.java @@ -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; + } } diff --git a/liteflow-spring-boot-starter/src/main/java/com/yomahub/liteflow/springboot/LiteflowProperty.java b/liteflow-spring-boot-starter/src/main/java/com/yomahub/liteflow/springboot/LiteflowProperty.java index d13fdd402..2ac3b5dbb 100644 --- a/liteflow-spring-boot-starter/src/main/java/com/yomahub/liteflow/springboot/LiteflowProperty.java +++ b/liteflow-spring-boot-starter/src/main/java/com/yomahub/liteflow/springboot/LiteflowProperty.java @@ -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; + } } diff --git a/liteflow-spring-boot-starter/src/main/java/com/yomahub/liteflow/springboot/config/LiteflowPropertyAutoConfiguration.java b/liteflow-spring-boot-starter/src/main/java/com/yomahub/liteflow/springboot/config/LiteflowPropertyAutoConfiguration.java index 39bf982b0..71c98bb1a 100644 --- a/liteflow-spring-boot-starter/src/main/java/com/yomahub/liteflow/springboot/config/LiteflowPropertyAutoConfiguration.java +++ b/liteflow-spring-boot-starter/src/main/java/com/yomahub/liteflow/springboot/config/LiteflowPropertyAutoConfiguration.java @@ -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; } diff --git a/liteflow-spring-boot-starter/src/main/resources/META-INF/additional-spring-configuration-metadata.json b/liteflow-spring-boot-starter/src/main/resources/META-INF/additional-spring-configuration-metadata.json index b6297cbee..a2fd62a47 100644 --- a/liteflow-spring-boot-starter/src/main/resources/META-INF/additional-spring-configuration-metadata.json +++ b/liteflow-spring-boot-starter/src/main/resources/META-INF/additional-spring-configuration-metadata.json @@ -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 } ] } \ No newline at end of file diff --git a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/fallback/application.properties b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/fallback/application.properties index 6e04fd049..b6a1da886 100644 --- a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/fallback/application.properties +++ b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/fallback/application.properties @@ -1 +1,2 @@ -liteflow.rule-source=fallback/flow.el.xml \ No newline at end of file +liteflow.rule-source=fallback/flow.el.xml +liteflow.fallback-cmp-enable=true \ No newline at end of file From ee598eb773cfe19b4d72594ea44d07e179458f6f Mon Sep 17 00:00:00 2001 From: Dale Lee <1658850308@qq.com> Date: Sun, 1 Oct 2023 19:24:27 +0800 Subject: [PATCH 4/8] =?UTF-8?q?feature=20#I7YYLE=20=E7=A7=BB=E9=99=A4?= =?UTF-8?q?=E6=9B=BF=E8=A1=A5=E7=BB=84=E4=BB=B6=E6=B5=8B=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../SubstituteSpringbootTest.java | 46 ----------------- .../test/substituteNode/cmp/ACmp.java | 21 -------- .../test/substituteNode/cmp/BCmp.java | 21 -------- .../test/substituteNode/cmp/CCmp.java | 21 -------- .../test/substituteNode/cmp/DCmp.java | 21 -------- .../test/substituteNode/cmp/SubCmp.java | 21 -------- .../substituteNode/application.properties | 2 - .../test/resources/substituteNode/flow.el.xml | 14 ------ .../SubstituteSpringbootTest.java | 50 ------------------- .../test/substituteNode/cmp/ACmp.java | 21 -------- .../test/substituteNode/cmp/BCmp.java | 21 -------- .../test/substituteNode/cmp/CCmp.java | 21 -------- .../test/substituteNode/cmp/DCmp.java | 21 -------- .../test/substituteNode/cmp/SubCmp.java | 21 -------- .../substituteNode/application.properties | 2 - .../test/resources/substituteNode/flow.el.xml | 14 ------ 16 files changed, 338 deletions(-) delete mode 100644 liteflow-testcase-el/liteflow-testcase-el-solon/src/test/java/com/yomahub/liteflow/test/substituteNode/SubstituteSpringbootTest.java delete mode 100644 liteflow-testcase-el/liteflow-testcase-el-solon/src/test/java/com/yomahub/liteflow/test/substituteNode/cmp/ACmp.java delete mode 100644 liteflow-testcase-el/liteflow-testcase-el-solon/src/test/java/com/yomahub/liteflow/test/substituteNode/cmp/BCmp.java delete mode 100644 liteflow-testcase-el/liteflow-testcase-el-solon/src/test/java/com/yomahub/liteflow/test/substituteNode/cmp/CCmp.java delete mode 100644 liteflow-testcase-el/liteflow-testcase-el-solon/src/test/java/com/yomahub/liteflow/test/substituteNode/cmp/DCmp.java delete mode 100644 liteflow-testcase-el/liteflow-testcase-el-solon/src/test/java/com/yomahub/liteflow/test/substituteNode/cmp/SubCmp.java delete mode 100644 liteflow-testcase-el/liteflow-testcase-el-solon/src/test/resources/substituteNode/application.properties delete mode 100644 liteflow-testcase-el/liteflow-testcase-el-solon/src/test/resources/substituteNode/flow.el.xml delete mode 100644 liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/substituteNode/SubstituteSpringbootTest.java delete mode 100644 liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/substituteNode/cmp/ACmp.java delete mode 100644 liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/substituteNode/cmp/BCmp.java delete mode 100644 liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/substituteNode/cmp/CCmp.java delete mode 100644 liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/substituteNode/cmp/DCmp.java delete mode 100644 liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/substituteNode/cmp/SubCmp.java delete mode 100644 liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/substituteNode/application.properties delete mode 100644 liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/substituteNode/flow.el.xml diff --git a/liteflow-testcase-el/liteflow-testcase-el-solon/src/test/java/com/yomahub/liteflow/test/substituteNode/SubstituteSpringbootTest.java b/liteflow-testcase-el/liteflow-testcase-el-solon/src/test/java/com/yomahub/liteflow/test/substituteNode/SubstituteSpringbootTest.java deleted file mode 100644 index 623662234..000000000 --- a/liteflow-testcase-el/liteflow-testcase-el-solon/src/test/java/com/yomahub/liteflow/test/substituteNode/SubstituteSpringbootTest.java +++ /dev/null @@ -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()); - } - -} diff --git a/liteflow-testcase-el/liteflow-testcase-el-solon/src/test/java/com/yomahub/liteflow/test/substituteNode/cmp/ACmp.java b/liteflow-testcase-el/liteflow-testcase-el-solon/src/test/java/com/yomahub/liteflow/test/substituteNode/cmp/ACmp.java deleted file mode 100644 index a314cdd38..000000000 --- a/liteflow-testcase-el/liteflow-testcase-el-solon/src/test/java/com/yomahub/liteflow/test/substituteNode/cmp/ACmp.java +++ /dev/null @@ -1,21 +0,0 @@ -/** - *

Title: liteflow

- *

Description: 轻量级的组件式流程框架

- * @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!"); - } - -} diff --git a/liteflow-testcase-el/liteflow-testcase-el-solon/src/test/java/com/yomahub/liteflow/test/substituteNode/cmp/BCmp.java b/liteflow-testcase-el/liteflow-testcase-el-solon/src/test/java/com/yomahub/liteflow/test/substituteNode/cmp/BCmp.java deleted file mode 100644 index 7bfec97e7..000000000 --- a/liteflow-testcase-el/liteflow-testcase-el-solon/src/test/java/com/yomahub/liteflow/test/substituteNode/cmp/BCmp.java +++ /dev/null @@ -1,21 +0,0 @@ -/** - *

Title: liteflow

- *

Description: 轻量级的组件式流程框架

- * @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!"); - } - -} diff --git a/liteflow-testcase-el/liteflow-testcase-el-solon/src/test/java/com/yomahub/liteflow/test/substituteNode/cmp/CCmp.java b/liteflow-testcase-el/liteflow-testcase-el-solon/src/test/java/com/yomahub/liteflow/test/substituteNode/cmp/CCmp.java deleted file mode 100644 index 040bbcbca..000000000 --- a/liteflow-testcase-el/liteflow-testcase-el-solon/src/test/java/com/yomahub/liteflow/test/substituteNode/cmp/CCmp.java +++ /dev/null @@ -1,21 +0,0 @@ -/** - *

Title: liteflow

- *

Description: 轻量级的组件式流程框架

- * @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!"); - } - -} diff --git a/liteflow-testcase-el/liteflow-testcase-el-solon/src/test/java/com/yomahub/liteflow/test/substituteNode/cmp/DCmp.java b/liteflow-testcase-el/liteflow-testcase-el-solon/src/test/java/com/yomahub/liteflow/test/substituteNode/cmp/DCmp.java deleted file mode 100644 index 14aa20e9c..000000000 --- a/liteflow-testcase-el/liteflow-testcase-el-solon/src/test/java/com/yomahub/liteflow/test/substituteNode/cmp/DCmp.java +++ /dev/null @@ -1,21 +0,0 @@ -/** - *

Title: liteflow

- *

Description: 轻量级的组件式流程框架

- * @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!"); - } - -} diff --git a/liteflow-testcase-el/liteflow-testcase-el-solon/src/test/java/com/yomahub/liteflow/test/substituteNode/cmp/SubCmp.java b/liteflow-testcase-el/liteflow-testcase-el-solon/src/test/java/com/yomahub/liteflow/test/substituteNode/cmp/SubCmp.java deleted file mode 100644 index 776a5b4cf..000000000 --- a/liteflow-testcase-el/liteflow-testcase-el-solon/src/test/java/com/yomahub/liteflow/test/substituteNode/cmp/SubCmp.java +++ /dev/null @@ -1,21 +0,0 @@ -/** - *

Title: liteflow

- *

Description: 轻量级的组件式流程框架

- * @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!"); - } - -} diff --git a/liteflow-testcase-el/liteflow-testcase-el-solon/src/test/resources/substituteNode/application.properties b/liteflow-testcase-el/liteflow-testcase-el-solon/src/test/resources/substituteNode/application.properties deleted file mode 100644 index 35bdc3a1e..000000000 --- a/liteflow-testcase-el/liteflow-testcase-el-solon/src/test/resources/substituteNode/application.properties +++ /dev/null @@ -1,2 +0,0 @@ -liteflow.rule-source=substituteNode/flow.el.xml -liteflow.substitute-cmp-class=com.yomahub.liteflow.test.substituteNode.cmp.SubCmp \ No newline at end of file diff --git a/liteflow-testcase-el/liteflow-testcase-el-solon/src/test/resources/substituteNode/flow.el.xml b/liteflow-testcase-el/liteflow-testcase-el-solon/src/test/resources/substituteNode/flow.el.xml deleted file mode 100644 index 7730921b9..000000000 --- a/liteflow-testcase-el/liteflow-testcase-el-solon/src/test/resources/substituteNode/flow.el.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - - THEN(node("a"), node("b"), node("c")); - - - - THEN(node("a"), node("b"), node("93-nodeTEST")); - - - - THEN(a, b, node("88-ffc")); - - \ No newline at end of file diff --git a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/substituteNode/SubstituteSpringbootTest.java b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/substituteNode/SubstituteSpringbootTest.java deleted file mode 100644 index 9323de377..000000000 --- a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/substituteNode/SubstituteSpringbootTest.java +++ /dev/null @@ -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()); - } - -} diff --git a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/substituteNode/cmp/ACmp.java b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/substituteNode/cmp/ACmp.java deleted file mode 100644 index b6e1d7d80..000000000 --- a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/substituteNode/cmp/ACmp.java +++ /dev/null @@ -1,21 +0,0 @@ -/** - *

Title: liteflow

- *

Description: 轻量级的组件式流程框架

- * @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!"); - } - -} diff --git a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/substituteNode/cmp/BCmp.java b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/substituteNode/cmp/BCmp.java deleted file mode 100644 index 495db7ac3..000000000 --- a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/substituteNode/cmp/BCmp.java +++ /dev/null @@ -1,21 +0,0 @@ -/** - *

Title: liteflow

- *

Description: 轻量级的组件式流程框架

- * @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!"); - } - -} diff --git a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/substituteNode/cmp/CCmp.java b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/substituteNode/cmp/CCmp.java deleted file mode 100644 index dca6da62a..000000000 --- a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/substituteNode/cmp/CCmp.java +++ /dev/null @@ -1,21 +0,0 @@ -/** - *

Title: liteflow

- *

Description: 轻量级的组件式流程框架

- * @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!"); - } - -} diff --git a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/substituteNode/cmp/DCmp.java b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/substituteNode/cmp/DCmp.java deleted file mode 100644 index 728b48ff9..000000000 --- a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/substituteNode/cmp/DCmp.java +++ /dev/null @@ -1,21 +0,0 @@ -/** - *

Title: liteflow

- *

Description: 轻量级的组件式流程框架

- * @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!"); - } - -} diff --git a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/substituteNode/cmp/SubCmp.java b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/substituteNode/cmp/SubCmp.java deleted file mode 100644 index 620490341..000000000 --- a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/substituteNode/cmp/SubCmp.java +++ /dev/null @@ -1,21 +0,0 @@ -/** - *

Title: liteflow

- *

Description: 轻量级的组件式流程框架

- * @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!"); - } - -} diff --git a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/substituteNode/application.properties b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/substituteNode/application.properties deleted file mode 100644 index 35bdc3a1e..000000000 --- a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/substituteNode/application.properties +++ /dev/null @@ -1,2 +0,0 @@ -liteflow.rule-source=substituteNode/flow.el.xml -liteflow.substitute-cmp-class=com.yomahub.liteflow.test.substituteNode.cmp.SubCmp \ No newline at end of file diff --git a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/substituteNode/flow.el.xml b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/substituteNode/flow.el.xml deleted file mode 100644 index 7730921b9..000000000 --- a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/substituteNode/flow.el.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - - THEN(node("a"), node("b"), node("c")); - - - - THEN(node("a"), node("b"), node("93-nodeTEST")); - - - - THEN(a, b, node("88-ffc")); - - \ No newline at end of file From acdafba0902e04ae3e4b4e4745b38b3705d48377 Mon Sep 17 00:00:00 2001 From: Dale Lee <1658850308@qq.com> Date: Mon, 2 Oct 2023 19:10:53 +0800 Subject: [PATCH 5/8] =?UTF-8?q?feature=20#I7YYLE=20=E6=A0=BC=E5=BC=8F?= =?UTF-8?q?=E5=8C=96=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../builder/el/operator/IteratorOperator.java | 10 +-- .../builder/el/operator/NodeOperator.java | 42 +++++------ .../builder/el/operator/SwitchOperator.java | 8 +-- .../FallbackCmpNotFoundException.java | 12 ++-- .../com/yomahub/liteflow/flow/FlowBus.java | 72 +++++++++---------- .../liteflow/flow/element/Condition.java | 50 ++++++------- .../flow/element/FallbackNodeProxy.java | 52 +++++++------- .../test/fallback/FallbackSpringbootTest.java | 48 ++++++------- .../liteflow/test/fallback/cmp/ACmp.java | 9 +-- .../liteflow/test/fallback/cmp/BCmp.java | 9 +-- .../liteflow/test/fallback/cmp/BreakCmp.java | 2 +- .../liteflow/test/fallback/cmp/CCmp.java | 9 +-- .../liteflow/test/fallback/cmp/DCmp.java | 2 +- .../liteflow/test/fallback/cmp/ForCmp.java | 2 +- .../liteflow/test/fallback/cmp/IfCmp1.java | 2 +- .../liteflow/test/fallback/cmp/IfCmp2.java | 2 +- .../test/fallback/cmp/IteratorCmp1.java | 2 +- .../test/fallback/cmp/IteratorCmp2.java | 2 +- .../test/fallback/cmp/SwitchCmp1.java | 2 +- .../test/fallback/cmp/SwitchCmp2.java | 2 +- .../liteflow/test/fallback/cmp/WhileCmp1.java | 4 +- 21 files changed, 173 insertions(+), 170 deletions(-) diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/IteratorOperator.java b/liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/IteratorOperator.java index 468b36188..fcb5df729 100644 --- a/liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/IteratorOperator.java +++ b/liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/IteratorOperator.java @@ -9,20 +9,20 @@ import com.yomahub.liteflow.flow.element.Node; import com.yomahub.liteflow.flow.element.condition.IteratorCondition; public class IteratorOperator extends BaseOperator { - + @Override public IteratorCondition build(Object[] objects) throws Exception { OperatorHelper.checkObjectSizeEq(objects, 1); - + Node node = OperatorHelper.convert(objects[0], Node.class); if (!ListUtil.toList(NodeTypeEnum.ITERATOR, NodeTypeEnum.FALLBACK).contains(node.getType())) { throw new QLException("The parameter must be iterator-node item"); } - + IteratorCondition iteratorCondition = new IteratorCondition(); iteratorCondition.setIteratorNode(node); - + return iteratorCondition; } - + } diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/NodeOperator.java b/liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/NodeOperator.java index 007223126..8fa963fbb 100644 --- a/liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/NodeOperator.java +++ b/liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/NodeOperator.java @@ -24,26 +24,26 @@ import com.yomahub.liteflow.property.LiteflowConfigGetter; * @since 2.8.3 */ public class NodeOperator extends BaseOperator { - - @Override - public Node build(Object[] objects) throws Exception { - // 检查是否开启了组件降级功能 - LiteflowConfig liteflowConfig = LiteflowConfigGetter.get(); - Boolean enable = liteflowConfig.getFallbackCmpEnable(); - if (!enable) { - throw new ELParseException("The fallback component is disabled"); - } - - OperatorHelper.checkObjectSizeEqOne(objects); - String nodeId = OperatorHelper.convert(objects[0], String.class); - - if (FlowBus.containNode(nodeId)) { - // 找到对应节点 - return FlowBus.getNode(nodeId); - } else { - // 生成代理节点 - return new FallbackNodeProxy(nodeId); - } - } + + @Override + public Node build(Object[] objects) throws Exception { + // 检查是否开启了组件降级功能 + LiteflowConfig liteflowConfig = LiteflowConfigGetter.get(); + Boolean enable = liteflowConfig.getFallbackCmpEnable(); + if (!enable) { + throw new ELParseException("The fallback component is disabled"); + } + + OperatorHelper.checkObjectSizeEqOne(objects); + String nodeId = OperatorHelper.convert(objects[0], String.class); + + if (FlowBus.containNode(nodeId)) { + // 找到对应节点 + return FlowBus.getNode(nodeId); + } else { + // 生成代理节点 + return new FallbackNodeProxy(nodeId); + } + } } diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/SwitchOperator.java b/liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/SwitchOperator.java index 5dee3ebd1..b4bf6f689 100644 --- a/liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/SwitchOperator.java +++ b/liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/SwitchOperator.java @@ -15,20 +15,20 @@ import com.yomahub.liteflow.flow.element.condition.SwitchCondition; * @since 2.8.0 */ public class SwitchOperator extends BaseOperator { - + @Override public SwitchCondition build(Object[] objects) throws Exception { OperatorHelper.checkObjectSizeEqOne(objects); - + Node switchNode = OperatorHelper.convert(objects[0], Node.class); if (!ListUtil.toList(NodeTypeEnum.SWITCH, NodeTypeEnum.SWITCH_SCRIPT, NodeTypeEnum.FALLBACK) .contains(switchNode.getType())) { throw new QLException("The caller must be Switch item"); } - + SwitchCondition switchCondition = new SwitchCondition(); switchCondition.setSwitchNode(switchNode); - + return switchCondition; } } diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/exception/FallbackCmpNotFoundException.java b/liteflow-core/src/main/java/com/yomahub/liteflow/exception/FallbackCmpNotFoundException.java index a334ea60f..de930dfee 100644 --- a/liteflow-core/src/main/java/com/yomahub/liteflow/exception/FallbackCmpNotFoundException.java +++ b/liteflow-core/src/main/java/com/yomahub/liteflow/exception/FallbackCmpNotFoundException.java @@ -6,25 +6,25 @@ package com.yomahub.liteflow.exception; * @author DaleLee */ 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; } - + } diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/flow/FlowBus.java b/liteflow-core/src/main/java/com/yomahub/liteflow/flow/FlowBus.java index 218502db0..abb439ccc 100644 --- a/liteflow-core/src/main/java/com/yomahub/liteflow/flow/FlowBus.java +++ b/liteflow-core/src/main/java/com/yomahub/liteflow/flow/FlowBus.java @@ -47,63 +47,63 @@ import java.util.stream.Collectors; * @author Bryan.Zhang */ public class FlowBus { - + private static final LFLog LOG = LFLoggerManager.getLogger(FlowBus.class); - + private static final Map chainMap = new CopyOnWriteHashMap<>(); - + private static final Map nodeMap = new CopyOnWriteHashMap<>(); - + private static final Map fallbackNodeMap = new CopyOnWriteHashMap<>(); - + private FlowBus() { } - + public static Chain getChain(String id) { return chainMap.get(id); } - + // 这一方法主要用于第一阶段chain的预装载 public static void addChain(String chainName) { if (!chainMap.containsKey(chainName)) { chainMap.put(chainName, new Chain(chainName)); } } - + // 这个方法主要用于第二阶段的替换chain public static void addChain(Chain chain) { chainMap.put(chain.getChainId(), chain); } - + public static boolean containChain(String chainId) { return chainMap.containsKey(chainId); } - + public static boolean needInit() { return MapUtil.isEmpty(chainMap); } - + public static boolean containNode(String nodeId) { return nodeMap.containsKey(nodeId); } - + /** * 添加已托管的节点(如:Spring、Solon 管理的节点) */ public static void addManagedNode(String nodeId, NodeComponent nodeComponent) { // 根据class来猜测类型 NodeTypeEnum type = NodeTypeEnum.guessType(nodeComponent.getClass()); - + if (type == null) { throw new NullNodeTypeException(StrUtil.format("node type is null for node[{}]", nodeId)); } - + Node node = new Node(ComponentInitializer.loadInstance() .initComponent(nodeComponent, type, nodeComponent.getName(), nodeId)); nodeMap.put(nodeId, node); addFallbackNode(node); } - + /** * 添加 node * @@ -115,7 +115,7 @@ public class FlowBus { public static void addNode(String nodeId, String name, NodeTypeEnum type, Class cmpClazz) { addNode(nodeId, name, type, cmpClazz, null, null); } - + /** * 添加 node * @@ -133,7 +133,7 @@ public class FlowBus { } addNode(nodeId, name, nodeType, cmpClazz, null, null); } - + /** * 添加脚本 node * @@ -143,12 +143,12 @@ public class FlowBus { * @param script 脚本 */ public static void addScriptNode(String nodeId, String name, NodeTypeEnum nodeType, String script, - String language) { + String language) { addNode(nodeId, name, nodeType, ScriptComponent.ScriptComponentClassMap.get(nodeType), script, language); } - + private static void addNode(String nodeId, String name, NodeTypeEnum type, Class cmpClazz, String script, - String language) { + String language) { try { // 判断此类是否是声明式的组件,如果是声明式的组件,就用动态代理生成实例 // 如果不是声明式的,就用传统的方式进行判断 @@ -188,10 +188,10 @@ public class FlowBus { .initComponent(cmpInstance, type, name, cmpInstance.getNodeId() == null ? nodeId : cmpInstance.getNodeId())) .collect(Collectors.toList()); - + // 初始化Node,把component放到Node里去 List nodes = cmpInstances.stream().map(Node::new).collect(Collectors.toList()); - + for (int i = 0; i < nodes.size(); i++) { Node node = nodes.get(i); NodeComponent cmpInstance = cmpInstances.get(i); @@ -206,12 +206,12 @@ public class FlowBus { throw new ScriptLoadException(errorMsg); } } - + String activeNodeId = StrUtil.isEmpty(cmpInstance.getNodeId()) ? nodeId : cmpInstance.getNodeId(); nodeMap.put(activeNodeId, node); addFallbackNode(node); } - + } catch (Exception e) { String error = StrUtil.format("component[{}] register error", StrUtil.isEmpty(name) ? nodeId : StrUtil.format("{}({})", nodeId, name)); @@ -219,30 +219,30 @@ public class FlowBus { throw new ComponentCannotRegisterException(StrUtil.format("{} {}", error, e.getMessage())); } } - + public static Node getNode(String nodeId) { return nodeMap.get(nodeId); } - + public static Map getNodeMap() { return nodeMap; } - + public static Map getChainMap() { return chainMap; } - + public static Node getFallBackNode(NodeTypeEnum nodeType) { return fallbackNodeMap.get(nodeType); } - + public static void cleanCache() { chainMap.clear(); nodeMap.clear(); fallbackNodeMap.clear(); cleanScriptCache(); } - + public static void cleanScriptCache() { // 如果引入了脚本组件SPI,则还需要清理脚本的缓存 try { @@ -250,7 +250,7 @@ public class FlowBus { } catch (ScriptSpiException ignored) { } } - + public static void refreshFlowMetaData(FlowParserTypeEnum type, String content) throws Exception { if (type.equals(FlowParserTypeEnum.TYPE_EL_XML)) { new LocalXmlFlowELParser().parse(content); @@ -260,7 +260,7 @@ public class FlowBus { new LocalYmlFlowELParser().parse(content); } } - + public static boolean removeChain(String chainId) { if (containChain(chainId)) { chainMap.remove(chainId); @@ -271,23 +271,23 @@ public class FlowBus { return false; } } - + public static void removeChain(String... chainIds) { Arrays.stream(chainIds).forEach(FlowBus::removeChain); } - + 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(); if (nodeType == null) { nodeType = fallbackCmp.type(); } fallbackNodeMap.put(nodeType, node); } - + } diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/flow/element/Condition.java b/liteflow-core/src/main/java/com/yomahub/liteflow/flow/element/Condition.java index e72f9f1b9..2b3f71301 100644 --- a/liteflow-core/src/main/java/com/yomahub/liteflow/flow/element/Condition.java +++ b/liteflow-core/src/main/java/com/yomahub/liteflow/flow/element/Condition.java @@ -30,21 +30,21 @@ import java.util.Map; * @author Bryan.Zhang */ public abstract class Condition implements Executable { - + private String id; - + private String tag; - + /** * 可执行元素的集合 */ private final Map> executableGroup = new HashMap<>(); - + /** * 当前所在的ChainName 如果对于子流程来说,那这个就是子流程所在的Chain */ private String currChainId; - + @Override public void execute(Integer slotIndex) throws Exception { // 当前 Condition 入栈 @@ -70,18 +70,18 @@ public abstract class Condition implements Executable { slot.popCondition(); } } - + public abstract void executeCondition(Integer slotIndex) throws Exception; - + @Override public ExecuteTypeEnum getExecuteType() { return ExecuteTypeEnum.CONDITION; } - + public List getExecutableList() { return getExecutableList(ConditionKey.DEFAULT_KEY); } - + public List getExecutableList(String groupKey) { List executableList = this.executableGroup.get(groupKey); if (CollUtil.isEmpty(executableList)) { @@ -89,7 +89,7 @@ public abstract class Condition implements Executable { } return executableList; } - + public Executable getExecutableOne(String groupKey) { List list = getExecutableList(groupKey); if (CollUtil.isEmpty(list)) { @@ -98,15 +98,15 @@ public abstract class Condition implements Executable { return list.get(0); } } - + public void setExecutableList(List executableList) { this.executableGroup.put(ConditionKey.DEFAULT_KEY, executableList); } - + public void addExecutable(Executable executable) { addExecutable(ConditionKey.DEFAULT_KEY, executable); } - + public void addExecutable(String groupKey, Executable executable) { if (ObjectUtil.isNull(executable)) { return; @@ -118,29 +118,29 @@ public abstract class Condition implements Executable { this.executableGroup.get(groupKey).add(executable); } } - + public abstract ConditionTypeEnum getConditionType(); - - @Override + + @Override public String getId() { return id; } - - @Override + + @Override public void setId(String id) { this.id = id; } - + @Override public String getTag() { return tag; } - - @Override + + @Override public void setTag(String tag) { this.tag = tag; } - + /** * 请使用 {@link #setCurrChainId(String)} */ @@ -148,16 +148,16 @@ public abstract class Condition implements Executable { public String getCurrChainName() { return currChainId; } - + public String getCurrChainId() { return currChainId; } - + @Override public void setCurrChainId(String currChainId) { this.currChainId = currChainId; } - + public Map> getExecutableGroup() { return executableGroup; } diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/flow/element/FallbackNodeProxy.java b/liteflow-core/src/main/java/com/yomahub/liteflow/flow/element/FallbackNodeProxy.java index 465962216..5ad5abe82 100644 --- a/liteflow-core/src/main/java/com/yomahub/liteflow/flow/element/FallbackNodeProxy.java +++ b/liteflow-core/src/main/java/com/yomahub/liteflow/flow/element/FallbackNodeProxy.java @@ -18,29 +18,29 @@ import com.yomahub.liteflow.slot.DataBus; import com.yomahub.liteflow.slot.Slot; 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)) { // 已经加载过了 @@ -60,7 +60,7 @@ public class FallbackNodeProxy extends Node { // 使用 node 的副本 this.fallbackNode = node.copy(); } - + private Node findFallbackNode(Condition condition) { ConditionTypeEnum conditionType = condition.getConditionType(); switch (conditionType) { @@ -87,95 +87,95 @@ public class FallbackNodeProxy extends Node { 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 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; } diff --git a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/fallback/FallbackSpringbootTest.java b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/fallback/FallbackSpringbootTest.java index 8f49d79fe..7614feff6 100644 --- a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/fallback/FallbackSpringbootTest.java +++ b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/fallback/FallbackSpringbootTest.java @@ -16,24 +16,24 @@ import javax.annotation.Resource; @EnableAutoConfiguration @ComponentScan({"com.yomahub.liteflow.test.fallback.cmp"}) public class FallbackSpringbootTest { - + @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"); @@ -41,140 +41,140 @@ public class FallbackSpringbootTest { 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"); diff --git a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/fallback/cmp/ACmp.java b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/fallback/cmp/ACmp.java index 05102a985..3dbb2c4d6 100644 --- a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/fallback/cmp/ACmp.java +++ b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/fallback/cmp/ACmp.java @@ -1,6 +1,7 @@ /** *

Title: liteflow

*

Description: 轻量级的组件式流程框架

+ * * @author Bryan.Zhang * @email weenyc31@163.com * @Date 2020/4/1 @@ -13,9 +14,9 @@ import com.yomahub.liteflow.core.NodeComponent; @LiteflowComponent("a") public class ACmp extends NodeComponent { - @Override - public void process() { - System.out.println("ACmp executed!"); - } + @Override + public void process() { + System.out.println("ACmp executed!"); + } } diff --git a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/fallback/cmp/BCmp.java b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/fallback/cmp/BCmp.java index c634c78fc..86eeccee1 100644 --- a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/fallback/cmp/BCmp.java +++ b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/fallback/cmp/BCmp.java @@ -1,6 +1,7 @@ /** *

Title: liteflow

*

Description: 轻量级的组件式流程框架

+ * * @author Bryan.Zhang * @email weenyc31@163.com * @Date 2020/4/1 @@ -16,9 +17,9 @@ import javax.annotation.Resource; @LiteflowComponent("b") public class BCmp extends NodeComponent { - @Override - public void process() { - System.out.println("BCmp executed!"); - } + @Override + public void process() { + System.out.println("BCmp executed!"); + } } diff --git a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/fallback/cmp/BreakCmp.java b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/fallback/cmp/BreakCmp.java index ec23619ff..32813ffe3 100644 --- a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/fallback/cmp/BreakCmp.java +++ b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/fallback/cmp/BreakCmp.java @@ -7,7 +7,7 @@ import com.yomahub.liteflow.core.NodeBreakComponent; @LiteflowComponent("bn1") @FallbackCmp public class BreakCmp extends NodeBreakComponent { - + @Override public boolean processBreak() throws Exception { return true; diff --git a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/fallback/cmp/CCmp.java b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/fallback/cmp/CCmp.java index 8340fd0c3..4a9259847 100644 --- a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/fallback/cmp/CCmp.java +++ b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/fallback/cmp/CCmp.java @@ -1,6 +1,7 @@ /** *

Title: liteflow

*

Description: 轻量级的组件式流程框架

+ * * @author Bryan.Zhang * @email weenyc31@163.com * @Date 2020/4/1 @@ -17,9 +18,9 @@ import org.springframework.stereotype.Component; @FallbackCmp public class CCmp extends NodeComponent { - @Override - public void process() { - System.out.println("CCmp executed!"); - } + @Override + public void process() { + System.out.println("CCmp executed!"); + } } diff --git a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/fallback/cmp/DCmp.java b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/fallback/cmp/DCmp.java index d036751c5..5d7fd18ee 100644 --- a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/fallback/cmp/DCmp.java +++ b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/fallback/cmp/DCmp.java @@ -5,7 +5,7 @@ import com.yomahub.liteflow.core.NodeComponent; @LiteflowComponent("d") public class DCmp extends NodeComponent { - + @Override public void process() throws Exception { throw new RuntimeException("component[d]"); diff --git a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/fallback/cmp/ForCmp.java b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/fallback/cmp/ForCmp.java index a0f47f408..2607f8acc 100644 --- a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/fallback/cmp/ForCmp.java +++ b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/fallback/cmp/ForCmp.java @@ -7,7 +7,7 @@ import com.yomahub.liteflow.core.NodeForComponent; @LiteflowComponent("for1") @FallbackCmp public class ForCmp extends NodeForComponent { - + @Override public int processFor() throws Exception { return 3; diff --git a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/fallback/cmp/IfCmp1.java b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/fallback/cmp/IfCmp1.java index d95597e20..62b47dec1 100644 --- a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/fallback/cmp/IfCmp1.java +++ b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/fallback/cmp/IfCmp1.java @@ -5,7 +5,7 @@ import com.yomahub.liteflow.core.NodeIfComponent; @LiteflowComponent("ifn1") public class IfCmp1 extends NodeIfComponent { - + @Override public boolean processIf() throws Exception { return true; diff --git a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/fallback/cmp/IfCmp2.java b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/fallback/cmp/IfCmp2.java index 2626056c2..c5b20fcd8 100644 --- a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/fallback/cmp/IfCmp2.java +++ b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/fallback/cmp/IfCmp2.java @@ -7,7 +7,7 @@ import com.yomahub.liteflow.core.NodeIfComponent; @LiteflowComponent("ifn2") @FallbackCmp public class IfCmp2 extends NodeIfComponent { - + @Override public boolean processIf() throws Exception { return false; diff --git a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/fallback/cmp/IteratorCmp1.java b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/fallback/cmp/IteratorCmp1.java index 02a9f1ca7..b63cb7c71 100644 --- a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/fallback/cmp/IteratorCmp1.java +++ b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/fallback/cmp/IteratorCmp1.java @@ -8,7 +8,7 @@ import java.util.Iterator; @LiteflowComponent("itn1") public class IteratorCmp1 extends NodeIteratorComponent { - + @Override public Iterator processIterator() throws Exception { return Arrays.asList("a", "b", "c").iterator(); diff --git a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/fallback/cmp/IteratorCmp2.java b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/fallback/cmp/IteratorCmp2.java index 9d0a7eabc..c45f19034 100644 --- a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/fallback/cmp/IteratorCmp2.java +++ b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/fallback/cmp/IteratorCmp2.java @@ -10,7 +10,7 @@ import java.util.Iterator; @LiteflowComponent("itn2") @FallbackCmp public class IteratorCmp2 extends NodeIteratorComponent { - + @Override public Iterator processIterator() throws Exception { return Collections.emptyIterator(); diff --git a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/fallback/cmp/SwitchCmp1.java b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/fallback/cmp/SwitchCmp1.java index e98fa71e7..1cb3fe1c3 100644 --- a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/fallback/cmp/SwitchCmp1.java +++ b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/fallback/cmp/SwitchCmp1.java @@ -5,7 +5,7 @@ import com.yomahub.liteflow.core.NodeSwitchComponent; @LiteflowComponent("swn1") public class SwitchCmp1 extends NodeSwitchComponent { - + @Override public String processSwitch() throws Exception { return "a"; diff --git a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/fallback/cmp/SwitchCmp2.java b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/fallback/cmp/SwitchCmp2.java index d8146c0f1..28b1edcfd 100644 --- a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/fallback/cmp/SwitchCmp2.java +++ b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/fallback/cmp/SwitchCmp2.java @@ -7,7 +7,7 @@ import com.yomahub.liteflow.core.NodeSwitchComponent; @LiteflowComponent("swn2") @FallbackCmp public class SwitchCmp2 extends NodeSwitchComponent { - + @Override public String processSwitch() throws Exception { return "b"; diff --git a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/fallback/cmp/WhileCmp1.java b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/fallback/cmp/WhileCmp1.java index c355e7383..6769480c6 100644 --- a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/fallback/cmp/WhileCmp1.java +++ b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/fallback/cmp/WhileCmp1.java @@ -9,10 +9,10 @@ import java.util.Set; @LiteflowComponent("wn1") public class WhileCmp1 extends NodeWhileComponent { private int count = 0; - + // 执行过的 chain Set executedChain = new HashSet<>(); - + @Override public boolean processWhile() throws Exception { // 判断是否切换了 chain From bb9b355f8b857052db0c8ef1bc509322c84220ef Mon Sep 17 00:00:00 2001 From: Dale Lee <1658850308@qq.com> Date: Mon, 2 Oct 2023 20:14:33 +0800 Subject: [PATCH 6/8] =?UTF-8?q?feature=20#I7YYLE=20=E5=AE=8C=E5=96=84?= =?UTF-8?q?=E6=B3=A8=E9=87=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../builder/el/operator/NodeOperator.java | 23 ++++++------------- .../com/yomahub/liteflow/flow/FlowBus.java | 1 + .../liteflow/flow/element/Condition.java | 1 + .../flow/element/FallbackNodeProxy.java | 6 +++++ .../java/com/yomahub/liteflow/slot/Slot.java | 1 + .../test/fallback/FallbackSpringbootTest.java | 5 ++++ 6 files changed, 21 insertions(+), 16 deletions(-) diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/NodeOperator.java b/liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/NodeOperator.java index 8fa963fbb..7f7849b53 100644 --- a/liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/NodeOperator.java +++ b/liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/NodeOperator.java @@ -1,15 +1,7 @@ package com.yomahub.liteflow.builder.el.operator; -import cn.hutool.core.util.ObjectUtil; -import cn.hutool.core.util.StrUtil; -import com.ql.util.express.ArraySwap; -import com.ql.util.express.IExpressContext; -import com.ql.util.express.InstructionSetContext; -import com.ql.util.express.OperateData; -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.core.NodeComponent; import com.yomahub.liteflow.exception.ELParseException; import com.yomahub.liteflow.flow.FlowBus; import com.yomahub.liteflow.flow.element.FallbackNodeProxy; @@ -20,20 +12,13 @@ import com.yomahub.liteflow.property.LiteflowConfigGetter; /** * EL规则中的node的操作符 * - * @author Bryan.Zhang + * @author Bryan.Zhang,DaleLee * @since 2.8.3 */ public class NodeOperator extends BaseOperator { @Override public Node build(Object[] objects) throws Exception { - // 检查是否开启了组件降级功能 - LiteflowConfig liteflowConfig = LiteflowConfigGetter.get(); - Boolean enable = liteflowConfig.getFallbackCmpEnable(); - if (!enable) { - throw new ELParseException("The fallback component is disabled"); - } - OperatorHelper.checkObjectSizeEqOne(objects); String nodeId = OperatorHelper.convert(objects[0], String.class); @@ -41,6 +26,12 @@ public class NodeOperator extends BaseOperator { // 找到对应节点 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); } diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/flow/FlowBus.java b/liteflow-core/src/main/java/com/yomahub/liteflow/flow/FlowBus.java index abb439ccc..920987bfc 100644 --- a/liteflow-core/src/main/java/com/yomahub/liteflow/flow/FlowBus.java +++ b/liteflow-core/src/main/java/com/yomahub/liteflow/flow/FlowBus.java @@ -45,6 +45,7 @@ import java.util.stream.Collectors; * 流程元数据类 * * @author Bryan.Zhang + * @author DaleLee */ public class FlowBus { diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/flow/element/Condition.java b/liteflow-core/src/main/java/com/yomahub/liteflow/flow/element/Condition.java index 2b3f71301..8d481c274 100644 --- a/liteflow-core/src/main/java/com/yomahub/liteflow/flow/element/Condition.java +++ b/liteflow-core/src/main/java/com/yomahub/liteflow/flow/element/Condition.java @@ -28,6 +28,7 @@ import java.util.Map; * Condition的抽象类 * * @author Bryan.Zhang + * @author DaleLee */ public abstract class Condition implements Executable { diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/flow/element/FallbackNodeProxy.java b/liteflow-core/src/main/java/com/yomahub/liteflow/flow/element/FallbackNodeProxy.java index 5ad5abe82..e4f7cb370 100644 --- a/liteflow-core/src/main/java/com/yomahub/liteflow/flow/element/FallbackNodeProxy.java +++ b/liteflow-core/src/main/java/com/yomahub/liteflow/flow/element/FallbackNodeProxy.java @@ -17,6 +17,12 @@ import com.yomahub.liteflow.flow.element.condition.WhileCondition; import com.yomahub.liteflow.slot.DataBus; import com.yomahub.liteflow.slot.Slot; +/** + * 降级组件代理 + * + * @author DaleLee + * @since + */ public class FallbackNodeProxy extends Node { // 原节点 id diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/slot/Slot.java b/liteflow-core/src/main/java/com/yomahub/liteflow/slot/Slot.java index 8b3275187..ebe3289f8 100644 --- a/liteflow-core/src/main/java/com/yomahub/liteflow/slot/Slot.java +++ b/liteflow-core/src/main/java/com/yomahub/liteflow/slot/Slot.java @@ -33,6 +33,7 @@ import java.util.concurrent.ConcurrentLinkedQueue; * * @author Bryan.Zhang * @author LeoLee + * @author DaleLee */ @SuppressWarnings("unchecked") public class Slot { diff --git a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/fallback/FallbackSpringbootTest.java b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/fallback/FallbackSpringbootTest.java index 7614feff6..2100becb2 100644 --- a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/fallback/FallbackSpringbootTest.java +++ b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/fallback/FallbackSpringbootTest.java @@ -11,6 +11,11 @@ import org.springframework.test.context.TestPropertySource; import javax.annotation.Resource; +/** + * SpringBoot 降级组件测试 + * + * @author DaleLee + */ @TestPropertySource(value = "classpath:/fallback/application.properties") @SpringBootTest(classes = FallbackSpringbootTest.class) @EnableAutoConfiguration From 63b1e2744a104a29abb59f92d25834610faf52f4 Mon Sep 17 00:00:00 2001 From: Dale Lee <1658850308@qq.com> Date: Wed, 4 Oct 2023 16:28:18 +0800 Subject: [PATCH 7/8] =?UTF-8?q?feature=20#I7YYLE=20=E6=94=AF=E6=8C=81?= =?UTF-8?q?=E5=B9=B6=E5=8F=91=E7=8E=AF=E5=A2=83=E4=B8=8B=E7=9A=84=E7=BB=84?= =?UTF-8?q?=E4=BB=B6=E9=99=8D=E7=BA=A7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../builder/el/operator/IteratorOperator.java | 22 +- .../builder/el/operator/SwitchOperator.java | 24 +- .../com/yomahub/liteflow/flow/FlowBus.java | 431 +++++++++--------- .../liteflow/flow/element/Condition.java | 229 +++++----- .../java/com/yomahub/liteflow/slot/Slot.java | 10 +- .../test/fallback/FallbackSpringbootTest.java | 34 ++ .../liteflow/test/fallback/cmp/ACmp.java | 8 - .../liteflow/test/fallback/cmp/BCmp.java | 8 - .../liteflow/test/fallback/cmp/CCmp.java | 8 - .../src/test/resources/fallback/flow.el.xml | 20 +- 10 files changed, 417 insertions(+), 377 deletions(-) diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/IteratorOperator.java b/liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/IteratorOperator.java index fcb5df729..696fdc1e6 100644 --- a/liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/IteratorOperator.java +++ b/liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/IteratorOperator.java @@ -10,19 +10,19 @@ import com.yomahub.liteflow.flow.element.condition.IteratorCondition; public class IteratorOperator extends BaseOperator { - @Override - public IteratorCondition build(Object[] objects) throws Exception { - OperatorHelper.checkObjectSizeEq(objects, 1); + @Override + public IteratorCondition build(Object[] objects) throws Exception { + OperatorHelper.checkObjectSizeEq(objects, 1); - Node node = OperatorHelper.convert(objects[0], Node.class); - if (!ListUtil.toList(NodeTypeEnum.ITERATOR, NodeTypeEnum.FALLBACK).contains(node.getType())) { - throw new QLException("The parameter must be iterator-node item"); - } + Node node = OperatorHelper.convert(objects[0], Node.class); + if (!ListUtil.toList(NodeTypeEnum.ITERATOR, NodeTypeEnum.FALLBACK).contains(node.getType())) { + throw new QLException("The parameter must be iterator-node item"); + } - IteratorCondition iteratorCondition = new IteratorCondition(); - iteratorCondition.setIteratorNode(node); + IteratorCondition iteratorCondition = new IteratorCondition(); + iteratorCondition.setIteratorNode(node); - return iteratorCondition; - } + return iteratorCondition; + } } diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/SwitchOperator.java b/liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/SwitchOperator.java index b4bf6f689..041628ee3 100644 --- a/liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/SwitchOperator.java +++ b/liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/SwitchOperator.java @@ -16,19 +16,19 @@ import com.yomahub.liteflow.flow.element.condition.SwitchCondition; */ public class SwitchOperator extends BaseOperator { - @Override - public SwitchCondition build(Object[] objects) throws Exception { - OperatorHelper.checkObjectSizeEqOne(objects); + @Override + public SwitchCondition build(Object[] objects) throws Exception { + OperatorHelper.checkObjectSizeEqOne(objects); - Node switchNode = OperatorHelper.convert(objects[0], Node.class); - if (!ListUtil.toList(NodeTypeEnum.SWITCH, NodeTypeEnum.SWITCH_SCRIPT, NodeTypeEnum.FALLBACK) - .contains(switchNode.getType())) { - throw new QLException("The caller must be Switch item"); - } + Node switchNode = OperatorHelper.convert(objects[0], Node.class); + if (!ListUtil.toList(NodeTypeEnum.SWITCH, NodeTypeEnum.SWITCH_SCRIPT, NodeTypeEnum.FALLBACK).contains(switchNode.getType())) { + throw new QLException("The caller must be Switch item"); + } - SwitchCondition switchCondition = new SwitchCondition(); - switchCondition.setSwitchNode(switchNode); + SwitchCondition switchCondition = new SwitchCondition(); + switchCondition.setSwitchNode(switchNode); + + return switchCondition; + } - return switchCondition; - } } diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/flow/FlowBus.java b/liteflow-core/src/main/java/com/yomahub/liteflow/flow/FlowBus.java index 920987bfc..b77f564db 100644 --- a/liteflow-core/src/main/java/com/yomahub/liteflow/flow/FlowBus.java +++ b/liteflow-core/src/main/java/com/yomahub/liteflow/flow/FlowBus.java @@ -6,7 +6,6 @@ * @email weenyc31@163.com * @Date 2020/4/1 */ - package com.yomahub.liteflow.flow; import cn.hutool.core.collection.ListUtil; @@ -14,7 +13,9 @@ import cn.hutool.core.map.MapUtil; import cn.hutool.core.util.StrUtil; import com.yomahub.liteflow.annotation.FallbackCmp; import com.yomahub.liteflow.annotation.util.AnnoUtil; -import com.yomahub.liteflow.core.*; +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; @@ -49,246 +50,254 @@ import java.util.stream.Collectors; */ public class FlowBus { - private static final LFLog LOG = LFLoggerManager.getLogger(FlowBus.class); + private static final LFLog LOG = LFLoggerManager.getLogger(FlowBus.class); - private static final Map chainMap = new CopyOnWriteHashMap<>(); + private static final Map chainMap = new CopyOnWriteHashMap<>(); - private static final Map nodeMap = new CopyOnWriteHashMap<>(); + private static final Map nodeMap = new CopyOnWriteHashMap<>(); - private static final Map fallbackNodeMap = new CopyOnWriteHashMap<>(); + private static final Map fallbackNodeMap = new CopyOnWriteHashMap<>(); - private FlowBus() { - } + private FlowBus() { + } - public static Chain getChain(String id) { - return chainMap.get(id); - } + public static Chain getChain(String id) { + return chainMap.get(id); + } - // 这一方法主要用于第一阶段chain的预装载 - public static void addChain(String chainName) { - if (!chainMap.containsKey(chainName)) { - chainMap.put(chainName, new Chain(chainName)); - } - } + // 这一方法主要用于第一阶段chain的预装载 + public static void addChain(String chainName) { + if (!chainMap.containsKey(chainName)) { + chainMap.put(chainName, new Chain(chainName)); + } + } - // 这个方法主要用于第二阶段的替换chain - public static void addChain(Chain chain) { - chainMap.put(chain.getChainId(), chain); - } + // 这个方法主要用于第二阶段的替换chain + public static void addChain(Chain chain) { + chainMap.put(chain.getChainId(), chain); + } - public static boolean containChain(String chainId) { - return chainMap.containsKey(chainId); - } + public static boolean containChain(String chainId) { + return chainMap.containsKey(chainId); + } - public static boolean needInit() { - return MapUtil.isEmpty(chainMap); - } + public static boolean needInit() { + return MapUtil.isEmpty(chainMap); + } - public static boolean containNode(String nodeId) { - return nodeMap.containsKey(nodeId); - } + public static boolean containNode(String nodeId) { + return nodeMap.containsKey(nodeId); + } - /** - * 添加已托管的节点(如:Spring、Solon 管理的节点) - */ - public static void addManagedNode(String nodeId, NodeComponent nodeComponent) { - // 根据class来猜测类型 - NodeTypeEnum type = NodeTypeEnum.guessType(nodeComponent.getClass()); + /** + * 添加已托管的节点(如:Spring、Solon 管理的节点) + * */ + public static void addManagedNode(String nodeId, NodeComponent nodeComponent) { + // 根据class来猜测类型 + NodeTypeEnum type = NodeTypeEnum.guessType(nodeComponent.getClass()); - if (type == null) { - throw new NullNodeTypeException(StrUtil.format("node type is null for node[{}]", nodeId)); - } + if (type == null) { + throw new NullNodeTypeException(StrUtil.format("node type is null for node[{}]", nodeId)); + } - Node node = new Node(ComponentInitializer.loadInstance() - .initComponent(nodeComponent, type, nodeComponent.getName(), nodeId)); - nodeMap.put(nodeId, node); - addFallbackNode(node); - } + Node node = new Node(ComponentInitializer.loadInstance() + .initComponent(nodeComponent, type, nodeComponent.getName(), nodeId)); + nodeMap.put(nodeId, node); + addFallbackNode(node); + } - /** - * 添加 node - * - * @param nodeId 节点id - * @param name 节点名称 - * @param type 节点类型 - * @param cmpClazz 节点组件类 - */ - public static void addNode(String nodeId, String name, NodeTypeEnum type, Class cmpClazz) { - addNode(nodeId, name, type, cmpClazz, null, null); - } + /** + * 添加 node + * @param nodeId 节点id + * @param name 节点名称 + * @param type 节点类型 + * @param cmpClazz 节点组件类 + */ + public static void addNode(String nodeId, String name, NodeTypeEnum type, Class cmpClazz) { + addNode(nodeId, name, type, cmpClazz, null, null); + } - /** - * 添加 node - * - * @param nodeId 节点id - * @param name 节点名称 - * @param nodeType 节点类型 - * @param cmpClazzStr 节点组件类路径 - */ - public static void addNode(String nodeId, String name, NodeTypeEnum nodeType, String cmpClazzStr) { - Class cmpClazz; - try { - cmpClazz = Class.forName(cmpClazzStr); - } catch (Exception e) { - throw new ComponentCannotRegisterException(e.getMessage()); - } - addNode(nodeId, name, nodeType, cmpClazz, null, null); - } + /** + * 添加 node + * @param nodeId 节点id + * @param name 节点名称 + * @param nodeType 节点类型 + * @param cmpClazzStr 节点组件类路径 + */ + public static void addNode(String nodeId, String name, NodeTypeEnum nodeType, String cmpClazzStr) { + Class cmpClazz; + try { + cmpClazz = Class.forName(cmpClazzStr); + } + catch (Exception e) { + throw new ComponentCannotRegisterException(e.getMessage()); + } + addNode(nodeId, name, nodeType, cmpClazz, null, null); + } - /** - * 添加脚本 node - * - * @param nodeId 节点id - * @param name 节点名称 - * @param nodeType 节点类型 - * @param script 脚本 - */ - public static void addScriptNode(String nodeId, String name, NodeTypeEnum nodeType, String script, - String language) { - addNode(nodeId, name, nodeType, ScriptComponent.ScriptComponentClassMap.get(nodeType), script, language); - } + /** + * 添加脚本 node + * @param nodeId 节点id + * @param name 节点名称 + * @param nodeType 节点类型 + * @param script 脚本 + */ + public static void addScriptNode(String nodeId, String name, NodeTypeEnum nodeType, String script, + String language) { + addNode(nodeId, name, nodeType, ScriptComponent.ScriptComponentClassMap.get(nodeType), script, language); + } - private static void addNode(String nodeId, String name, NodeTypeEnum type, Class cmpClazz, String script, - String language) { - try { - // 判断此类是否是声明式的组件,如果是声明式的组件,就用动态代理生成实例 - // 如果不是声明式的,就用传统的方式进行判断 - List cmpInstances = new ArrayList<>(); - if (LiteFlowProxyUtil.isDeclareCmp(cmpClazz)) { - // 这里的逻辑要仔细看下 - // 如果是spring体系,把原始的类往spring上下文中进行注册,那么会走到ComponentScanner中 - // 由于ComponentScanner中已经对原始类进行了动态代理,出来的对象已经变成了动态代理类,所以这时候的bean已经是NodeComponent的子类了 - // 所以spring体系下,无需再对这个bean做二次代理 - // 但是在非spring体系下,这个bean依旧是原来那个bean,所以需要对这个bean做一次代理 - // 这里用ContextAware的spi机制来判断是否spring体系 - ContextAware contextAware = ContextAwareHolder.loadContextAware(); - Object bean = ContextAwareHolder.loadContextAware().registerBean(nodeId, cmpClazz); - if (LocalContextAware.class.isAssignableFrom(contextAware.getClass())) { - cmpInstances = LiteFlowProxyUtil.proxy2NodeComponent(bean, nodeId); - } else { - cmpInstances = ListUtil.toList((NodeComponent) bean); - } - } else { - // 以node方式配置,本质上是为了适配无spring的环境,如果有spring环境,其实不用这么配置 - // 这里的逻辑是判断是否能从spring上下文中取到,如果没有spring,则就是new instance了 - // 如果是script类型的节点,因为class只有一个,所以也不能注册进spring上下文,注册的时候需要new Instance - if (!type.isScript()) { - cmpInstances = ListUtil.toList( - (NodeComponent) ContextAwareHolder.loadContextAware().registerOrGet(nodeId, cmpClazz)); - } - // 去除null元素 - cmpInstances.remove(null); - // 如果为空 - if (cmpInstances.isEmpty()) { - NodeComponent cmpInstance = (NodeComponent) cmpClazz.newInstance(); - cmpInstances.add(cmpInstance); - } - } - // 进行初始化component - cmpInstances = cmpInstances.stream().map(cmpInstance -> ComponentInitializer.loadInstance() - .initComponent(cmpInstance, type, name, - cmpInstance.getNodeId() == null ? nodeId : cmpInstance.getNodeId())) - .collect(Collectors.toList()); + private static void addNode(String nodeId, String name, NodeTypeEnum type, Class cmpClazz, String script, + String language) { + try { + // 判断此类是否是声明式的组件,如果是声明式的组件,就用动态代理生成实例 + // 如果不是声明式的,就用传统的方式进行判断 + List cmpInstances = new ArrayList<>(); + if (LiteFlowProxyUtil.isDeclareCmp(cmpClazz)) { + // 这里的逻辑要仔细看下 + // 如果是spring体系,把原始的类往spring上下文中进行注册,那么会走到ComponentScanner中 + // 由于ComponentScanner中已经对原始类进行了动态代理,出来的对象已经变成了动态代理类,所以这时候的bean已经是NodeComponent的子类了 + // 所以spring体系下,无需再对这个bean做二次代理 + // 但是在非spring体系下,这个bean依旧是原来那个bean,所以需要对这个bean做一次代理 + // 这里用ContextAware的spi机制来判断是否spring体系 + ContextAware contextAware = ContextAwareHolder.loadContextAware(); + Object bean = ContextAwareHolder.loadContextAware().registerBean(nodeId, cmpClazz); + if (LocalContextAware.class.isAssignableFrom(contextAware.getClass())) { + cmpInstances = LiteFlowProxyUtil.proxy2NodeComponent(bean, nodeId); + } + else { + cmpInstances = ListUtil.toList((NodeComponent) bean); + } + } + else { + // 以node方式配置,本质上是为了适配无spring的环境,如果有spring环境,其实不用这么配置 + // 这里的逻辑是判断是否能从spring上下文中取到,如果没有spring,则就是new instance了 + // 如果是script类型的节点,因为class只有一个,所以也不能注册进spring上下文,注册的时候需要new Instance + if (!type.isScript()) { + cmpInstances = ListUtil + .toList((NodeComponent) ContextAwareHolder.loadContextAware().registerOrGet(nodeId, cmpClazz)); + } + // 去除null元素 + cmpInstances.remove(null); + // 如果为空 + if (cmpInstances.isEmpty()) { + NodeComponent cmpInstance = (NodeComponent) cmpClazz.newInstance(); + cmpInstances.add(cmpInstance); + } + } + // 进行初始化component + cmpInstances = cmpInstances.stream() + .map(cmpInstance -> ComponentInitializer.loadInstance() + .initComponent(cmpInstance, type, name, + cmpInstance.getNodeId() == null ? nodeId : cmpInstance.getNodeId())) + .collect(Collectors.toList()); - // 初始化Node,把component放到Node里去 - List nodes = cmpInstances.stream().map(Node::new).collect(Collectors.toList()); + // 初始化Node,把component放到Node里去 + List nodes = cmpInstances.stream().map(Node::new).collect(Collectors.toList()); - for (int i = 0; i < nodes.size(); i++) { - Node node = nodes.get(i); - NodeComponent cmpInstance = cmpInstances.get(i); - // 如果是脚本节点,则还要加载script脚本 - if (type.isScript()) { - if (StrUtil.isNotBlank(script)) { - node.setScript(script); - node.setLanguage(language); - ((ScriptComponent) cmpInstance).loadScript(script, language); - } else { - String errorMsg = StrUtil.format("script for node[{}] is empty", nodeId); - throw new ScriptLoadException(errorMsg); - } - } + for (int i = 0; i < nodes.size(); i++) { + Node node = nodes.get(i); + NodeComponent cmpInstance = cmpInstances.get(i); + // 如果是脚本节点,则还要加载script脚本 + if (type.isScript()) { + if (StrUtil.isNotBlank(script)) { + node.setScript(script); + node.setLanguage(language); + ((ScriptComponent) cmpInstance).loadScript(script, language); + } + else { + String errorMsg = StrUtil.format("script for node[{}] is empty", nodeId); + throw new ScriptLoadException(errorMsg); + } + } - String activeNodeId = StrUtil.isEmpty(cmpInstance.getNodeId()) ? nodeId : cmpInstance.getNodeId(); - nodeMap.put(activeNodeId, node); - addFallbackNode(node); - } + String activeNodeId = StrUtil.isEmpty(cmpInstance.getNodeId()) ? nodeId : cmpInstance.getNodeId(); + nodeMap.put(activeNodeId, node); + addFallbackNode(node); + } - } catch (Exception e) { - String error = StrUtil.format("component[{}] register error", - StrUtil.isEmpty(name) ? nodeId : StrUtil.format("{}({})", nodeId, name)); - LOG.error(e.getMessage()); - throw new ComponentCannotRegisterException(StrUtil.format("{} {}", error, e.getMessage())); - } - } + } + catch (Exception e) { + String error = StrUtil.format("component[{}] register error", + StrUtil.isEmpty(name) ? nodeId : StrUtil.format("{}({})", nodeId, name)); + LOG.error(e.getMessage()); + throw new ComponentCannotRegisterException(StrUtil.format("{} {}", error, e.getMessage())); + } + } - public static Node getNode(String nodeId) { - return nodeMap.get(nodeId); - } + public static Node getNode(String nodeId) { + return nodeMap.get(nodeId); + } - public static Map getNodeMap() { - return nodeMap; - } + public static Map getNodeMap() { + return nodeMap; + } - public static Map getChainMap() { - return chainMap; - } + public static Map getChainMap() { + return chainMap; + } - public static Node getFallBackNode(NodeTypeEnum nodeType) { - return fallbackNodeMap.get(nodeType); - } + public static Node getFallBackNode(NodeTypeEnum nodeType) { + return fallbackNodeMap.get(nodeType); + } - public static void cleanCache() { - chainMap.clear(); - nodeMap.clear(); - fallbackNodeMap.clear(); - cleanScriptCache(); - } + public static void cleanCache() { + chainMap.clear(); + nodeMap.clear(); + fallbackNodeMap.clear(); + cleanScriptCache(); + } - public static void cleanScriptCache() { - // 如果引入了脚本组件SPI,则还需要清理脚本的缓存 - try { - ScriptExecutorFactory.loadInstance().cleanScriptCache(); - } catch (ScriptSpiException ignored) { - } - } + public static void cleanScriptCache() { + // 如果引入了脚本组件SPI,则还需要清理脚本的缓存 + try { + ScriptExecutorFactory.loadInstance().cleanScriptCache(); + } + catch (ScriptSpiException ignored) { + } + } - public static void refreshFlowMetaData(FlowParserTypeEnum type, String content) throws Exception { - if (type.equals(FlowParserTypeEnum.TYPE_EL_XML)) { - new LocalXmlFlowELParser().parse(content); - } else if (type.equals(FlowParserTypeEnum.TYPE_EL_JSON)) { - new LocalJsonFlowELParser().parse(content); - } else if (type.equals(FlowParserTypeEnum.TYPE_EL_YML)) { - new LocalYmlFlowELParser().parse(content); - } - } + public static void refreshFlowMetaData(FlowParserTypeEnum type, String content) throws Exception { + if (type.equals(FlowParserTypeEnum.TYPE_EL_XML)) { + new LocalXmlFlowELParser().parse(content); + } + else if (type.equals(FlowParserTypeEnum.TYPE_EL_JSON)) { + new LocalJsonFlowELParser().parse(content); + } + else if (type.equals(FlowParserTypeEnum.TYPE_EL_YML)) { + new LocalYmlFlowELParser().parse(content); + } + } - public static boolean removeChain(String chainId) { - if (containChain(chainId)) { - chainMap.remove(chainId); - return true; - } else { - String errMsg = StrUtil.format("cannot find the chain[{}]", chainId); - LOG.error(errMsg); - return false; - } - } + public static boolean removeChain(String chainId) { + if (containChain(chainId)) { + chainMap.remove(chainId); + return true; + } + else { + String errMsg = StrUtil.format("cannot find the chain[{}]", chainId); + LOG.error(errMsg); + return false; + } + } - public static void removeChain(String... chainIds) { - Arrays.stream(chainIds).forEach(FlowBus::removeChain); - } + public static void removeChain(String... chainIds) { + Arrays.stream(chainIds).forEach(FlowBus::removeChain); + } - private static void addFallbackNode(Node node) { - NodeComponent nodeComponent = node.getInstance(); - FallbackCmp fallbackCmp = AnnoUtil.getAnnotation(nodeComponent.getClass(), FallbackCmp.class); - if (fallbackCmp == null) { - return; - } + // 判断是否是降级组件,如果是则添加到 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(); - if (nodeType == null) { - nodeType = fallbackCmp.type(); - } - fallbackNodeMap.put(nodeType, node); - } + NodeTypeEnum nodeType = node.getType(); + if (nodeType == null) { + nodeType = fallbackCmp.type(); + } + fallbackNodeMap.put(nodeType, node); + } } diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/flow/element/Condition.java b/liteflow-core/src/main/java/com/yomahub/liteflow/flow/element/Condition.java index 8d481c274..3bfbe3203 100644 --- a/liteflow-core/src/main/java/com/yomahub/liteflow/flow/element/Condition.java +++ b/liteflow-core/src/main/java/com/yomahub/liteflow/flow/element/Condition.java @@ -1,20 +1,18 @@ /** *

Title: liteflow

*

Description: 轻量级的组件式流程框架

- * * @author Bryan.Zhang * @email weenyc31@163.com * @Date 2020/4/1 */ - 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.enums.ConditionTypeEnum; import com.yomahub.liteflow.flow.element.condition.ConditionKey; import com.yomahub.liteflow.slot.DataBus; import com.yomahub.liteflow.slot.Slot; @@ -30,136 +28,141 @@ import java.util.Map; * @author Bryan.Zhang * @author DaleLee */ -public abstract class Condition implements Executable { +public abstract class Condition implements Executable{ - private String id; + private String id; - private String tag; + private String tag; - /** - * 可执行元素的集合 - */ - private final Map> executableGroup = new HashMap<>(); + /** + * 可执行元素的集合 + */ + private final Map> executableGroup = new HashMap<>(); - /** - * 当前所在的ChainName 如果对于子流程来说,那这个就是子流程所在的Chain - */ - private String currChainId; + /** + * 当前所在的ChainName 如果对于子流程来说,那这个就是子流程所在的Chain + */ + private String currChainId; - @Override - public void execute(Integer slotIndex) throws Exception { - // 当前 Condition 入栈 - Slot slot = DataBus.getSlot(slotIndex); - try { - slot.pushCondition(this); - executeCondition(slotIndex); - } catch (ChainEndException e) { - // 这里单独catch ChainEndException是因为ChainEndException是用户自己setIsEnd抛出的异常 - // 是属于正常逻辑,所以会在FlowExecutor中判断。这里不作为异常处理 - throw e; - } catch (Exception e) { - String chainId = this.getCurrChainId(); - // 这里事先取到exception set到slot里,为了方便finally取到exception - if (slot.isSubChain(chainId)) { - slot.setSubException(chainId, e); - } else { - slot.setException(e); - } - throw e; - } finally { - // 当前 Condition 出栈 - slot.popCondition(); - } - } + @Override + public void execute(Integer slotIndex) throws Exception { + Slot slot = DataBus.getSlot(slotIndex); + try { + // 当前 Condition 入栈 + slot.pushCondition(this); + executeCondition(slotIndex); + } + catch (ChainEndException e) { + // 这里单独catch ChainEndException是因为ChainEndException是用户自己setIsEnd抛出的异常 + // 是属于正常逻辑,所以会在FlowExecutor中判断。这里不作为异常处理 + throw e; + } + catch (Exception e) { + String chainId = this.getCurrChainId(); + // 这里事先取到exception set到slot里,为了方便finally取到exception + if (slot.isSubChain(chainId)) { + slot.setSubException(chainId, e); + } + else { + slot.setException(e); + } + throw e; + } finally { + // 当前 Condition 出栈 + slot.popCondition(); + } + } - public abstract void executeCondition(Integer slotIndex) throws Exception; + public abstract void executeCondition(Integer slotIndex) throws Exception; - @Override - public ExecuteTypeEnum getExecuteType() { - return ExecuteTypeEnum.CONDITION; - } + @Override + public ExecuteTypeEnum getExecuteType() { + return ExecuteTypeEnum.CONDITION; + } - public List getExecutableList() { - return getExecutableList(ConditionKey.DEFAULT_KEY); - } + public List getExecutableList() { + return getExecutableList(ConditionKey.DEFAULT_KEY); + } - public List getExecutableList(String groupKey) { - List executableList = this.executableGroup.get(groupKey); - if (CollUtil.isEmpty(executableList)) { - executableList = new ArrayList<>(); - } - return executableList; - } + public List getExecutableList(String groupKey) { + List executableList = this.executableGroup.get(groupKey); + if (CollUtil.isEmpty(executableList)) { + executableList = new ArrayList<>(); + } + return executableList; + } - public Executable getExecutableOne(String groupKey) { - List list = getExecutableList(groupKey); - if (CollUtil.isEmpty(list)) { - return null; - } else { - return list.get(0); - } - } + public Executable getExecutableOne(String groupKey) { + List list = getExecutableList(groupKey); + if (CollUtil.isEmpty(list)) { + return null; + } + else { + return list.get(0); + } + } - public void setExecutableList(List executableList) { - this.executableGroup.put(ConditionKey.DEFAULT_KEY, executableList); - } + public void setExecutableList(List executableList) { + this.executableGroup.put(ConditionKey.DEFAULT_KEY, executableList); + } - public void addExecutable(Executable executable) { - addExecutable(ConditionKey.DEFAULT_KEY, executable); - } + public void addExecutable(Executable executable) { + addExecutable(ConditionKey.DEFAULT_KEY, executable); + } - public void addExecutable(String groupKey, Executable executable) { - if (ObjectUtil.isNull(executable)) { - return; - } - List executableList = this.executableGroup.get(groupKey); - if (CollUtil.isEmpty(executableList)) { - this.executableGroup.put(groupKey, ListUtil.toList(executable)); - } else { - this.executableGroup.get(groupKey).add(executable); - } - } + public void addExecutable(String groupKey, Executable executable) { + if (ObjectUtil.isNull(executable)) { + return; + } + List executableList = this.executableGroup.get(groupKey); + if (CollUtil.isEmpty(executableList)) { + this.executableGroup.put(groupKey, ListUtil.toList(executable)); + } + else { + this.executableGroup.get(groupKey).add(executable); + } + } - public abstract ConditionTypeEnum getConditionType(); + public abstract ConditionTypeEnum getConditionType(); - @Override - public String getId() { - return id; - } + @Override + public String getId() { + return id; + } - @Override - public void setId(String id) { - this.id = id; - } + @Override + public void setId(String id) { + this.id = id; + } - @Override - public String getTag() { - return tag; - } + @Override + public String getTag() { + return tag; + } - @Override - public void setTag(String tag) { - this.tag = tag; - } + @Override + public void setTag(String tag) { + this.tag = tag; + } - /** - * 请使用 {@link #setCurrChainId(String)} - */ - @Deprecated - public String getCurrChainName() { - return currChainId; - } + /** + * 请使用 {@link #setCurrChainId(String)} + */ + @Deprecated + public String getCurrChainName() { + return currChainId; + } - public String getCurrChainId() { - return currChainId; - } + public String getCurrChainId() { + return currChainId; + } - @Override - public void setCurrChainId(String currChainId) { - this.currChainId = currChainId; - } + @Override + public void setCurrChainId(String currChainId) { + this.currChainId = currChainId; + } - public Map> getExecutableGroup() { - return executableGroup; - } + public Map> getExecutableGroup() { + return executableGroup; + } } diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/slot/Slot.java b/liteflow-core/src/main/java/com/yomahub/liteflow/slot/Slot.java index ebe3289f8..8bd133c14 100644 --- a/liteflow-core/src/main/java/com/yomahub/liteflow/slot/Slot.java +++ b/liteflow-core/src/main/java/com/yomahub/liteflow/slot/Slot.java @@ -19,8 +19,10 @@ 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; @@ -90,7 +92,7 @@ public class Slot { private List contextBeanList; - private final Deque conditionStack = new ConcurrentLinkedDeque<>(); + private static final ThreadLocal> conditionStack = ThreadLocal.withInitial(LinkedList::new); public Slot() { } @@ -292,15 +294,15 @@ public class Slot { } public Condition getCurrentCondition() { - return this.conditionStack.peek(); + return conditionStack.get().peek(); } public void pushCondition(Condition condition) { - this.conditionStack.push(condition); + conditionStack.get().push(condition); } public void popCondition() { - this.conditionStack.pop(); + conditionStack.get().pop(); } /** diff --git a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/fallback/FallbackSpringbootTest.java b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/fallback/FallbackSpringbootTest.java index 2100becb2..39a801fd7 100644 --- a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/fallback/FallbackSpringbootTest.java +++ b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/fallback/FallbackSpringbootTest.java @@ -10,6 +10,8 @@ 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 降级组件测试 @@ -186,4 +188,36 @@ public class FallbackSpringbootTest { 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 future1 = flowExecutor.execute2Future("concurrent1", "arg", new Object()); + Future 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)); + } } diff --git a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/fallback/cmp/ACmp.java b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/fallback/cmp/ACmp.java index 3dbb2c4d6..8a6739027 100644 --- a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/fallback/cmp/ACmp.java +++ b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/fallback/cmp/ACmp.java @@ -1,11 +1,3 @@ -/** - *

Title: liteflow

- *

Description: 轻量级的组件式流程框架

- * - * @author Bryan.Zhang - * @email weenyc31@163.com - * @Date 2020/4/1 - */ package com.yomahub.liteflow.test.fallback.cmp; import com.yomahub.liteflow.annotation.LiteflowComponent; diff --git a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/fallback/cmp/BCmp.java b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/fallback/cmp/BCmp.java index 86eeccee1..6216dd712 100644 --- a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/fallback/cmp/BCmp.java +++ b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/fallback/cmp/BCmp.java @@ -1,11 +1,3 @@ -/** - *

Title: liteflow

- *

Description: 轻量级的组件式流程框架

- * - * @author Bryan.Zhang - * @email weenyc31@163.com - * @Date 2020/4/1 - */ package com.yomahub.liteflow.test.fallback.cmp; import com.yomahub.liteflow.annotation.LiteflowComponent; diff --git a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/fallback/cmp/CCmp.java b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/fallback/cmp/CCmp.java index 4a9259847..a18c23d48 100644 --- a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/fallback/cmp/CCmp.java +++ b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/fallback/cmp/CCmp.java @@ -1,11 +1,3 @@ -/** - *

Title: liteflow

- *

Description: 轻量级的组件式流程框架

- * - * @author Bryan.Zhang - * @email weenyc31@163.com - * @Date 2020/4/1 - */ package com.yomahub.liteflow.test.fallback.cmp; import com.yomahub.liteflow.annotation.FallbackCmp; diff --git a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/fallback/flow.el.xml b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/fallback/flow.el.xml index 66e6da96c..9647a51d6 100644 --- a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/fallback/flow.el.xml +++ b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/fallback/flow.el.xml @@ -8,6 +8,7 @@ THEN(PRE(node("x1")), node("x2"), FINALLY(node("x3"))); + WHEN(b, node("x")); @@ -33,12 +34,12 @@ FOR(3).DO(node("x")); - + WHILE(node("x")).DO(a) - + WHILE(wn1).DO(node("x")) @@ -117,4 +118,19 @@ THEN(b, node("x2")) ); + + + + WHEN( + THEN(node("x1")), + IF(node("x2"), b) + ).maxWaitSeconds(10000); + + + + WHEN( + node("x1"), + IF(node("x2"), b) + ).maxWaitSeconds(10000); + \ No newline at end of file From c422761aeff2f33b054987f8525e090f49da4691 Mon Sep 17 00:00:00 2001 From: Dale Lee <1658850308@qq.com> Date: Fri, 6 Oct 2023 21:01:52 +0800 Subject: [PATCH 8/8] =?UTF-8?q?feature=20#I7YYLE=20=E5=AE=8C=E5=96=84?= =?UTF-8?q?=E6=B5=8B=E8=AF=95=E7=94=A8=E4=BE=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../liteflow/annotation/FallbackCmp.java | 8 +- .../builder/el/operator/NodeOperator.java | 3 +- .../FallbackCmpNotFoundException.java | 1 + .../com/yomahub/liteflow/flow/FlowBus.java | 3 - .../flow/element/FallbackNodeProxy.java | 2 +- .../META-INF/liteflow-default.properties | 2 +- .../FallbackELDeclSpringbootTest.java | 225 ++++++++++++++++++ .../liteflow/test/fallback/cmp/ACmp.java | 16 ++ .../liteflow/test/fallback/cmp/BCmp.java | 16 ++ .../liteflow/test/fallback/cmp/BreakCmp.java | 20 ++ .../liteflow/test/fallback/cmp/CCmp.java | 18 ++ .../liteflow/test/fallback/cmp/DCmp.java | 15 ++ .../liteflow/test/fallback/cmp/ForCmp.java | 20 ++ .../liteflow/test/fallback/cmp/IfCmp1.java | 18 ++ .../liteflow/test/fallback/cmp/IfCmp2.java | 20 ++ .../test/fallback/cmp/IteratorCmp1.java | 21 ++ .../test/fallback/cmp/IteratorCmp2.java | 23 ++ .../test/fallback/cmp/SwitchCmp1.java | 18 ++ .../test/fallback/cmp/SwitchCmp2.java | 20 ++ .../liteflow/test/fallback/cmp/WhileCmp1.java | 31 +++ .../liteflow/test/fallback/cmp/WhileCmp2.java | 20 ++ .../resources/fallback/application.properties | 2 + .../src/test/resources/fallback/flow.el.xml | 136 +++++++++++ .../liteflow/test/fallback/FallbackTest.java | 225 ++++++++++++++++++ .../liteflow/test/fallback/cmp/ACmp.java | 12 + .../liteflow/test/fallback/cmp/BCmp.java | 12 + .../liteflow/test/fallback/cmp/BreakCmp.java | 13 + .../liteflow/test/fallback/cmp/CCmp.java | 14 ++ .../liteflow/test/fallback/cmp/DCmp.java | 11 + .../liteflow/test/fallback/cmp/ForCmp.java | 13 + .../liteflow/test/fallback/cmp/IfCmp1.java | 11 + .../liteflow/test/fallback/cmp/IfCmp2.java | 13 + .../test/fallback/cmp/IteratorCmp1.java | 14 ++ .../test/fallback/cmp/IteratorCmp2.java | 16 ++ .../test/fallback/cmp/SwitchCmp1.java | 11 + .../test/fallback/cmp/SwitchCmp2.java | 13 + .../liteflow/test/fallback/cmp/WhileCmp1.java | 24 ++ .../liteflow/test/fallback/cmp/WhileCmp2.java | 13 + .../src/test/resources/fallback/flow.el.xml | 153 ++++++++++++ .../test/fallback/FallbackELSolonTest.java | 222 +++++++++++++++++ .../liteflow/test/fallback/cmp/ACmp.java | 14 ++ .../liteflow/test/fallback/cmp/BCmp.java | 14 ++ .../liteflow/test/fallback/cmp/BreakCmp.java | 15 ++ .../liteflow/test/fallback/cmp/CCmp.java | 16 ++ .../liteflow/test/fallback/cmp/DCmp.java | 13 + .../liteflow/test/fallback/cmp/ForCmp.java | 15 ++ .../liteflow/test/fallback/cmp/IfCmp1.java | 13 + .../liteflow/test/fallback/cmp/IfCmp2.java | 15 ++ .../test/fallback/cmp/IteratorCmp1.java | 16 ++ .../test/fallback/cmp/IteratorCmp2.java | 18 ++ .../test/fallback/cmp/SwitchCmp1.java | 13 + .../test/fallback/cmp/SwitchCmp2.java | 15 ++ .../liteflow/test/fallback/cmp/WhileCmp1.java | 26 ++ .../liteflow/test/fallback/cmp/WhileCmp2.java | 15 ++ .../resources/fallback/application.properties | 2 + .../src/test/resources/fallback/flow.el.xml | 136 +++++++++++ ...est.java => FallbackELSpringbootTest.java} | 6 +- .../test/fallback/FallbackELSpringTest.java | 221 +++++++++++++++++ .../liteflow/test/fallback/cmp/ACmp.java | 14 ++ .../liteflow/test/fallback/cmp/BCmp.java | 14 ++ .../liteflow/test/fallback/cmp/BreakCmp.java | 15 ++ .../liteflow/test/fallback/cmp/CCmp.java | 16 ++ .../liteflow/test/fallback/cmp/DCmp.java | 13 + .../liteflow/test/fallback/cmp/ForCmp.java | 15 ++ .../liteflow/test/fallback/cmp/IfCmp1.java | 13 + .../liteflow/test/fallback/cmp/IfCmp2.java | 15 ++ .../test/fallback/cmp/IteratorCmp1.java | 16 ++ .../test/fallback/cmp/IteratorCmp2.java | 18 ++ .../test/fallback/cmp/SwitchCmp1.java | 13 + .../test/fallback/cmp/SwitchCmp2.java | 15 ++ .../liteflow/test/fallback/cmp/WhileCmp1.java | 26 ++ .../liteflow/test/fallback/cmp/WhileCmp2.java | 15 ++ .../test/resources/fallback/application.xml | 24 ++ .../src/test/resources/fallback/flow.el.xml | 136 +++++++++++ 74 files changed, 2395 insertions(+), 14 deletions(-) create mode 100644 liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/java/com/yomahub/liteflow/test/fallback/FallbackELDeclSpringbootTest.java create mode 100644 liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/java/com/yomahub/liteflow/test/fallback/cmp/ACmp.java create mode 100644 liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/java/com/yomahub/liteflow/test/fallback/cmp/BCmp.java create mode 100644 liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/java/com/yomahub/liteflow/test/fallback/cmp/BreakCmp.java create mode 100644 liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/java/com/yomahub/liteflow/test/fallback/cmp/CCmp.java create mode 100644 liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/java/com/yomahub/liteflow/test/fallback/cmp/DCmp.java create mode 100644 liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/java/com/yomahub/liteflow/test/fallback/cmp/ForCmp.java create mode 100644 liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/java/com/yomahub/liteflow/test/fallback/cmp/IfCmp1.java create mode 100644 liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/java/com/yomahub/liteflow/test/fallback/cmp/IfCmp2.java create mode 100644 liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/java/com/yomahub/liteflow/test/fallback/cmp/IteratorCmp1.java create mode 100644 liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/java/com/yomahub/liteflow/test/fallback/cmp/IteratorCmp2.java create mode 100644 liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/java/com/yomahub/liteflow/test/fallback/cmp/SwitchCmp1.java create mode 100644 liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/java/com/yomahub/liteflow/test/fallback/cmp/SwitchCmp2.java create mode 100644 liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/java/com/yomahub/liteflow/test/fallback/cmp/WhileCmp1.java create mode 100644 liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/java/com/yomahub/liteflow/test/fallback/cmp/WhileCmp2.java create mode 100644 liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/resources/fallback/application.properties create mode 100644 liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/resources/fallback/flow.el.xml create mode 100644 liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/java/com/yomahub/liteflow/test/fallback/FallbackTest.java create mode 100644 liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/java/com/yomahub/liteflow/test/fallback/cmp/ACmp.java create mode 100644 liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/java/com/yomahub/liteflow/test/fallback/cmp/BCmp.java create mode 100644 liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/java/com/yomahub/liteflow/test/fallback/cmp/BreakCmp.java create mode 100644 liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/java/com/yomahub/liteflow/test/fallback/cmp/CCmp.java create mode 100644 liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/java/com/yomahub/liteflow/test/fallback/cmp/DCmp.java create mode 100644 liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/java/com/yomahub/liteflow/test/fallback/cmp/ForCmp.java create mode 100644 liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/java/com/yomahub/liteflow/test/fallback/cmp/IfCmp1.java create mode 100644 liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/java/com/yomahub/liteflow/test/fallback/cmp/IfCmp2.java create mode 100644 liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/java/com/yomahub/liteflow/test/fallback/cmp/IteratorCmp1.java create mode 100644 liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/java/com/yomahub/liteflow/test/fallback/cmp/IteratorCmp2.java create mode 100644 liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/java/com/yomahub/liteflow/test/fallback/cmp/SwitchCmp1.java create mode 100644 liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/java/com/yomahub/liteflow/test/fallback/cmp/SwitchCmp2.java create mode 100644 liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/java/com/yomahub/liteflow/test/fallback/cmp/WhileCmp1.java create mode 100644 liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/java/com/yomahub/liteflow/test/fallback/cmp/WhileCmp2.java create mode 100644 liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/resources/fallback/flow.el.xml create mode 100644 liteflow-testcase-el/liteflow-testcase-el-solon/src/test/java/com/yomahub/liteflow/test/fallback/FallbackELSolonTest.java create mode 100644 liteflow-testcase-el/liteflow-testcase-el-solon/src/test/java/com/yomahub/liteflow/test/fallback/cmp/ACmp.java create mode 100644 liteflow-testcase-el/liteflow-testcase-el-solon/src/test/java/com/yomahub/liteflow/test/fallback/cmp/BCmp.java create mode 100644 liteflow-testcase-el/liteflow-testcase-el-solon/src/test/java/com/yomahub/liteflow/test/fallback/cmp/BreakCmp.java create mode 100644 liteflow-testcase-el/liteflow-testcase-el-solon/src/test/java/com/yomahub/liteflow/test/fallback/cmp/CCmp.java create mode 100644 liteflow-testcase-el/liteflow-testcase-el-solon/src/test/java/com/yomahub/liteflow/test/fallback/cmp/DCmp.java create mode 100644 liteflow-testcase-el/liteflow-testcase-el-solon/src/test/java/com/yomahub/liteflow/test/fallback/cmp/ForCmp.java create mode 100644 liteflow-testcase-el/liteflow-testcase-el-solon/src/test/java/com/yomahub/liteflow/test/fallback/cmp/IfCmp1.java create mode 100644 liteflow-testcase-el/liteflow-testcase-el-solon/src/test/java/com/yomahub/liteflow/test/fallback/cmp/IfCmp2.java create mode 100644 liteflow-testcase-el/liteflow-testcase-el-solon/src/test/java/com/yomahub/liteflow/test/fallback/cmp/IteratorCmp1.java create mode 100644 liteflow-testcase-el/liteflow-testcase-el-solon/src/test/java/com/yomahub/liteflow/test/fallback/cmp/IteratorCmp2.java create mode 100644 liteflow-testcase-el/liteflow-testcase-el-solon/src/test/java/com/yomahub/liteflow/test/fallback/cmp/SwitchCmp1.java create mode 100644 liteflow-testcase-el/liteflow-testcase-el-solon/src/test/java/com/yomahub/liteflow/test/fallback/cmp/SwitchCmp2.java create mode 100644 liteflow-testcase-el/liteflow-testcase-el-solon/src/test/java/com/yomahub/liteflow/test/fallback/cmp/WhileCmp1.java create mode 100644 liteflow-testcase-el/liteflow-testcase-el-solon/src/test/java/com/yomahub/liteflow/test/fallback/cmp/WhileCmp2.java create mode 100644 liteflow-testcase-el/liteflow-testcase-el-solon/src/test/resources/fallback/application.properties create mode 100644 liteflow-testcase-el/liteflow-testcase-el-solon/src/test/resources/fallback/flow.el.xml rename liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/fallback/{FallbackSpringbootTest.java => FallbackELSpringbootTest.java} (98%) create mode 100644 liteflow-testcase-el/liteflow-testcase-el-springnative/src/test/java/com/yomahub/liteflow/test/fallback/FallbackELSpringTest.java create mode 100644 liteflow-testcase-el/liteflow-testcase-el-springnative/src/test/java/com/yomahub/liteflow/test/fallback/cmp/ACmp.java create mode 100644 liteflow-testcase-el/liteflow-testcase-el-springnative/src/test/java/com/yomahub/liteflow/test/fallback/cmp/BCmp.java create mode 100644 liteflow-testcase-el/liteflow-testcase-el-springnative/src/test/java/com/yomahub/liteflow/test/fallback/cmp/BreakCmp.java create mode 100644 liteflow-testcase-el/liteflow-testcase-el-springnative/src/test/java/com/yomahub/liteflow/test/fallback/cmp/CCmp.java create mode 100644 liteflow-testcase-el/liteflow-testcase-el-springnative/src/test/java/com/yomahub/liteflow/test/fallback/cmp/DCmp.java create mode 100644 liteflow-testcase-el/liteflow-testcase-el-springnative/src/test/java/com/yomahub/liteflow/test/fallback/cmp/ForCmp.java create mode 100644 liteflow-testcase-el/liteflow-testcase-el-springnative/src/test/java/com/yomahub/liteflow/test/fallback/cmp/IfCmp1.java create mode 100644 liteflow-testcase-el/liteflow-testcase-el-springnative/src/test/java/com/yomahub/liteflow/test/fallback/cmp/IfCmp2.java create mode 100644 liteflow-testcase-el/liteflow-testcase-el-springnative/src/test/java/com/yomahub/liteflow/test/fallback/cmp/IteratorCmp1.java create mode 100644 liteflow-testcase-el/liteflow-testcase-el-springnative/src/test/java/com/yomahub/liteflow/test/fallback/cmp/IteratorCmp2.java create mode 100644 liteflow-testcase-el/liteflow-testcase-el-springnative/src/test/java/com/yomahub/liteflow/test/fallback/cmp/SwitchCmp1.java create mode 100644 liteflow-testcase-el/liteflow-testcase-el-springnative/src/test/java/com/yomahub/liteflow/test/fallback/cmp/SwitchCmp2.java create mode 100644 liteflow-testcase-el/liteflow-testcase-el-springnative/src/test/java/com/yomahub/liteflow/test/fallback/cmp/WhileCmp1.java create mode 100644 liteflow-testcase-el/liteflow-testcase-el-springnative/src/test/java/com/yomahub/liteflow/test/fallback/cmp/WhileCmp2.java create mode 100644 liteflow-testcase-el/liteflow-testcase-el-springnative/src/test/resources/fallback/application.xml create mode 100644 liteflow-testcase-el/liteflow-testcase-el-springnative/src/test/resources/fallback/flow.el.xml diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/annotation/FallbackCmp.java b/liteflow-core/src/main/java/com/yomahub/liteflow/annotation/FallbackCmp.java index caf9deed6..a1e9ae2bd 100644 --- a/liteflow-core/src/main/java/com/yomahub/liteflow/annotation/FallbackCmp.java +++ b/liteflow-core/src/main/java/com/yomahub/liteflow/annotation/FallbackCmp.java @@ -11,17 +11,13 @@ import java.lang.annotation.Target; /** * 降级组件 + * * @author DaleLee + * @since 2.11.1 */ @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited public @interface FallbackCmp { - - /** - * 节点类型 - * @return NodeTypeEnum - */ - NodeTypeEnum type() default NodeTypeEnum.COMMON; } diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/NodeOperator.java b/liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/NodeOperator.java index 7f7849b53..16e3ae0e8 100644 --- a/liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/NodeOperator.java +++ b/liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/NodeOperator.java @@ -12,7 +12,8 @@ import com.yomahub.liteflow.property.LiteflowConfigGetter; /** * EL规则中的node的操作符 * - * @author Bryan.Zhang,DaleLee + * @author Bryan.Zhang + * @author DaleLee * @since 2.8.3 */ public class NodeOperator extends BaseOperator { diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/exception/FallbackCmpNotFoundException.java b/liteflow-core/src/main/java/com/yomahub/liteflow/exception/FallbackCmpNotFoundException.java index de930dfee..5a1eca0b2 100644 --- a/liteflow-core/src/main/java/com/yomahub/liteflow/exception/FallbackCmpNotFoundException.java +++ b/liteflow-core/src/main/java/com/yomahub/liteflow/exception/FallbackCmpNotFoundException.java @@ -4,6 +4,7 @@ package com.yomahub.liteflow.exception; * 没有找到降级组件异常 * * @author DaleLee + * @since 2.11.1 */ public class FallbackCmpNotFoundException extends RuntimeException { diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/flow/FlowBus.java b/liteflow-core/src/main/java/com/yomahub/liteflow/flow/FlowBus.java index b77f564db..db3c0e654 100644 --- a/liteflow-core/src/main/java/com/yomahub/liteflow/flow/FlowBus.java +++ b/liteflow-core/src/main/java/com/yomahub/liteflow/flow/FlowBus.java @@ -294,9 +294,6 @@ public class FlowBus { } NodeTypeEnum nodeType = node.getType(); - if (nodeType == null) { - nodeType = fallbackCmp.type(); - } fallbackNodeMap.put(nodeType, node); } diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/flow/element/FallbackNodeProxy.java b/liteflow-core/src/main/java/com/yomahub/liteflow/flow/element/FallbackNodeProxy.java index e4f7cb370..e19119c93 100644 --- a/liteflow-core/src/main/java/com/yomahub/liteflow/flow/element/FallbackNodeProxy.java +++ b/liteflow-core/src/main/java/com/yomahub/liteflow/flow/element/FallbackNodeProxy.java @@ -21,7 +21,7 @@ import com.yomahub.liteflow.slot.Slot; * 降级组件代理 * * @author DaleLee - * @since + * @since 2.11.1 */ public class FallbackNodeProxy extends Node { diff --git a/liteflow-solon-plugin/src/main/resources/META-INF/liteflow-default.properties b/liteflow-solon-plugin/src/main/resources/META-INF/liteflow-default.properties index 35a41afd5..c1fda2e94 100644 --- a/liteflow-solon-plugin/src/main/resources/META-INF/liteflow-default.properties +++ b/liteflow-solon-plugin/src/main/resources/META-INF/liteflow-default.properties @@ -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 diff --git a/liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/java/com/yomahub/liteflow/test/fallback/FallbackELDeclSpringbootTest.java b/liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/java/com/yomahub/liteflow/test/fallback/FallbackELDeclSpringbootTest.java new file mode 100644 index 000000000..2f9f592ed --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/java/com/yomahub/liteflow/test/fallback/FallbackELDeclSpringbootTest.java @@ -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 future1 = flowExecutor.execute2Future("concurrent1", "arg", new Object()); + Future 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)); + } +} diff --git a/liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/java/com/yomahub/liteflow/test/fallback/cmp/ACmp.java b/liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/java/com/yomahub/liteflow/test/fallback/cmp/ACmp.java new file mode 100644 index 000000000..913035fd4 --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/java/com/yomahub/liteflow/test/fallback/cmp/ACmp.java @@ -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!"); + } + +} diff --git a/liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/java/com/yomahub/liteflow/test/fallback/cmp/BCmp.java b/liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/java/com/yomahub/liteflow/test/fallback/cmp/BCmp.java new file mode 100644 index 000000000..af597c5b4 --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/java/com/yomahub/liteflow/test/fallback/cmp/BCmp.java @@ -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!"); + } + +} diff --git a/liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/java/com/yomahub/liteflow/test/fallback/cmp/BreakCmp.java b/liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/java/com/yomahub/liteflow/test/fallback/cmp/BreakCmp.java new file mode 100644 index 000000000..fcbd8e7eb --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/java/com/yomahub/liteflow/test/fallback/cmp/BreakCmp.java @@ -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; + } +} diff --git a/liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/java/com/yomahub/liteflow/test/fallback/cmp/CCmp.java b/liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/java/com/yomahub/liteflow/test/fallback/cmp/CCmp.java new file mode 100644 index 000000000..e74168e37 --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/java/com/yomahub/liteflow/test/fallback/cmp/CCmp.java @@ -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!"); + } + +} diff --git a/liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/java/com/yomahub/liteflow/test/fallback/cmp/DCmp.java b/liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/java/com/yomahub/liteflow/test/fallback/cmp/DCmp.java new file mode 100644 index 000000000..23107e654 --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/java/com/yomahub/liteflow/test/fallback/cmp/DCmp.java @@ -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]"); + } +} diff --git a/liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/java/com/yomahub/liteflow/test/fallback/cmp/ForCmp.java b/liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/java/com/yomahub/liteflow/test/fallback/cmp/ForCmp.java new file mode 100644 index 000000000..99596035d --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/java/com/yomahub/liteflow/test/fallback/cmp/ForCmp.java @@ -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; + } +} diff --git a/liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/java/com/yomahub/liteflow/test/fallback/cmp/IfCmp1.java b/liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/java/com/yomahub/liteflow/test/fallback/cmp/IfCmp1.java new file mode 100644 index 000000000..bd1c6f51e --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/java/com/yomahub/liteflow/test/fallback/cmp/IfCmp1.java @@ -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; + } +} diff --git a/liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/java/com/yomahub/liteflow/test/fallback/cmp/IfCmp2.java b/liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/java/com/yomahub/liteflow/test/fallback/cmp/IfCmp2.java new file mode 100644 index 000000000..5af938e89 --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/java/com/yomahub/liteflow/test/fallback/cmp/IfCmp2.java @@ -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; + } +} diff --git a/liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/java/com/yomahub/liteflow/test/fallback/cmp/IteratorCmp1.java b/liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/java/com/yomahub/liteflow/test/fallback/cmp/IteratorCmp1.java new file mode 100644 index 000000000..1ee36ed1d --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/java/com/yomahub/liteflow/test/fallback/cmp/IteratorCmp1.java @@ -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(); + } +} diff --git a/liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/java/com/yomahub/liteflow/test/fallback/cmp/IteratorCmp2.java b/liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/java/com/yomahub/liteflow/test/fallback/cmp/IteratorCmp2.java new file mode 100644 index 000000000..eab745bb8 --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/java/com/yomahub/liteflow/test/fallback/cmp/IteratorCmp2.java @@ -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(); + } +} diff --git a/liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/java/com/yomahub/liteflow/test/fallback/cmp/SwitchCmp1.java b/liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/java/com/yomahub/liteflow/test/fallback/cmp/SwitchCmp1.java new file mode 100644 index 000000000..46948f736 --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/java/com/yomahub/liteflow/test/fallback/cmp/SwitchCmp1.java @@ -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"; + } +} diff --git a/liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/java/com/yomahub/liteflow/test/fallback/cmp/SwitchCmp2.java b/liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/java/com/yomahub/liteflow/test/fallback/cmp/SwitchCmp2.java new file mode 100644 index 000000000..7da7c7100 --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/java/com/yomahub/liteflow/test/fallback/cmp/SwitchCmp2.java @@ -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"; + } +} diff --git a/liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/java/com/yomahub/liteflow/test/fallback/cmp/WhileCmp1.java b/liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/java/com/yomahub/liteflow/test/fallback/cmp/WhileCmp1.java new file mode 100644 index 000000000..0d65cfb12 --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/java/com/yomahub/liteflow/test/fallback/cmp/WhileCmp1.java @@ -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 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; + } +} diff --git a/liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/java/com/yomahub/liteflow/test/fallback/cmp/WhileCmp2.java b/liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/java/com/yomahub/liteflow/test/fallback/cmp/WhileCmp2.java new file mode 100644 index 000000000..a9bef49b7 --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/java/com/yomahub/liteflow/test/fallback/cmp/WhileCmp2.java @@ -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; + } +} diff --git a/liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/resources/fallback/application.properties b/liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/resources/fallback/application.properties new file mode 100644 index 000000000..b6a1da886 --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/resources/fallback/application.properties @@ -0,0 +1,2 @@ +liteflow.rule-source=fallback/flow.el.xml +liteflow.fallback-cmp-enable=true \ No newline at end of file diff --git a/liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/resources/fallback/flow.el.xml b/liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/resources/fallback/flow.el.xml new file mode 100644 index 000000000..9647a51d6 --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/resources/fallback/flow.el.xml @@ -0,0 +1,136 @@ + + + + + THEN(a, node("x")); + + + + THEN(PRE(node("x1")), node("x2"), FINALLY(node("x3"))); + + + + + WHEN(b, node("x")); + + + + + IF(node("x"), a) + + + + + IF(ifn1, node("x")) + + + + + FOR(node("x")).DO(a); + + + + + FOR(3).DO(node("x")); + + + + + WHILE(node("x")).DO(a) + + + + + WHILE(wn1).DO(node("x")) + + + + + ITERATOR(node("x")).DO(a) + + + + + ITERATOR(itn1).DO(node("x")) + + + + + FOR(3).DO(a).BREAK(node("x")); + + + + WHILE(wn1).DO(a).BREAK(node("x")); + + + + ITERATOR(itn1).DO(a).BREAK(node("x")); + + + + + SWITCH(node("x")).to(a,b); + + + + + SWITCH(swn1).to(node("x"),a); + + + + + IF(AND(node("x"),ifn1), a); + + + + + IF(OR(node("x"),ifn1), a); + + + + + IF(NOT(node("x")), a); + + + + + CATCH(THEN(a, d)).DO(node("x")) + + + + + THEN( + a, + node("x1"), + IF(node("x2"), b) + ); + + + + IF( + OR(node("x1"), ifn1), + THEN(a, node("x2")) + ); + + + + FOR(node("x1")).DO( + THEN(b, node("x2")) + ); + + + + + WHEN( + THEN(node("x1")), + IF(node("x2"), b) + ).maxWaitSeconds(10000); + + + + WHEN( + node("x1"), + IF(node("x2"), b) + ).maxWaitSeconds(10000); + + \ No newline at end of file diff --git a/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/java/com/yomahub/liteflow/test/fallback/FallbackTest.java b/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/java/com/yomahub/liteflow/test/fallback/FallbackTest.java new file mode 100644 index 000000000..3ffb7dbc3 --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/java/com/yomahub/liteflow/test/fallback/FallbackTest.java @@ -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 future1 = flowExecutor.execute2Future("concurrent1", "arg", new Object()); + Future 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)); + } +} diff --git a/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/java/com/yomahub/liteflow/test/fallback/cmp/ACmp.java b/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/java/com/yomahub/liteflow/test/fallback/cmp/ACmp.java new file mode 100644 index 000000000..ed6d7fe76 --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/java/com/yomahub/liteflow/test/fallback/cmp/ACmp.java @@ -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!"); + } + +} diff --git a/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/java/com/yomahub/liteflow/test/fallback/cmp/BCmp.java b/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/java/com/yomahub/liteflow/test/fallback/cmp/BCmp.java new file mode 100644 index 000000000..82b029643 --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/java/com/yomahub/liteflow/test/fallback/cmp/BCmp.java @@ -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!"); + } + +} diff --git a/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/java/com/yomahub/liteflow/test/fallback/cmp/BreakCmp.java b/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/java/com/yomahub/liteflow/test/fallback/cmp/BreakCmp.java new file mode 100644 index 000000000..155bdfae6 --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/java/com/yomahub/liteflow/test/fallback/cmp/BreakCmp.java @@ -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; + } +} diff --git a/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/java/com/yomahub/liteflow/test/fallback/cmp/CCmp.java b/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/java/com/yomahub/liteflow/test/fallback/cmp/CCmp.java new file mode 100644 index 000000000..8e1915878 --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/java/com/yomahub/liteflow/test/fallback/cmp/CCmp.java @@ -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!"); + } + +} diff --git a/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/java/com/yomahub/liteflow/test/fallback/cmp/DCmp.java b/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/java/com/yomahub/liteflow/test/fallback/cmp/DCmp.java new file mode 100644 index 000000000..94c0eaabb --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/java/com/yomahub/liteflow/test/fallback/cmp/DCmp.java @@ -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]"); + } +} diff --git a/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/java/com/yomahub/liteflow/test/fallback/cmp/ForCmp.java b/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/java/com/yomahub/liteflow/test/fallback/cmp/ForCmp.java new file mode 100644 index 000000000..0a69a7638 --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/java/com/yomahub/liteflow/test/fallback/cmp/ForCmp.java @@ -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; + } +} diff --git a/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/java/com/yomahub/liteflow/test/fallback/cmp/IfCmp1.java b/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/java/com/yomahub/liteflow/test/fallback/cmp/IfCmp1.java new file mode 100644 index 000000000..5437cc8fe --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/java/com/yomahub/liteflow/test/fallback/cmp/IfCmp1.java @@ -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; + } +} diff --git a/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/java/com/yomahub/liteflow/test/fallback/cmp/IfCmp2.java b/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/java/com/yomahub/liteflow/test/fallback/cmp/IfCmp2.java new file mode 100644 index 000000000..67187c399 --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/java/com/yomahub/liteflow/test/fallback/cmp/IfCmp2.java @@ -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; + } +} diff --git a/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/java/com/yomahub/liteflow/test/fallback/cmp/IteratorCmp1.java b/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/java/com/yomahub/liteflow/test/fallback/cmp/IteratorCmp1.java new file mode 100644 index 000000000..b6a5a7336 --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/java/com/yomahub/liteflow/test/fallback/cmp/IteratorCmp1.java @@ -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(); + } +} diff --git a/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/java/com/yomahub/liteflow/test/fallback/cmp/IteratorCmp2.java b/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/java/com/yomahub/liteflow/test/fallback/cmp/IteratorCmp2.java new file mode 100644 index 000000000..1a6456da9 --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/java/com/yomahub/liteflow/test/fallback/cmp/IteratorCmp2.java @@ -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(); + } +} diff --git a/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/java/com/yomahub/liteflow/test/fallback/cmp/SwitchCmp1.java b/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/java/com/yomahub/liteflow/test/fallback/cmp/SwitchCmp1.java new file mode 100644 index 000000000..6fa17eacc --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/java/com/yomahub/liteflow/test/fallback/cmp/SwitchCmp1.java @@ -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"; + } +} diff --git a/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/java/com/yomahub/liteflow/test/fallback/cmp/SwitchCmp2.java b/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/java/com/yomahub/liteflow/test/fallback/cmp/SwitchCmp2.java new file mode 100644 index 000000000..78b10c31b --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/java/com/yomahub/liteflow/test/fallback/cmp/SwitchCmp2.java @@ -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"; + } +} diff --git a/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/java/com/yomahub/liteflow/test/fallback/cmp/WhileCmp1.java b/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/java/com/yomahub/liteflow/test/fallback/cmp/WhileCmp1.java new file mode 100644 index 000000000..d525911ba --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/java/com/yomahub/liteflow/test/fallback/cmp/WhileCmp1.java @@ -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 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; + } +} diff --git a/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/java/com/yomahub/liteflow/test/fallback/cmp/WhileCmp2.java b/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/java/com/yomahub/liteflow/test/fallback/cmp/WhileCmp2.java new file mode 100644 index 000000000..531a77d7e --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/java/com/yomahub/liteflow/test/fallback/cmp/WhileCmp2.java @@ -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; + } +} diff --git a/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/resources/fallback/flow.el.xml b/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/resources/fallback/flow.el.xml new file mode 100644 index 000000000..24eba9db2 --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/resources/fallback/flow.el.xml @@ -0,0 +1,153 @@ + + + + + + + + + + + + + + + + + + + + + + THEN(a, node("x")); + + + + THEN(PRE(node("x1")), node("x2"), FINALLY(node("x3"))); + + + + + WHEN(b, node("x")); + + + + + IF(node("x"), a) + + + + + IF(ifn1, node("x")) + + + + + FOR(node("x")).DO(a); + + + + + FOR(3).DO(node("x")); + + + + + WHILE(node("x")).DO(a) + + + + + WHILE(wn1).DO(node("x")) + + + + + ITERATOR(node("x")).DO(a) + + + + + ITERATOR(itn1).DO(node("x")) + + + + + FOR(3).DO(a).BREAK(node("x")); + + + + WHILE(wn1).DO(a).BREAK(node("x")); + + + + ITERATOR(itn1).DO(a).BREAK(node("x")); + + + + + SWITCH(node("x")).to(a,b); + + + + + SWITCH(swn1).to(node("x"),a); + + + + + IF(AND(node("x"),ifn1), a); + + + + + IF(OR(node("x"),ifn1), a); + + + + + IF(NOT(node("x")), a); + + + + + CATCH(THEN(a, d)).DO(node("x")) + + + + + THEN( + a, + node("x1"), + IF(node("x2"), b) + ); + + + + IF( + OR(node("x1"), ifn1), + THEN(a, node("x2")) + ); + + + + FOR(node("x1")).DO( + THEN(b, node("x2")) + ); + + + + + WHEN( + THEN(node("x1")), + IF(node("x2"), b) + ).maxWaitSeconds(10000); + + + + WHEN( + node("x1"), + IF(node("x2"), b) + ).maxWaitSeconds(10000); + + \ No newline at end of file diff --git a/liteflow-testcase-el/liteflow-testcase-el-solon/src/test/java/com/yomahub/liteflow/test/fallback/FallbackELSolonTest.java b/liteflow-testcase-el/liteflow-testcase-el-solon/src/test/java/com/yomahub/liteflow/test/fallback/FallbackELSolonTest.java new file mode 100644 index 000000000..db1603212 --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-solon/src/test/java/com/yomahub/liteflow/test/fallback/FallbackELSolonTest.java @@ -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 future1 = flowExecutor.execute2Future("concurrent1", "arg", new Object()); + Future 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)); + } +} diff --git a/liteflow-testcase-el/liteflow-testcase-el-solon/src/test/java/com/yomahub/liteflow/test/fallback/cmp/ACmp.java b/liteflow-testcase-el/liteflow-testcase-el-solon/src/test/java/com/yomahub/liteflow/test/fallback/cmp/ACmp.java new file mode 100644 index 000000000..8a6739027 --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-solon/src/test/java/com/yomahub/liteflow/test/fallback/cmp/ACmp.java @@ -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!"); + } + +} diff --git a/liteflow-testcase-el/liteflow-testcase-el-solon/src/test/java/com/yomahub/liteflow/test/fallback/cmp/BCmp.java b/liteflow-testcase-el/liteflow-testcase-el-solon/src/test/java/com/yomahub/liteflow/test/fallback/cmp/BCmp.java new file mode 100644 index 000000000..632bd78be --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-solon/src/test/java/com/yomahub/liteflow/test/fallback/cmp/BCmp.java @@ -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!"); + } + +} diff --git a/liteflow-testcase-el/liteflow-testcase-el-solon/src/test/java/com/yomahub/liteflow/test/fallback/cmp/BreakCmp.java b/liteflow-testcase-el/liteflow-testcase-el-solon/src/test/java/com/yomahub/liteflow/test/fallback/cmp/BreakCmp.java new file mode 100644 index 000000000..32813ffe3 --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-solon/src/test/java/com/yomahub/liteflow/test/fallback/cmp/BreakCmp.java @@ -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; + } +} diff --git a/liteflow-testcase-el/liteflow-testcase-el-solon/src/test/java/com/yomahub/liteflow/test/fallback/cmp/CCmp.java b/liteflow-testcase-el/liteflow-testcase-el-solon/src/test/java/com/yomahub/liteflow/test/fallback/cmp/CCmp.java new file mode 100644 index 000000000..54d0799b5 --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-solon/src/test/java/com/yomahub/liteflow/test/fallback/cmp/CCmp.java @@ -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!"); + } + +} diff --git a/liteflow-testcase-el/liteflow-testcase-el-solon/src/test/java/com/yomahub/liteflow/test/fallback/cmp/DCmp.java b/liteflow-testcase-el/liteflow-testcase-el-solon/src/test/java/com/yomahub/liteflow/test/fallback/cmp/DCmp.java new file mode 100644 index 000000000..5d7fd18ee --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-solon/src/test/java/com/yomahub/liteflow/test/fallback/cmp/DCmp.java @@ -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]"); + } +} diff --git a/liteflow-testcase-el/liteflow-testcase-el-solon/src/test/java/com/yomahub/liteflow/test/fallback/cmp/ForCmp.java b/liteflow-testcase-el/liteflow-testcase-el-solon/src/test/java/com/yomahub/liteflow/test/fallback/cmp/ForCmp.java new file mode 100644 index 000000000..2607f8acc --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-solon/src/test/java/com/yomahub/liteflow/test/fallback/cmp/ForCmp.java @@ -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; + } +} diff --git a/liteflow-testcase-el/liteflow-testcase-el-solon/src/test/java/com/yomahub/liteflow/test/fallback/cmp/IfCmp1.java b/liteflow-testcase-el/liteflow-testcase-el-solon/src/test/java/com/yomahub/liteflow/test/fallback/cmp/IfCmp1.java new file mode 100644 index 000000000..62b47dec1 --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-solon/src/test/java/com/yomahub/liteflow/test/fallback/cmp/IfCmp1.java @@ -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; + } +} diff --git a/liteflow-testcase-el/liteflow-testcase-el-solon/src/test/java/com/yomahub/liteflow/test/fallback/cmp/IfCmp2.java b/liteflow-testcase-el/liteflow-testcase-el-solon/src/test/java/com/yomahub/liteflow/test/fallback/cmp/IfCmp2.java new file mode 100644 index 000000000..c5b20fcd8 --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-solon/src/test/java/com/yomahub/liteflow/test/fallback/cmp/IfCmp2.java @@ -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; + } +} diff --git a/liteflow-testcase-el/liteflow-testcase-el-solon/src/test/java/com/yomahub/liteflow/test/fallback/cmp/IteratorCmp1.java b/liteflow-testcase-el/liteflow-testcase-el-solon/src/test/java/com/yomahub/liteflow/test/fallback/cmp/IteratorCmp1.java new file mode 100644 index 000000000..b63cb7c71 --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-solon/src/test/java/com/yomahub/liteflow/test/fallback/cmp/IteratorCmp1.java @@ -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(); + } +} diff --git a/liteflow-testcase-el/liteflow-testcase-el-solon/src/test/java/com/yomahub/liteflow/test/fallback/cmp/IteratorCmp2.java b/liteflow-testcase-el/liteflow-testcase-el-solon/src/test/java/com/yomahub/liteflow/test/fallback/cmp/IteratorCmp2.java new file mode 100644 index 000000000..c45f19034 --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-solon/src/test/java/com/yomahub/liteflow/test/fallback/cmp/IteratorCmp2.java @@ -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(); + } +} diff --git a/liteflow-testcase-el/liteflow-testcase-el-solon/src/test/java/com/yomahub/liteflow/test/fallback/cmp/SwitchCmp1.java b/liteflow-testcase-el/liteflow-testcase-el-solon/src/test/java/com/yomahub/liteflow/test/fallback/cmp/SwitchCmp1.java new file mode 100644 index 000000000..1cb3fe1c3 --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-solon/src/test/java/com/yomahub/liteflow/test/fallback/cmp/SwitchCmp1.java @@ -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"; + } +} diff --git a/liteflow-testcase-el/liteflow-testcase-el-solon/src/test/java/com/yomahub/liteflow/test/fallback/cmp/SwitchCmp2.java b/liteflow-testcase-el/liteflow-testcase-el-solon/src/test/java/com/yomahub/liteflow/test/fallback/cmp/SwitchCmp2.java new file mode 100644 index 000000000..28b1edcfd --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-solon/src/test/java/com/yomahub/liteflow/test/fallback/cmp/SwitchCmp2.java @@ -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"; + } +} diff --git a/liteflow-testcase-el/liteflow-testcase-el-solon/src/test/java/com/yomahub/liteflow/test/fallback/cmp/WhileCmp1.java b/liteflow-testcase-el/liteflow-testcase-el-solon/src/test/java/com/yomahub/liteflow/test/fallback/cmp/WhileCmp1.java new file mode 100644 index 000000000..6769480c6 --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-solon/src/test/java/com/yomahub/liteflow/test/fallback/cmp/WhileCmp1.java @@ -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 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; + } +} diff --git a/liteflow-testcase-el/liteflow-testcase-el-solon/src/test/java/com/yomahub/liteflow/test/fallback/cmp/WhileCmp2.java b/liteflow-testcase-el/liteflow-testcase-el-solon/src/test/java/com/yomahub/liteflow/test/fallback/cmp/WhileCmp2.java new file mode 100644 index 000000000..b198faa0e --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-solon/src/test/java/com/yomahub/liteflow/test/fallback/cmp/WhileCmp2.java @@ -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; + } +} diff --git a/liteflow-testcase-el/liteflow-testcase-el-solon/src/test/resources/fallback/application.properties b/liteflow-testcase-el/liteflow-testcase-el-solon/src/test/resources/fallback/application.properties new file mode 100644 index 000000000..b6a1da886 --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-solon/src/test/resources/fallback/application.properties @@ -0,0 +1,2 @@ +liteflow.rule-source=fallback/flow.el.xml +liteflow.fallback-cmp-enable=true \ No newline at end of file diff --git a/liteflow-testcase-el/liteflow-testcase-el-solon/src/test/resources/fallback/flow.el.xml b/liteflow-testcase-el/liteflow-testcase-el-solon/src/test/resources/fallback/flow.el.xml new file mode 100644 index 000000000..9647a51d6 --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-solon/src/test/resources/fallback/flow.el.xml @@ -0,0 +1,136 @@ + + + + + THEN(a, node("x")); + + + + THEN(PRE(node("x1")), node("x2"), FINALLY(node("x3"))); + + + + + WHEN(b, node("x")); + + + + + IF(node("x"), a) + + + + + IF(ifn1, node("x")) + + + + + FOR(node("x")).DO(a); + + + + + FOR(3).DO(node("x")); + + + + + WHILE(node("x")).DO(a) + + + + + WHILE(wn1).DO(node("x")) + + + + + ITERATOR(node("x")).DO(a) + + + + + ITERATOR(itn1).DO(node("x")) + + + + + FOR(3).DO(a).BREAK(node("x")); + + + + WHILE(wn1).DO(a).BREAK(node("x")); + + + + ITERATOR(itn1).DO(a).BREAK(node("x")); + + + + + SWITCH(node("x")).to(a,b); + + + + + SWITCH(swn1).to(node("x"),a); + + + + + IF(AND(node("x"),ifn1), a); + + + + + IF(OR(node("x"),ifn1), a); + + + + + IF(NOT(node("x")), a); + + + + + CATCH(THEN(a, d)).DO(node("x")) + + + + + THEN( + a, + node("x1"), + IF(node("x2"), b) + ); + + + + IF( + OR(node("x1"), ifn1), + THEN(a, node("x2")) + ); + + + + FOR(node("x1")).DO( + THEN(b, node("x2")) + ); + + + + + WHEN( + THEN(node("x1")), + IF(node("x2"), b) + ).maxWaitSeconds(10000); + + + + WHEN( + node("x1"), + IF(node("x2"), b) + ).maxWaitSeconds(10000); + + \ No newline at end of file diff --git a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/fallback/FallbackSpringbootTest.java b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/fallback/FallbackELSpringbootTest.java similarity index 98% rename from liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/fallback/FallbackSpringbootTest.java rename to liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/fallback/FallbackELSpringbootTest.java index 39a801fd7..dfa7f1ab1 100644 --- a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/fallback/FallbackSpringbootTest.java +++ b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/fallback/FallbackELSpringbootTest.java @@ -2,6 +2,7 @@ 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; @@ -17,12 +18,13 @@ import java.util.concurrent.Future; * SpringBoot 降级组件测试 * * @author DaleLee + * @since 2.11.1 */ @TestPropertySource(value = "classpath:/fallback/application.properties") -@SpringBootTest(classes = FallbackSpringbootTest.class) +@SpringBootTest(classes = FallbackELSpringbootTest.class) @EnableAutoConfiguration @ComponentScan({"com.yomahub.liteflow.test.fallback.cmp"}) -public class FallbackSpringbootTest { +public class FallbackELSpringbootTest extends BaseTest { @Resource private FlowExecutor flowExecutor; diff --git a/liteflow-testcase-el/liteflow-testcase-el-springnative/src/test/java/com/yomahub/liteflow/test/fallback/FallbackELSpringTest.java b/liteflow-testcase-el/liteflow-testcase-el-springnative/src/test/java/com/yomahub/liteflow/test/fallback/FallbackELSpringTest.java new file mode 100644 index 000000000..a6552f9fd --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-springnative/src/test/java/com/yomahub/liteflow/test/fallback/FallbackELSpringTest.java @@ -0,0 +1,221 @@ +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.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit.jupiter.SpringExtension; + +import javax.annotation.Resource; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Future; + +/** + * Spring 降级组件测试 + * + * @author DaleLee + */ +@ExtendWith(SpringExtension.class) +@ContextConfiguration("classpath:/fallback/application.xml") +public class FallbackELSpringTest 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 future1 = flowExecutor.execute2Future("concurrent1", "arg", new Object()); + Future 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)); + } +} diff --git a/liteflow-testcase-el/liteflow-testcase-el-springnative/src/test/java/com/yomahub/liteflow/test/fallback/cmp/ACmp.java b/liteflow-testcase-el/liteflow-testcase-el-springnative/src/test/java/com/yomahub/liteflow/test/fallback/cmp/ACmp.java new file mode 100644 index 000000000..8a6739027 --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-springnative/src/test/java/com/yomahub/liteflow/test/fallback/cmp/ACmp.java @@ -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!"); + } + +} diff --git a/liteflow-testcase-el/liteflow-testcase-el-springnative/src/test/java/com/yomahub/liteflow/test/fallback/cmp/BCmp.java b/liteflow-testcase-el/liteflow-testcase-el-springnative/src/test/java/com/yomahub/liteflow/test/fallback/cmp/BCmp.java new file mode 100644 index 000000000..632bd78be --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-springnative/src/test/java/com/yomahub/liteflow/test/fallback/cmp/BCmp.java @@ -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!"); + } + +} diff --git a/liteflow-testcase-el/liteflow-testcase-el-springnative/src/test/java/com/yomahub/liteflow/test/fallback/cmp/BreakCmp.java b/liteflow-testcase-el/liteflow-testcase-el-springnative/src/test/java/com/yomahub/liteflow/test/fallback/cmp/BreakCmp.java new file mode 100644 index 000000000..32813ffe3 --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-springnative/src/test/java/com/yomahub/liteflow/test/fallback/cmp/BreakCmp.java @@ -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; + } +} diff --git a/liteflow-testcase-el/liteflow-testcase-el-springnative/src/test/java/com/yomahub/liteflow/test/fallback/cmp/CCmp.java b/liteflow-testcase-el/liteflow-testcase-el-springnative/src/test/java/com/yomahub/liteflow/test/fallback/cmp/CCmp.java new file mode 100644 index 000000000..54d0799b5 --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-springnative/src/test/java/com/yomahub/liteflow/test/fallback/cmp/CCmp.java @@ -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!"); + } + +} diff --git a/liteflow-testcase-el/liteflow-testcase-el-springnative/src/test/java/com/yomahub/liteflow/test/fallback/cmp/DCmp.java b/liteflow-testcase-el/liteflow-testcase-el-springnative/src/test/java/com/yomahub/liteflow/test/fallback/cmp/DCmp.java new file mode 100644 index 000000000..5d7fd18ee --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-springnative/src/test/java/com/yomahub/liteflow/test/fallback/cmp/DCmp.java @@ -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]"); + } +} diff --git a/liteflow-testcase-el/liteflow-testcase-el-springnative/src/test/java/com/yomahub/liteflow/test/fallback/cmp/ForCmp.java b/liteflow-testcase-el/liteflow-testcase-el-springnative/src/test/java/com/yomahub/liteflow/test/fallback/cmp/ForCmp.java new file mode 100644 index 000000000..2607f8acc --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-springnative/src/test/java/com/yomahub/liteflow/test/fallback/cmp/ForCmp.java @@ -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; + } +} diff --git a/liteflow-testcase-el/liteflow-testcase-el-springnative/src/test/java/com/yomahub/liteflow/test/fallback/cmp/IfCmp1.java b/liteflow-testcase-el/liteflow-testcase-el-springnative/src/test/java/com/yomahub/liteflow/test/fallback/cmp/IfCmp1.java new file mode 100644 index 000000000..62b47dec1 --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-springnative/src/test/java/com/yomahub/liteflow/test/fallback/cmp/IfCmp1.java @@ -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; + } +} diff --git a/liteflow-testcase-el/liteflow-testcase-el-springnative/src/test/java/com/yomahub/liteflow/test/fallback/cmp/IfCmp2.java b/liteflow-testcase-el/liteflow-testcase-el-springnative/src/test/java/com/yomahub/liteflow/test/fallback/cmp/IfCmp2.java new file mode 100644 index 000000000..c5b20fcd8 --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-springnative/src/test/java/com/yomahub/liteflow/test/fallback/cmp/IfCmp2.java @@ -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; + } +} diff --git a/liteflow-testcase-el/liteflow-testcase-el-springnative/src/test/java/com/yomahub/liteflow/test/fallback/cmp/IteratorCmp1.java b/liteflow-testcase-el/liteflow-testcase-el-springnative/src/test/java/com/yomahub/liteflow/test/fallback/cmp/IteratorCmp1.java new file mode 100644 index 000000000..b63cb7c71 --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-springnative/src/test/java/com/yomahub/liteflow/test/fallback/cmp/IteratorCmp1.java @@ -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(); + } +} diff --git a/liteflow-testcase-el/liteflow-testcase-el-springnative/src/test/java/com/yomahub/liteflow/test/fallback/cmp/IteratorCmp2.java b/liteflow-testcase-el/liteflow-testcase-el-springnative/src/test/java/com/yomahub/liteflow/test/fallback/cmp/IteratorCmp2.java new file mode 100644 index 000000000..c45f19034 --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-springnative/src/test/java/com/yomahub/liteflow/test/fallback/cmp/IteratorCmp2.java @@ -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(); + } +} diff --git a/liteflow-testcase-el/liteflow-testcase-el-springnative/src/test/java/com/yomahub/liteflow/test/fallback/cmp/SwitchCmp1.java b/liteflow-testcase-el/liteflow-testcase-el-springnative/src/test/java/com/yomahub/liteflow/test/fallback/cmp/SwitchCmp1.java new file mode 100644 index 000000000..1cb3fe1c3 --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-springnative/src/test/java/com/yomahub/liteflow/test/fallback/cmp/SwitchCmp1.java @@ -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"; + } +} diff --git a/liteflow-testcase-el/liteflow-testcase-el-springnative/src/test/java/com/yomahub/liteflow/test/fallback/cmp/SwitchCmp2.java b/liteflow-testcase-el/liteflow-testcase-el-springnative/src/test/java/com/yomahub/liteflow/test/fallback/cmp/SwitchCmp2.java new file mode 100644 index 000000000..28b1edcfd --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-springnative/src/test/java/com/yomahub/liteflow/test/fallback/cmp/SwitchCmp2.java @@ -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"; + } +} diff --git a/liteflow-testcase-el/liteflow-testcase-el-springnative/src/test/java/com/yomahub/liteflow/test/fallback/cmp/WhileCmp1.java b/liteflow-testcase-el/liteflow-testcase-el-springnative/src/test/java/com/yomahub/liteflow/test/fallback/cmp/WhileCmp1.java new file mode 100644 index 000000000..6769480c6 --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-springnative/src/test/java/com/yomahub/liteflow/test/fallback/cmp/WhileCmp1.java @@ -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 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; + } +} diff --git a/liteflow-testcase-el/liteflow-testcase-el-springnative/src/test/java/com/yomahub/liteflow/test/fallback/cmp/WhileCmp2.java b/liteflow-testcase-el/liteflow-testcase-el-springnative/src/test/java/com/yomahub/liteflow/test/fallback/cmp/WhileCmp2.java new file mode 100644 index 000000000..b198faa0e --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-springnative/src/test/java/com/yomahub/liteflow/test/fallback/cmp/WhileCmp2.java @@ -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; + } +} diff --git a/liteflow-testcase-el/liteflow-testcase-el-springnative/src/test/resources/fallback/application.xml b/liteflow-testcase-el/liteflow-testcase-el-springnative/src/test/resources/fallback/application.xml new file mode 100644 index 000000000..950c3106e --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-springnative/src/test/resources/fallback/application.xml @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/liteflow-testcase-el/liteflow-testcase-el-springnative/src/test/resources/fallback/flow.el.xml b/liteflow-testcase-el/liteflow-testcase-el-springnative/src/test/resources/fallback/flow.el.xml new file mode 100644 index 000000000..9647a51d6 --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-springnative/src/test/resources/fallback/flow.el.xml @@ -0,0 +1,136 @@ + + + + + THEN(a, node("x")); + + + + THEN(PRE(node("x1")), node("x2"), FINALLY(node("x3"))); + + + + + WHEN(b, node("x")); + + + + + IF(node("x"), a) + + + + + IF(ifn1, node("x")) + + + + + FOR(node("x")).DO(a); + + + + + FOR(3).DO(node("x")); + + + + + WHILE(node("x")).DO(a) + + + + + WHILE(wn1).DO(node("x")) + + + + + ITERATOR(node("x")).DO(a) + + + + + ITERATOR(itn1).DO(node("x")) + + + + + FOR(3).DO(a).BREAK(node("x")); + + + + WHILE(wn1).DO(a).BREAK(node("x")); + + + + ITERATOR(itn1).DO(a).BREAK(node("x")); + + + + + SWITCH(node("x")).to(a,b); + + + + + SWITCH(swn1).to(node("x"),a); + + + + + IF(AND(node("x"),ifn1), a); + + + + + IF(OR(node("x"),ifn1), a); + + + + + IF(NOT(node("x")), a); + + + + + CATCH(THEN(a, d)).DO(node("x")) + + + + + THEN( + a, + node("x1"), + IF(node("x2"), b) + ); + + + + IF( + OR(node("x1"), ifn1), + THEN(a, node("x2")) + ); + + + + FOR(node("x1")).DO( + THEN(b, node("x2")) + ); + + + + + WHEN( + THEN(node("x1")), + IF(node("x2"), b) + ).maxWaitSeconds(10000); + + + + WHEN( + node("x1"), + IF(node("x2"), b) + ).maxWaitSeconds(10000); + + \ No newline at end of file