From f64b97c7a2cfc930846ec605cca6ed386da13e16 Mon Sep 17 00:00:00 2001 From: luoyi <972849752@qq.com> Date: Wed, 27 Sep 2023 20:40:29 +0800 Subject: [PATCH] =?UTF-8?q?enhancement=20#I821F1=20=E4=BD=BF=E7=94=A8=20Ja?= =?UTF-8?q?ckson=20=E5=BA=8F=E5=88=97=E5=8C=96=E5=AF=B9=E8=B1=A1=E6=A3=80?= =?UTF-8?q?=E6=B5=8B=20chain=20=E6=98=AF=E5=90=A6=E5=AD=98=E5=9C=A8?= =?UTF-8?q?=E5=BE=AA=E7=8E=AF=E5=BC=95=E7=94=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../builder/el/LiteFlowChainELBuilder.java | 32 +++++--- .../yomahub/liteflow/core/FlowExecutor.java | 81 +------------------ .../yomahub/liteflow/flow/element/Node.java | 15 ++-- 3 files changed, 32 insertions(+), 96 deletions(-) diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/LiteFlowChainELBuilder.java b/liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/LiteFlowChainELBuilder.java index 9473efb8..616988d7 100644 --- a/liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/LiteFlowChainELBuilder.java +++ b/liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/LiteFlowChainELBuilder.java @@ -4,15 +4,15 @@ import cn.hutool.core.collection.CollUtil; import cn.hutool.core.util.ArrayUtil; import cn.hutool.core.util.CharUtil; import cn.hutool.core.util.StrUtil; +import com.fasterxml.jackson.databind.JsonMappingException; +import com.fasterxml.jackson.databind.ObjectMapper; import com.ql.util.express.DefaultContext; import com.ql.util.express.ExpressRunner; import com.ql.util.express.InstructionSet; import com.ql.util.express.exception.QLException; import com.yomahub.liteflow.builder.el.operator.*; import com.yomahub.liteflow.common.ChainConstant; -import com.yomahub.liteflow.exception.DataNotFoundException; -import com.yomahub.liteflow.exception.ELParseException; -import com.yomahub.liteflow.exception.FlowSystemException; +import com.yomahub.liteflow.exception.*; import com.yomahub.liteflow.flow.FlowBus; import com.yomahub.liteflow.flow.element.Chain; import com.yomahub.liteflow.flow.element.Condition; @@ -34,6 +34,8 @@ public class LiteFlowChainELBuilder { private static final LFLog LOG = LFLoggerManager.getLogger(LiteFlowChainELBuilder.class); + private static ObjectMapper objectMapper =new ObjectMapper(); + private Chain chain; /** @@ -109,15 +111,12 @@ public class LiteFlowChainELBuilder { return this; } - /** - *

原来逻辑从 FlowBus 中获取相应的 chain,如果 EL 表达式中出现嵌套引用 chain,那么在构建 Condition 的时候可能会出现 chain 死循环引用情况

- *

故删掉从 FlowBus 中获取的逻辑,直接使用新的 {@link LiteFlowChainELBuilder} 对象。

- * - * @param chainId - * @return LiteFlowChainELBuilder - */ public LiteFlowChainELBuilder setChainId(String chainId) { - this.chain.setChainId(chainId); + if (FlowBus.containChain(chainId)) { + this.chain = FlowBus.getChain(chainId); + } else { + this.chain.setChainId(chainId); + } return this; } @@ -199,6 +198,17 @@ public class LiteFlowChainELBuilder { if (CollUtil.isNotEmpty(errorList)) { throw new RuntimeException(CollUtil.join(errorList, ",", "[", "]")); } + // 对每一个 chain 进行循环引用检测 + try { + objectMapper.writeValueAsString(this.chain); + } catch (Exception e) { + e.printStackTrace(); + if (e instanceof JsonMappingException) { + throw new CyclicDependencyException(StrUtil.format("There is a circular dependency in the chain[{}], please check carefully.", chain.getChainId())); + } else { + throw new ParseException(e.getMessage()); + } + } } /** diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/core/FlowExecutor.java b/liteflow-core/src/main/java/com/yomahub/liteflow/core/FlowExecutor.java index fea85b47..830ad102 100644 --- a/liteflow-core/src/main/java/com/yomahub/liteflow/core/FlowExecutor.java +++ b/liteflow-core/src/main/java/com/yomahub/liteflow/core/FlowExecutor.java @@ -15,7 +15,9 @@ import com.yomahub.liteflow.enums.InnerChainTypeEnum; import com.yomahub.liteflow.exception.*; import com.yomahub.liteflow.flow.FlowBus; import com.yomahub.liteflow.flow.LiteflowResponse; -import com.yomahub.liteflow.flow.element.*; +import com.yomahub.liteflow.flow.element.Chain; +import com.yomahub.liteflow.flow.element.Node; +import com.yomahub.liteflow.flow.element.Rollbackable; import com.yomahub.liteflow.flow.entity.CmpStep; import com.yomahub.liteflow.flow.id.IdGeneratorHolder; import com.yomahub.liteflow.log.LFLog; @@ -193,9 +195,6 @@ public class FlowExecutor { } } - // 检查构建生成的 chain 的有效性 - checkValidOfChain(); - // 执行钩子 if (isStart) { FlowInitHook.executeHook(); @@ -215,80 +214,6 @@ public class FlowExecutor { } } - /** - * 检查 chain 的有效性,同时重新构建 FlowBus 的 chain,将其子 chain 引用连起来 - * @throws CyclicDependencyException - */ - private void checkValidOfChain() { - - // 存储已经构建完的有效的 chain 对应 Id - Set validChainIdSet = new HashSet<>(); - - // 遍历所有解析的 chain - for (Chain rootChain : FlowBus.getChainMap().values()) { - - // 不存在 validChainIdSet 中的 chain,说明还未检查 - if (!validChainIdSet.contains(rootChain.getChainId())) { - - // 与 rootChain 相关联的 chain 的 ID - Set associatedChainIdSet = new HashSet<>(); - - // 检查 chain 的有效性,是否存在死循环情况 - checkValidOfChain(rootChain, associatedChainIdSet); - - // 检查完当前 chain 后,能走到这里说明当前相关的 chain 是有效的 - validChainIdSet.addAll(associatedChainIdSet); - - } - } - - } - - /** - * 检查 chain 的有效性 - * @param currentChain 当前遍历到的 chain 节点 - * @param associatedChainIdSet 与 rootChain 相关联的 chainId 集合 - * @throws CyclicDependencyException - */ - private void checkValidOfChain(Chain currentChain, Set associatedChainIdSet) { - - // 判断 associatedChainIdSet 中是否已经存在对应的 chain - if (associatedChainIdSet.add(currentChain.getChainId())) { - - // Set 中不存在则说明可能是父 chain 或者子 chain 未引用自身,又或者子 chain 未引用其父 chain,继续判断其子 chain - for (Condition condition : currentChain.getConditionList()) { - - // 遍历所有 executable 列表 - for (Executable executable : condition.getExecutableList()) { - - // 只需判断 chain,因为只有 chain 才会存在死循环依赖情况 - if (executable instanceof Chain) { - - // 能执行到此处,必能从 FlowBus 中获取到对应的 chain,故无需做非空判断 - Chain childrenChain = FlowBus.getChainMap().get(executable.getId()); - - // 递归检查 chain 有效性 - checkValidOfChain(childrenChain, associatedChainIdSet); - - // 重新构建 chain 的 condition 列表 - ((Chain) executable).setConditionList(childrenChain.getConditionList()); - - } - } - } - } else { - - String errorMessage = StrUtil.format("There is a circular dependency in the chain[{}], please check carefully.", currentChain.getChainId()); - - LOG.error(errorMessage); - - // chain 重复,说明子 chain 中引用了自身或其父 chain,存在死循环情况 - throw new CyclicDependencyException(errorMessage); - - } - - } - // 此方法就是从原有的配置源主动拉取新的进行刷新 // 和FlowBus.refreshFlowMetaData的区别就是一个为主动拉取,一个为被动监听到新的内容进行刷新 public void reloadRule() { diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/flow/element/Node.java b/liteflow-core/src/main/java/com/yomahub/liteflow/flow/element/Node.java index 5d90e3c1..59a4674d 100644 --- a/liteflow-core/src/main/java/com/yomahub/liteflow/flow/element/Node.java +++ b/liteflow-core/src/main/java/com/yomahub/liteflow/flow/element/Node.java @@ -8,23 +8,23 @@ package com.yomahub.liteflow.flow.element; -import cn.hutool.core.util.BooleanUtil; import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.StrUtil; import com.alibaba.ttl.TransmittableThreadLocal; +import com.fasterxml.jackson.annotation.JsonIgnore; import com.yomahub.liteflow.core.NodeComponent; +import com.yomahub.liteflow.enums.ExecuteTypeEnum; +import com.yomahub.liteflow.enums.NodeTypeEnum; +import com.yomahub.liteflow.exception.ChainEndException; +import com.yomahub.liteflow.exception.FlowSystemException; +import com.yomahub.liteflow.flow.executor.NodeExecutor; +import com.yomahub.liteflow.flow.executor.NodeExecutorHelper; import com.yomahub.liteflow.log.LFLog; import com.yomahub.liteflow.log.LFLoggerManager; import com.yomahub.liteflow.property.LiteflowConfig; import com.yomahub.liteflow.property.LiteflowConfigGetter; import com.yomahub.liteflow.slot.DataBus; import com.yomahub.liteflow.slot.Slot; -import com.yomahub.liteflow.flow.executor.NodeExecutor; -import com.yomahub.liteflow.flow.executor.NodeExecutorHelper; -import com.yomahub.liteflow.enums.ExecuteTypeEnum; -import com.yomahub.liteflow.enums.NodeTypeEnum; -import com.yomahub.liteflow.exception.ChainEndException; -import com.yomahub.liteflow.exception.FlowSystemException; /** * Node节点,实现可执行器 Node节点并不是单例的,每构建一次都会copy出一个新的实例 @@ -47,6 +47,7 @@ public class Node implements Executable, Cloneable, Rollbackable{ private String language; + @JsonIgnore private NodeComponent instance; private String tag;