From 4e616f9da6b10a38dcb51d9086d8d88509b69cd9 Mon Sep 17 00:00:00 2001 From: luoyi <972849752@qq.com> Date: Wed, 30 Aug 2023 21:16:10 +0800 Subject: [PATCH 01/53] =?UTF-8?q?enhancement=20#I7XAIB=20WHEN=20=E5=A2=9E?= =?UTF-8?q?=E5=8A=A0=20must=20=E8=AF=AD=E6=B3=95=EF=BC=8C=E8=B0=83?= =?UTF-8?q?=E6=95=B4=20WhenCondition=20=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../builder/el/LiteFlowChainELBuilder.java | 3 +- .../builder/el/operator/AnyOperator.java | 3 +- .../builder/el/operator/MustOperator.java | 28 +++ .../liteflow/common/ChainConstant.java | 2 + .../liteflow/enums/ParallelStrategyEnum.java | 57 +++++ .../ParallelExecutorCreateException.java | 29 +++ .../flow/element/condition/WhenCondition.java | 174 +++------------- .../strategy/AllOfParallelExecutor.java | 31 +++ .../strategy/AnyOfParallelExecutor.java | 31 +++ .../strategy/ParallelStrategyExecutor.java | 194 ++++++++++++++++++ .../strategy/ParallelStrategyHelper.java | 79 +++++++ .../strategy/SpecifyParallelExecutor.java | 78 +++++++ .../asyncNode/AsyncNodeELSpringbootTest.java | 36 ++++ .../liteflow/test/asyncNode/cmp/KCmp.java | 27 +++ .../liteflow/test/asyncNode/cmp/LCmp.java | 15 ++ .../src/test/resources/asyncNode/flow.el.xml | 16 ++ 16 files changed, 652 insertions(+), 151 deletions(-) create mode 100644 liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/MustOperator.java create mode 100644 liteflow-core/src/main/java/com/yomahub/liteflow/enums/ParallelStrategyEnum.java create mode 100644 liteflow-core/src/main/java/com/yomahub/liteflow/exception/ParallelExecutorCreateException.java create mode 100644 liteflow-core/src/main/java/com/yomahub/liteflow/flow/parallel/strategy/AllOfParallelExecutor.java create mode 100644 liteflow-core/src/main/java/com/yomahub/liteflow/flow/parallel/strategy/AnyOfParallelExecutor.java create mode 100644 liteflow-core/src/main/java/com/yomahub/liteflow/flow/parallel/strategy/ParallelStrategyExecutor.java create mode 100644 liteflow-core/src/main/java/com/yomahub/liteflow/flow/parallel/strategy/ParallelStrategyHelper.java create mode 100644 liteflow-core/src/main/java/com/yomahub/liteflow/flow/parallel/strategy/SpecifyParallelExecutor.java create mode 100644 liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/asyncNode/cmp/KCmp.java create mode 100644 liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/asyncNode/cmp/LCmp.java 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 97e3de3e5..a5e26cab9 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 @@ -15,8 +15,8 @@ import com.yomahub.liteflow.exception.ELParseException; import com.yomahub.liteflow.exception.FlowSystemException; import com.yomahub.liteflow.flow.FlowBus; import com.yomahub.liteflow.flow.element.Chain; -import com.yomahub.liteflow.flow.element.Node; import com.yomahub.liteflow.flow.element.Condition; +import com.yomahub.liteflow.flow.element.Node; import com.yomahub.liteflow.log.LFLog; import com.yomahub.liteflow.log.LFLoggerManager; @@ -72,6 +72,7 @@ public class LiteFlowChainELBuilder { EXPRESS_RUNNER.addFunctionAndClassMethod(ChainConstant.DEFAULT, Object.class, new DefaultOperator()); EXPRESS_RUNNER.addFunctionAndClassMethod(ChainConstant.TAG, Object.class, new TagOperator()); EXPRESS_RUNNER.addFunctionAndClassMethod(ChainConstant.ANY, Object.class, new AnyOperator()); + EXPRESS_RUNNER.addFunctionAndClassMethod(ChainConstant.MUST, Object.class, new MustOperator()); EXPRESS_RUNNER.addFunctionAndClassMethod(ChainConstant.ID, Object.class, new IdOperator()); EXPRESS_RUNNER.addFunctionAndClassMethod(ChainConstant.IGNORE_ERROR, Object.class, new IgnoreErrorOperator()); EXPRESS_RUNNER.addFunctionAndClassMethod(ChainConstant.THREAD_POOL, Object.class, new ThreadPoolOperator()); diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/AnyOperator.java b/liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/AnyOperator.java index 144f3a275..4f326dd68 100644 --- a/liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/AnyOperator.java +++ b/liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/AnyOperator.java @@ -2,6 +2,7 @@ package com.yomahub.liteflow.builder.el.operator; import com.yomahub.liteflow.builder.el.operator.base.BaseOperator; import com.yomahub.liteflow.builder.el.operator.base.OperatorHelper; +import com.yomahub.liteflow.enums.ParallelStrategyEnum; import com.yomahub.liteflow.flow.element.condition.WhenCondition; /** @@ -19,7 +20,7 @@ public class AnyOperator extends BaseOperator { WhenCondition whenCondition = OperatorHelper.convert(objects[0], WhenCondition.class); Boolean any = OperatorHelper.convert(objects[1], Boolean.class); - whenCondition.setAny(any); + whenCondition.setParallelStrategy(any ? ParallelStrategyEnum.ANY : ParallelStrategyEnum.ALL); return whenCondition; } diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/MustOperator.java b/liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/MustOperator.java new file mode 100644 index 000000000..cb018c529 --- /dev/null +++ b/liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/MustOperator.java @@ -0,0 +1,28 @@ +package com.yomahub.liteflow.builder.el.operator; + +import com.yomahub.liteflow.builder.el.operator.base.BaseOperator; +import com.yomahub.liteflow.builder.el.operator.base.OperatorHelper; +import com.yomahub.liteflow.enums.ParallelStrategyEnum; +import com.yomahub.liteflow.flow.element.condition.WhenCondition; + +/** + * EL 规则中的 must 的操作符 + * + * @author luo yi + * @since 2.11.0 + */ +public class MustOperator extends BaseOperator { + + @Override + public WhenCondition build(Object[] objects) throws Exception { + OperatorHelper.checkObjectSizeEqTwo(objects); + + WhenCondition whenCondition = OperatorHelper.convert(objects[0], WhenCondition.class); + + String specifyId = OperatorHelper.convert(objects[1], String.class); + whenCondition.setSpecifyId(specifyId); + whenCondition.setParallelStrategy(ParallelStrategyEnum.SPECIFY); + return whenCondition; + } + +} diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/common/ChainConstant.java b/liteflow-core/src/main/java/com/yomahub/liteflow/common/ChainConstant.java index 7379f26ea..a097cdfe1 100644 --- a/liteflow-core/src/main/java/com/yomahub/liteflow/common/ChainConstant.java +++ b/liteflow-core/src/main/java/com/yomahub/liteflow/common/ChainConstant.java @@ -30,6 +30,8 @@ public interface ChainConstant { String ANY = "any"; + String MUST = "must"; + String TYPE = "type"; String THEN = "THEN"; diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/enums/ParallelStrategyEnum.java b/liteflow-core/src/main/java/com/yomahub/liteflow/enums/ParallelStrategyEnum.java new file mode 100644 index 000000000..fc69b634e --- /dev/null +++ b/liteflow-core/src/main/java/com/yomahub/liteflow/enums/ParallelStrategyEnum.java @@ -0,0 +1,57 @@ +package com.yomahub.liteflow.enums; + +import com.yomahub.liteflow.flow.parallel.strategy.AllOfParallelExecutor; +import com.yomahub.liteflow.flow.parallel.strategy.AnyOfParallelExecutor; +import com.yomahub.liteflow.flow.parallel.strategy.ParallelStrategyExecutor; +import com.yomahub.liteflow.flow.parallel.strategy.SpecifyParallelExecutor; + +/** + * 并行策略枚举类 + * + * @author luo yi + * @since 2.11.0 + */ +public enum ParallelStrategyEnum { + + ANY("anyOf", "完成任一任务", AnyOfParallelExecutor.class), + + ALL("allOf", "完成全部任务", AllOfParallelExecutor.class), + + SPECIFY("must", "完成指定任务", SpecifyParallelExecutor.class); + + private String strategyType; + + private String description; + + private Class clazz; + + ParallelStrategyEnum(String strategyType, String description, Class clazz) { + this.strategyType = strategyType; + this.description = description; + this.clazz = clazz; + } + + public String getStrategyType() { + return strategyType; + } + + public void setStrategyType(String strategyType) { + this.strategyType = strategyType; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public Class getClazz() { + return clazz; + } + + public void setClazz(Class clazz) { + this.clazz = clazz; + } +} diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/exception/ParallelExecutorCreateException.java b/liteflow-core/src/main/java/com/yomahub/liteflow/exception/ParallelExecutorCreateException.java new file mode 100644 index 000000000..68ea8a39a --- /dev/null +++ b/liteflow-core/src/main/java/com/yomahub/liteflow/exception/ParallelExecutorCreateException.java @@ -0,0 +1,29 @@ +package com.yomahub.liteflow.exception; + +/** + * 并行策略执行器创建异常 + * + * @author luo yi + * @since 2.11.0 + */ +public class ParallelExecutorCreateException extends RuntimeException { + + private static final long serialVersionUID = 1L; + + /** 异常信息 */ + private String message; + + public ParallelExecutorCreateException(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/element/condition/WhenCondition.java b/liteflow-core/src/main/java/com/yomahub/liteflow/flow/element/condition/WhenCondition.java index 830aee652..4249617da 100644 --- a/liteflow-core/src/main/java/com/yomahub/liteflow/flow/element/condition/WhenCondition.java +++ b/liteflow-core/src/main/java/com/yomahub/liteflow/flow/element/condition/WhenCondition.java @@ -7,28 +7,16 @@ */ package com.yomahub.liteflow.flow.element.condition; -import cn.hutool.core.util.ObjectUtil; -import cn.hutool.core.util.StrUtil; import com.yomahub.liteflow.common.LocalDefaultFlowConstant; import com.yomahub.liteflow.enums.ConditionTypeEnum; -import com.yomahub.liteflow.exception.WhenExecuteException; +import com.yomahub.liteflow.enums.ParallelStrategyEnum; import com.yomahub.liteflow.flow.element.Condition; -import com.yomahub.liteflow.flow.parallel.CompletableFutureTimeout; -import com.yomahub.liteflow.flow.parallel.ParallelSupplier; -import com.yomahub.liteflow.flow.parallel.WhenFutureObj; +import com.yomahub.liteflow.flow.parallel.strategy.ParallelStrategyExecutor; +import com.yomahub.liteflow.flow.parallel.strategy.ParallelStrategyHelper; 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.thread.ExecutorHelper; -import java.util.List; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.ExecutorService; + import java.util.concurrent.TimeUnit; -import java.util.stream.Collectors; /** * 并行器 @@ -46,8 +34,11 @@ public class WhenCondition extends Condition { // 此属性已弃用 private String group = LocalDefaultFlowConstant.DEFAULT; - // 只在when类型下有效,为true的话说明在多个并行节点下,任意一个成功,整个when就成功 - private boolean any = false; + // 当前 When 对应并行策略,默认为 ALL + private ParallelStrategyEnum parallelStrategy; + + // 只有 must 条件下,才会赋值 specifyId + private String specifyId; // when单独的线程池名称 private String threadExecutorClass; @@ -71,133 +62,10 @@ public class WhenCondition extends Condition { // 使用线程池执行when并发流程 // 这块涉及到挺多的多线程逻辑,所以注释比较详细,看到这里的童鞋可以仔细阅读 private void executeAsyncCondition(Integer slotIndex) throws Exception { - Slot slot = DataBus.getSlot(slotIndex); - - String currChainName = this.getCurrChainId(); - - // 此方法其实只会初始化一次Executor,不会每次都会初始化。Executor是唯一的 - ExecutorService parallelExecutor = ExecutorHelper.loadInstance() - .buildWhenExecutor(this.getThreadExecutorClass()); - - // 获得liteflow的参数 - LiteflowConfig liteflowConfig = LiteflowConfigGetter.get(); - - // 定义是否中断参数 - // 这里为什么要定义成数组呢,因为后面lambda要用到,根据final不能修改引用的原则,这里用了数组对象 - final boolean[] interrupted = { false }; - - // 这里主要是做了封装CompletableFuture对象,用lumbda表达式做了很多事情,这句代码要仔细理清 - // 1.先进行过滤,前置和后置组件过滤掉,因为在EL Chain处理的时候已经提出来了 - // 2.过滤isAccess为false的情况,因为不过滤这个的话,如果加上了any,那么isAccess为false那就是最快的了 - // 3.根据condition.getNodeList()的集合进行流处理,用map进行把executable对象转换成List> - // 4.在转的过程中,套入CompletableFutureTimeout方法进行超时判断,如果超时则用WhenFutureObj.timeOut返回超时的对象 - // 5.第2个参数是主要的本体CompletableFuture,传入了ParallelSupplier和线程池对象 - if (ObjectUtil.isNull(this.getMaxWaitTime())) { - if (ObjectUtil.isNotNull(liteflowConfig.getWhenMaxWaitSeconds())) { - // 获取全局异步线程最长等待秒数 - this.setMaxWaitTime(liteflowConfig.getWhenMaxWaitSeconds()); - this.setMaxWaitTimeUnit(TimeUnit.SECONDS); - } else { - // 获取全局异步线程最⻓的等待时间 - this.setMaxWaitTime(liteflowConfig.getWhenMaxWaitTime()); - } - } - - if (ObjectUtil.isNull(this.getMaxWaitTimeUnit())) { - // 获取全局异步线程最⻓的等待时间单位 - this.setMaxWaitTimeUnit(liteflowConfig.getWhenMaxWaitTimeUnit()); - } - - List> completableFutureList = this.getExecutableList() - .stream() - .filter(executable -> !(executable instanceof PreCondition) && !(executable instanceof FinallyCondition)) - .filter(executable -> { - try { - return executable.isAccess(slotIndex); - } catch (Exception e) { - LOG.error("there was an error when executing the when component isAccess", e); - return false; - } - }) - .map(executable -> CompletableFutureTimeout.completeOnTimeout( - WhenFutureObj.timeOut(executable.getId()), - CompletableFuture.supplyAsync(new ParallelSupplier(executable, currChainName, slotIndex), - parallelExecutor), - this.getMaxWaitTime(), this.getMaxWaitTimeUnit())) - .collect(Collectors.toList()); - - CompletableFuture resultCompletableFuture; - - // 这里判断执行方式 - // 如果any为false,说明这些异步任务全部执行好或者超时,才返回 - // 如果any为true,说明这些异步任务只要任意一个执行完成,就返回 - if (this.isAny()) { - // 把这些CompletableFuture通过anyOf合成一个CompletableFuture - resultCompletableFuture = CompletableFuture - .anyOf(completableFutureList.toArray(new CompletableFuture[] {})); - } else { - // 把这些CompletableFuture通过allOf合成一个CompletableFuture - resultCompletableFuture = CompletableFuture - .allOf(completableFutureList.toArray(new CompletableFuture[] {})); - } - - try { - // 进行执行,这句执行完后,就意味着所有的任务要么执行完毕,要么超时返回 - resultCompletableFuture.get(); - } catch (InterruptedException | ExecutionException e) { - LOG.error("there was an error when executing the CompletableFuture", e); - interrupted[0] = true; - } - - // 拿到已经完成的CompletableFuture - // 如果any为false,那么所有任务都已经完成 - // 如果any为true,那么这里拿到的是第一个完成的任务 - // 这里过滤和转换一起用lumbda做了 - List allCompletableWhenFutureObjList = completableFutureList.stream().filter(f -> { - // 过滤出已经完成的,没完成的就直接终止 - if (f.isDone()) { - return true; - } else { - f.cancel(true); - return false; - } - }).map(f -> { - try { - return f.get(); - } catch (InterruptedException | ExecutionException e) { - interrupted[0] = true; - return null; - } - }).collect(Collectors.toList()); - - // 判断超时,上面已经拿到了所有已经完成的CompletableFuture - // 那我们只要过滤出超时的CompletableFuture - List timeOutWhenFutureObjList = allCompletableWhenFutureObjList.stream() - .filter(WhenFutureObj::isTimeout) - .collect(Collectors.toList()); - - // 输出超时信息 - timeOutWhenFutureObjList.forEach(whenFutureObj -> LOG.warn( - "executing thread has reached max-wait-seconds, thread canceled.Execute-item: [{}]", whenFutureObj.getExecutorName())); - - // 当配置了ignoreError = false,出现interrupted或者!f.get()的情况,将抛出WhenExecuteException - if (!this.isIgnoreError()) { - if (interrupted[0]) { - throw new WhenExecuteException(StrUtil - .format("requestId [{}] when execute interrupted. errorResume [false].", slot.getRequestId())); - } - - // 循环判断CompletableFuture的返回值,如果异步执行失败,则抛出相应的业务异常 - for (WhenFutureObj whenFutureObj : allCompletableWhenFutureObjList) { - if (!whenFutureObj.isSuccess()) { - LOG.info(StrUtil.format("when-executor[{}] execute failed. errorResume [false].", whenFutureObj.getExecutorName())); - throw whenFutureObj.getEx(); - } - } - } else if (interrupted[0]) { - // 这里由于配置了ignoreError,所以只打印warn日志 - LOG.warn("executing when condition timeout , but ignore with errorResume."); - } + // 获取并发执行策略 + ParallelStrategyExecutor parallelStrategyExecutor = ParallelStrategyHelper.loadInstance().buildParallelExecutor(this.getParallelStrategy()); + // 执行逻辑 + parallelStrategyExecutor.execute(this, slotIndex); } public boolean isIgnoreError() { @@ -216,12 +84,20 @@ public class WhenCondition extends Condition { this.group = group; } - public boolean isAny() { - return any; + public ParallelStrategyEnum getParallelStrategy() { + return parallelStrategy; } - public void setAny(boolean any) { - this.any = any; + public void setParallelStrategy(ParallelStrategyEnum parallelStrategy) { + this.parallelStrategy = parallelStrategy; + } + + public String getSpecifyId() { + return specifyId; + } + + public void setSpecifyId(String specifyId) { + this.specifyId = specifyId; } public String getThreadExecutorClass() { diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/flow/parallel/strategy/AllOfParallelExecutor.java b/liteflow-core/src/main/java/com/yomahub/liteflow/flow/parallel/strategy/AllOfParallelExecutor.java new file mode 100644 index 000000000..c3d6de2a4 --- /dev/null +++ b/liteflow-core/src/main/java/com/yomahub/liteflow/flow/parallel/strategy/AllOfParallelExecutor.java @@ -0,0 +1,31 @@ +package com.yomahub.liteflow.flow.parallel.strategy; + +import com.yomahub.liteflow.flow.element.condition.WhenCondition; +import com.yomahub.liteflow.flow.parallel.WhenFutureObj; + +import java.util.List; +import java.util.concurrent.CompletableFuture; + +/** + * 完成全部任务 + * + * @author luo yi + * @since 2.11.0 + */ +public class AllOfParallelExecutor extends ParallelStrategyExecutor { + + @Override + public void execute(WhenCondition whenCondition, Integer slotIndex) throws Exception { + + // 获取所有 CompletableFuture + List> completableFutureList = this.getCompletableFutureList(whenCondition, slotIndex); + + // 把这些 CompletableFuture 通过 anyOf 合成一个 CompletableFuture + CompletableFuture resultCompletableFuture = CompletableFuture.allOf(completableFutureList.toArray(new CompletableFuture[] {})); + + // 结果处理 + this.handleResult(whenCondition, slotIndex, completableFutureList, resultCompletableFuture); + + } + +} diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/flow/parallel/strategy/AnyOfParallelExecutor.java b/liteflow-core/src/main/java/com/yomahub/liteflow/flow/parallel/strategy/AnyOfParallelExecutor.java new file mode 100644 index 000000000..2115db84e --- /dev/null +++ b/liteflow-core/src/main/java/com/yomahub/liteflow/flow/parallel/strategy/AnyOfParallelExecutor.java @@ -0,0 +1,31 @@ +package com.yomahub.liteflow.flow.parallel.strategy; + +import com.yomahub.liteflow.flow.element.condition.WhenCondition; +import com.yomahub.liteflow.flow.parallel.WhenFutureObj; + +import java.util.List; +import java.util.concurrent.CompletableFuture; + +/** + * 完成任一任务 + * + * @author luo yi + * @since 2.11.0 + */ +public class AnyOfParallelExecutor extends ParallelStrategyExecutor { + + @Override + public void execute(WhenCondition whenCondition, Integer slotIndex) throws Exception { + + // 获取所有 CompletableFuture + List> completableFutureList = this.getCompletableFutureList(whenCondition, slotIndex); + + // 把这些 CompletableFuture 通过 anyOf 合成一个 CompletableFuture + CompletableFuture resultCompletableFuture = CompletableFuture.anyOf(completableFutureList.toArray(new CompletableFuture[] {})); + + // 结果处理 + this.handleResult(whenCondition, slotIndex, completableFutureList, resultCompletableFuture); + + } + +} diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/flow/parallel/strategy/ParallelStrategyExecutor.java b/liteflow-core/src/main/java/com/yomahub/liteflow/flow/parallel/strategy/ParallelStrategyExecutor.java new file mode 100644 index 000000000..56f8c9ba9 --- /dev/null +++ b/liteflow-core/src/main/java/com/yomahub/liteflow/flow/parallel/strategy/ParallelStrategyExecutor.java @@ -0,0 +1,194 @@ +package com.yomahub.liteflow.flow.parallel.strategy; + +import cn.hutool.core.util.ObjectUtil; +import cn.hutool.core.util.StrUtil; +import com.yomahub.liteflow.exception.WhenExecuteException; +import com.yomahub.liteflow.flow.element.Executable; +import com.yomahub.liteflow.flow.element.condition.FinallyCondition; +import com.yomahub.liteflow.flow.element.condition.PreCondition; +import com.yomahub.liteflow.flow.element.condition.WhenCondition; +import com.yomahub.liteflow.flow.parallel.CompletableFutureTimeout; +import com.yomahub.liteflow.flow.parallel.ParallelSupplier; +import com.yomahub.liteflow.flow.parallel.WhenFutureObj; +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.thread.ExecutorHelper; + +import java.util.List; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.TimeUnit; +import java.util.stream.Collectors; + +/** + * 并发策略执行器抽象类 + * + * @author luo yi + * @since 2.11.0 + */ +public abstract class ParallelStrategyExecutor { + + protected final LFLog LOG = LFLoggerManager.getLogger(this.getClass()); + + /** + * 封装 CompletableFuture 对象 + * @param executable + * @param parallelExecutor + * @param whenCondition + * @param currChainName + * @param slotIndex + * @return + */ + protected CompletableFuture wrappedFutureObj(Executable executable, ExecutorService parallelExecutor, + WhenCondition whenCondition, String currChainName, Integer slotIndex) { + return CompletableFutureTimeout.completeOnTimeout( + WhenFutureObj.timeOut(executable.getId()), + CompletableFuture.supplyAsync(new ParallelSupplier(executable, currChainName, slotIndex), parallelExecutor), + whenCondition.getMaxWaitTime(), + whenCondition.getMaxWaitTimeUnit()); + } + + /** + * 设置 WhenCondition 参数 + * @param whenCondition + */ + protected void setWhenConditionParams(WhenCondition whenCondition) { + // 获得liteflow的参数 + LiteflowConfig liteflowConfig = LiteflowConfigGetter.get(); + if (ObjectUtil.isNull(whenCondition.getMaxWaitTime())) { + if (ObjectUtil.isNotNull(liteflowConfig.getWhenMaxWaitSeconds())) { + // 获取全局异步线程最长等待秒数 + whenCondition.setMaxWaitTime(liteflowConfig.getWhenMaxWaitSeconds()); + whenCondition.setMaxWaitTimeUnit(TimeUnit.SECONDS); + } else { + // 获取全局异步线程最⻓的等待时间 + whenCondition.setMaxWaitTime(liteflowConfig.getWhenMaxWaitTime()); + } + } + + if (ObjectUtil.isNull(whenCondition.getMaxWaitTimeUnit())) { + // 获取全局异步线程最⻓的等待时间单位 + whenCondition.setMaxWaitTimeUnit(liteflowConfig.getWhenMaxWaitTimeUnit()); + } + } + + /** + * 获取所有任务 + * @param whenCondition + * @param slotIndex + * @return + */ + protected List> getCompletableFutureList(WhenCondition whenCondition, Integer slotIndex) { + String currChainName = whenCondition.getCurrChainId(); + + // 此方法其实只会初始化一次Executor,不会每次都会初始化。Executor是唯一的 + ExecutorService parallelExecutor = ExecutorHelper.loadInstance().buildWhenExecutor(whenCondition.getThreadExecutorClass()); + + // 设置参数 + setWhenConditionParams(whenCondition); + + // 这里主要是做了封装CompletableFuture对象,用lumbda表达式做了很多事情,这句代码要仔细理清 + // 1.先进行过滤,前置和后置组件过滤掉,因为在EL Chain处理的时候已经提出来了 + // 2.过滤isAccess为false的情况,因为不过滤这个的话,如果加上了any,那么isAccess为false那就是最快的了 + // 3.根据condition.getNodeList()的集合进行流处理,用map进行把executable对象转换成List> + // 4.在转的过程中,套入CompletableFutureTimeout方法进行超时判断,如果超时则用WhenFutureObj.timeOut返回超时的对象 + // 5.第2个参数是主要的本体CompletableFuture,传入了ParallelSupplier和线程池对象 + List> completableFutureList = whenCondition.getExecutableList() + .stream() + .filter(executable -> !(executable instanceof PreCondition) && !(executable instanceof FinallyCondition)) + .filter(executable -> { + try { + return executable.isAccess(slotIndex); + } catch (Exception e) { + LOG.error("there was an error when executing the when component isAccess", e); + return false; + } + }) + .map(executable -> wrappedFutureObj(executable, parallelExecutor, whenCondition, currChainName, slotIndex)) + .collect(Collectors.toList()); + + return completableFutureList; + } + + /** + * 结果处理 + * @param whenCondition + * @param slotIndex + * @param completableFutureList + * @param resultCompletableFuture + * @throws Exception + */ + protected void handleResult(WhenCondition whenCondition, Integer slotIndex, List> completableFutureList, CompletableFuture resultCompletableFuture) throws Exception { + Slot slot = DataBus.getSlot(slotIndex); + + // 定义是否中断参数 + // 这里为什么要定义成数组呢,因为后面lambda要用到,根据final不能修改引用的原则,这里用了数组对象 + final boolean[] interrupted = { false }; + + try { + // 进行执行,这句执行完后,就意味着所有的任务要么执行完毕,要么超时返回 + resultCompletableFuture.get(); + } catch (InterruptedException | ExecutionException e) { + LOG.error("there was an error when executing the CompletableFuture", e); + interrupted[0] = true; + } + + // 拿到已经完成的CompletableFuture + // 如果any为false,那么所有任务都已经完成 + // 如果any为true,那么这里拿到的是第一个完成的任务 + // 这里过滤和转换一起用lumbda做了 + List allCompletableWhenFutureObjList = completableFutureList.stream().filter(f -> { + // 过滤出已经完成的,没完成的就直接终止 + if (f.isDone()) { + return true; + } else { + f.cancel(true); + return false; + } + }).map(f -> { + try { + return f.get(); + } catch (InterruptedException | ExecutionException e) { + interrupted[0] = true; + return null; + } + }).collect(Collectors.toList()); + + // 判断超时,上面已经拿到了所有已经完成的CompletableFuture + // 那我们只要过滤出超时的CompletableFuture + List timeOutWhenFutureObjList = allCompletableWhenFutureObjList.stream() + .filter(WhenFutureObj::isTimeout) + .collect(Collectors.toList()); + + // 输出超时信息 + timeOutWhenFutureObjList.forEach(whenFutureObj -> LOG.warn( + "executing thread has reached max-wait-seconds, thread canceled.Execute-item: [{}]", whenFutureObj.getExecutorName())); + + // 当配置了ignoreError = false,出现interrupted或者!f.get()的情况,将抛出WhenExecuteException + if (!whenCondition.isIgnoreError()) { + if (interrupted[0]) { + throw new WhenExecuteException(StrUtil + .format("requestId [{}] when execute interrupted. errorResume [false].", slot.getRequestId())); + } + + // 循环判断CompletableFuture的返回值,如果异步执行失败,则抛出相应的业务异常 + for (WhenFutureObj whenFutureObj : allCompletableWhenFutureObjList) { + if (!whenFutureObj.isSuccess()) { + LOG.info(StrUtil.format("when-executor[{}] execute failed. errorResume [false].", whenFutureObj.getExecutorName())); + throw whenFutureObj.getEx(); + } + } + } else if (interrupted[0]) { + // 这里由于配置了ignoreError,所以只打印warn日志 + LOG.warn("executing when condition timeout , but ignore with errorResume."); + } + } + + public abstract void execute(WhenCondition whenCondition, Integer slotIndex) throws Exception; + +} diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/flow/parallel/strategy/ParallelStrategyHelper.java b/liteflow-core/src/main/java/com/yomahub/liteflow/flow/parallel/strategy/ParallelStrategyHelper.java new file mode 100644 index 000000000..250fccfb5 --- /dev/null +++ b/liteflow-core/src/main/java/com/yomahub/liteflow/flow/parallel/strategy/ParallelStrategyHelper.java @@ -0,0 +1,79 @@ +package com.yomahub.liteflow.flow.parallel.strategy; + +import cn.hutool.core.map.MapUtil; +import cn.hutool.core.util.ObjUtil; +import com.yomahub.liteflow.enums.ParallelStrategyEnum; +import com.yomahub.liteflow.exception.ParallelExecutorCreateException; +import com.yomahub.liteflow.log.LFLog; +import com.yomahub.liteflow.log.LFLoggerManager; +import com.yomahub.liteflow.spi.holder.ContextAwareHolder; + +import java.util.Map; + +/** + * WHEN 并发策略辅助 + * + * @author luo yi + * @since 2.11.0 + */ +public class ParallelStrategyHelper { + + private final LFLog LOG = LFLoggerManager.getLogger(ParallelStrategyHelper.class); + + /** + * 此处使用Map缓存线程池信息 key - 线程池构建者的Class全类名 value - 线程池对象 + */ + private final Map strategyExecutorMap; + + private ParallelStrategyHelper() { + strategyExecutorMap = MapUtil.newConcurrentHashMap(); + } + + /** + * 使用静态内部类实现单例模式 + */ + private static class Holder { + + static final ParallelStrategyHelper INSTANCE = new ParallelStrategyHelper(); + + } + + public static ParallelStrategyHelper loadInstance() { + return ParallelStrategyHelper.Holder.INSTANCE; + } + + private ParallelStrategyExecutor getParallelStrategyExecutor(ParallelStrategyEnum parallelStrategyEnum) { + try { + ParallelStrategyExecutor strategyExecutor = strategyExecutorMap.get(parallelStrategyEnum); + if (ObjUtil.isNotNull(strategyExecutor)) return strategyExecutor; + + Class executorClass = (Class) Class.forName(parallelStrategyEnum.getClazz().getName()); + strategyExecutor = ContextAwareHolder.loadContextAware().registerBean(executorClass); + strategyExecutorMap.put(parallelStrategyEnum, strategyExecutor); + return strategyExecutor; + } catch (Exception e) { + LOG.error(e.getMessage()); + throw new ParallelExecutorCreateException(e.getMessage()); + } + } + + public ParallelStrategyExecutor buildParallelExecutor(ParallelStrategyEnum parallelStrategyEnum) { + if (ObjUtil.isNull(parallelStrategyEnum)) return buildParallelExecutor(); + return getParallelStrategyExecutor(parallelStrategyEnum); + } + + /** + * 默认需完成所有任务 + * @return + */ + public ParallelStrategyExecutor buildParallelExecutor() { + return buildParallelExecutor(ParallelStrategyEnum.ALL); + } + + public void clearStrategyExecutorMap() { + if (MapUtil.isNotEmpty(strategyExecutorMap)) { + strategyExecutorMap.clear(); + } + } + +} diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/flow/parallel/strategy/SpecifyParallelExecutor.java b/liteflow-core/src/main/java/com/yomahub/liteflow/flow/parallel/strategy/SpecifyParallelExecutor.java new file mode 100644 index 000000000..f763eb7d6 --- /dev/null +++ b/liteflow-core/src/main/java/com/yomahub/liteflow/flow/parallel/strategy/SpecifyParallelExecutor.java @@ -0,0 +1,78 @@ +package com.yomahub.liteflow.flow.parallel.strategy; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.ObjUtil; +import com.yomahub.liteflow.flow.element.Executable; +import com.yomahub.liteflow.flow.element.condition.FinallyCondition; +import com.yomahub.liteflow.flow.element.condition.PreCondition; +import com.yomahub.liteflow.flow.element.condition.WhenCondition; +import com.yomahub.liteflow.flow.parallel.WhenFutureObj; +import com.yomahub.liteflow.thread.ExecutorHelper; + +import java.util.List; +import java.util.Map; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ExecutorService; +import java.util.stream.Collectors; + +/** + * 完成指定任务执行器,使用 ID 进行比较 + * + * @author luo yi + * @since 2.11.0 + */ +public class SpecifyParallelExecutor extends ParallelStrategyExecutor { + + @Override + public void execute(WhenCondition whenCondition, Integer slotIndex) throws Exception { + + String currChainName = whenCondition.getCurrChainId(); + + this.setWhenConditionParams(whenCondition); + + // 此方法其实只会初始化一次Executor,不会每次都会初始化。Executor是唯一的 + ExecutorService parallelExecutor = ExecutorHelper.loadInstance().buildWhenExecutor(whenCondition.getThreadExecutorClass()); + + // 过滤指定 ID 的任务,且该任务只会有一个或者没有 + Map> specifyExecutableMap = whenCondition.getExecutableList() + .stream() + .filter(executable -> !(executable instanceof PreCondition) && !(executable instanceof FinallyCondition)) + .filter(executable -> { + try { + return executable.isAccess(slotIndex); + } catch (Exception e) { + LOG.error("there was an error when executing the when component isAccess", e); + return false; + } + }) + .collect(Collectors.partitioningBy(executable -> whenCondition.getSpecifyId().equals(executable.getId()))); + + CompletableFuture resultCompletableFuture = null; + + // 处理非指定 task + List> completableFutureList = specifyExecutableMap.get(Boolean.FALSE) + .stream() + .map(executable -> wrappedFutureObj(executable, parallelExecutor, whenCondition, currChainName, slotIndex)) + .collect(Collectors.toList()); + + if (specifyExecutableMap.containsKey(Boolean.TRUE) && CollUtil.isNotEmpty(specifyExecutableMap.get(Boolean.TRUE))) { + // 存在 must 指定的 task + CompletableFuture specifyCompletableFuture = wrappedFutureObj(specifyExecutableMap.get(Boolean.TRUE).get(0), parallelExecutor, whenCondition, currChainName, slotIndex); + // 组合所有任务 + completableFutureList.add(specifyCompletableFuture); + // 设置结果 future + resultCompletableFuture = specifyCompletableFuture; + } + + if (ObjUtil.isNull(resultCompletableFuture)) { + LOG.warn("The specified task[{}] was not found, waiting for all tasks to complete by default.", whenCondition.getSpecifyId()); + // 不存在指定任务,则所有任务都执行 + resultCompletableFuture = CompletableFuture.allOf(completableFutureList.toArray(new CompletableFuture[] {})); + } + + // 结果处理 + this.handleResult(whenCondition, slotIndex, completableFutureList, resultCompletableFuture); + + } + +} diff --git a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/asyncNode/AsyncNodeELSpringbootTest.java b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/asyncNode/AsyncNodeELSpringbootTest.java index 30703e603..99f9e1d97 100644 --- a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/asyncNode/AsyncNodeELSpringbootTest.java +++ b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/asyncNode/AsyncNodeELSpringbootTest.java @@ -139,4 +139,40 @@ public class AsyncNodeELSpringbootTest extends BaseTest { Assertions.assertTrue(context.getData("check").toString().startsWith("habc")); } + // 测试 must 关键字 + @Test + public void testAsyncFlow9() throws Exception { + LiteflowResponse response = flowExecutor.execute2Resp("chain9", "it's a base request"); + DefaultContext context = response.getFirstContextBean(); + Assertions.assertTrue(response.isSuccess()); + Assertions.assertTrue(context.getData("check").toString().startsWith("habc")); + } + + // 测试 must 与 ignoreError 关键字,不忽略异常 + @Test + public void testAsyncFlow10() throws Exception { + LiteflowResponse response = flowExecutor.execute2Resp("chain10", "it's a base request"); + DefaultContext context = response.getFirstContextBean(); + Assertions.assertTrue(context.getData("check").toString().startsWith("kg")); + Assertions.assertFalse(response.isSuccess()); + } + + // 测试 must 与 ignoreError 关键字,忽略异常 + @Test + public void testAsyncFlow11() throws Exception { + LiteflowResponse response = flowExecutor.execute2Resp("chain11", "it's a base request"); + DefaultContext context = response.getFirstContextBean(); + Assertions.assertTrue(response.isSuccess()); + Assertions.assertTrue(context.getData("check").toString().startsWith("kgdabc")); + } + + // 测试 must 、 ignoreError 、 id 关键字 + @Test + public void testAsyncFlow12() throws Exception { + LiteflowResponse response = flowExecutor.execute2Resp("chain12", "it's a base request"); + DefaultContext context = response.getFirstContextBean(); + Assertions.assertTrue(response.isSuccess()); + Assertions.assertTrue(context.getData("check").toString().startsWith("akbc")); + } + } diff --git a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/asyncNode/cmp/KCmp.java b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/asyncNode/cmp/KCmp.java new file mode 100644 index 000000000..f4b27d714 --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/asyncNode/cmp/KCmp.java @@ -0,0 +1,27 @@ +package com.yomahub.liteflow.test.asyncNode.cmp; + +import com.yomahub.liteflow.core.NodeComponent; +import com.yomahub.liteflow.slot.DefaultContext; +import org.springframework.stereotype.Component; + +@Component("k") +public class KCmp extends NodeComponent { + + @Override + public void process() throws Exception { + Thread.sleep(200); + DefaultContext context = this.getFirstContextBean(); + synchronized (NodeComponent.class) { + if (context.hasData("check")) { + String str = context.getData("check"); + str += this.getNodeId(); + context.setData("check", str); + } + else { + context.setData("check", this.getNodeId()); + } + } + System.out.println("Kcomp executed!"); + } + +} diff --git a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/asyncNode/cmp/LCmp.java b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/asyncNode/cmp/LCmp.java new file mode 100644 index 000000000..87e08565c --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/asyncNode/cmp/LCmp.java @@ -0,0 +1,15 @@ +package com.yomahub.liteflow.test.asyncNode.cmp; + +import com.yomahub.liteflow.core.NodeComponent; +import org.springframework.stereotype.Component; + +@Component("l") +public class LCmp extends NodeComponent { + + @Override + public void process() throws Exception { + System.out.println("Lcomp executed! Throw exception"); + int i = 1/0; + } + +} diff --git a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/asyncNode/flow.el.xml b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/asyncNode/flow.el.xml index 06373bb2f..e48bf988e 100644 --- a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/asyncNode/flow.el.xml +++ b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/asyncNode/flow.el.xml @@ -46,4 +46,20 @@ THEN(WHEN(d, g, h).any(true), THEN(a, b, c)); + + THEN(WHEN(d, g, h).must("h"), THEN(a, b, c)); + + + + THEN(WHEN(d, g, k, l).must("g").ignoreError(false), THEN(a, b, c)); + + + + THEN(WHEN(d, g, k, l).ignoreError(true).must("d"), THEN(a, b, c)); + + + + THEN(WHEN(d, g, l, a, THEN(k, b).id("z")).ignoreError(true).must("z"), c); + + \ No newline at end of file From 918111dfda9093fb6df5863fa96f6a6dd9a58ee6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9F=A9=E5=8D=8E=E9=94=8B?= <799954772@qq.com> Date: Thu, 14 Sep 2023 11:19:42 +0800 Subject: [PATCH 02/53] =?UTF-8?q?=E3=80=90fix=E3=80=91=E4=BF=AE=E5=A4=8DAp?= =?UTF-8?q?olloParseHelper.java=E4=B8=AD=E8=B0=83=E7=94=A8convert=E5=90=8E?= =?UTF-8?q?=EF=BC=8C=E5=8F=AF=E8=83=BD=E4=BC=9A=E5=87=BA=E7=8E=B0=E7=A9=BA?= =?UTF-8?q?=E6=8C=87=E9=92=88=E7=9A=84=E9=97=AE=E9=A2=98=20=E3=80=90fix?= =?UTF-8?q?=E3=80=91FlowInitHook.java=E6=96=87=E4=BB=B6=E4=B8=AD=EF=BC=8C?= =?UTF-8?q?=E5=B8=B8=E9=87=8F=E5=91=BD=E5=B0=8F=E5=86=99=EF=BC=8C=E4=B8=8D?= =?UTF-8?q?=E7=AC=A6=E5=90=88=E5=B8=B8=E7=94=A8=E8=A7=84=E8=8C=83=EF=BC=8C?= =?UTF-8?q?=E6=94=B9=E4=B8=BA=E4=BA=86=E5=A4=A7=E5=86=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../yomahub/liteflow/core/FlowInitHook.java | 10 +- .../parser/apollo/util/ApolloParseHelper.java | 337 +++++++++--------- 2 files changed, 177 insertions(+), 170 deletions(-) diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/core/FlowInitHook.java b/liteflow-core/src/main/java/com/yomahub/liteflow/core/FlowInitHook.java index 4e4ea12c2..ba1628d62 100644 --- a/liteflow-core/src/main/java/com/yomahub/liteflow/core/FlowInitHook.java +++ b/liteflow-core/src/main/java/com/yomahub/liteflow/core/FlowInitHook.java @@ -14,20 +14,20 @@ import java.util.function.BooleanSupplier; */ public class FlowInitHook { - private static final List supplierList = new ArrayList<>(); + private static final List SUPPLIER_LIST = new ArrayList<>(); public static void executeHook() { - if (CollUtil.isNotEmpty(supplierList)) { - supplierList.forEach(BooleanSupplier::getAsBoolean); + if (CollUtil.isNotEmpty(SUPPLIER_LIST)) { + SUPPLIER_LIST.forEach(BooleanSupplier::getAsBoolean); } } public static void addHook(BooleanSupplier hookSupplier) { - supplierList.add(hookSupplier); + SUPPLIER_LIST.add(hookSupplier); } public static void cleanHook() { - supplierList.clear(); + SUPPLIER_LIST.clear(); } } diff --git a/liteflow-rule-plugin/liteflow-rule-apollo/src/main/java/com/yomahub/liteflow/parser/apollo/util/ApolloParseHelper.java b/liteflow-rule-plugin/liteflow-rule-apollo/src/main/java/com/yomahub/liteflow/parser/apollo/util/ApolloParseHelper.java index 468704be1..3a27c8e7e 100644 --- a/liteflow-rule-plugin/liteflow-rule-apollo/src/main/java/com/yomahub/liteflow/parser/apollo/util/ApolloParseHelper.java +++ b/liteflow-rule-plugin/liteflow-rule-apollo/src/main/java/com/yomahub/liteflow/parser/apollo/util/ApolloParseHelper.java @@ -24,215 +24,222 @@ import java.util.Objects; import java.util.Set; import java.util.stream.Collectors; +import static com.ctrip.framework.apollo.enums.PropertyChangeType.DELETED; + /** * @author zhanghua * @since 2.9.5 */ public class ApolloParseHelper { - private static final Logger LOG = LoggerFactory.getLogger(ApolloParseHelper.class); + private static final Logger LOG = LoggerFactory.getLogger(ApolloParseHelper.class); - private final String CHAIN_XML_PATTERN = "{}"; + private final String CHAIN_XML_PATTERN = "{}"; - private final String NODE_XML_PATTERN = "{}"; + private final String NODE_XML_PATTERN = "{}"; - private final String NODE_ITEM_XML_PATTERN = ""; + private final String NODE_ITEM_XML_PATTERN = ""; - private final String XML_PATTERN = "{}{}"; + private final String XML_PATTERN = "{}{}"; - private final ApolloParserConfigVO apolloParserConfigVO; + private final ApolloParserConfigVO apolloParserConfigVO; - private Config chainConfig; + private Config chainConfig; - private Config scriptConfig; + private Config scriptConfig; - public ApolloParseHelper(ApolloParserConfigVO apolloParserConfigVO) { - this.apolloParserConfigVO = apolloParserConfigVO; + public ApolloParseHelper(ApolloParserConfigVO apolloParserConfigVO) { + this.apolloParserConfigVO = apolloParserConfigVO; - try { - try { - // 这里本身对于程序运行来说没有什么意义,拿到的永远是null - // 其实config对象也没有注入到spring容器中 - // 这里这样写的目的是为了单测中的mockito,当有@MockBean的时候,这里就能拿到了 - this.chainConfig = ContextAwareHolder.loadContextAware().getBean("chainConfig"); - this.scriptConfig = ContextAwareHolder.loadContextAware().getBean("scriptConfig"); - } - catch (Exception ignored) { - } + try { + try { + // 这里本身对于程序运行来说没有什么意义,拿到的永远是null + // 其实config对象也没有注入到spring容器中 + // 这里这样写的目的是为了单测中的mockito,当有@MockBean的时候,这里就能拿到了 + this.chainConfig = ContextAwareHolder.loadContextAware().getBean("chainConfig"); + this.scriptConfig = ContextAwareHolder.loadContextAware().getBean("scriptConfig"); + } catch (Exception ignored) { + } - if (ObjectUtil.isNull(chainConfig)) { - chainConfig = ConfigService.getConfig(apolloParserConfigVO.getChainNamespace()); - String scriptNamespace; - // scriptConfig is optional - if (StrUtil.isNotBlank(scriptNamespace = apolloParserConfigVO.getScriptNamespace())) { - scriptConfig = ConfigService.getConfig(scriptNamespace); - } - } - } - catch (Exception e) { - throw new ApolloException(e.getMessage()); - } - } + if (ObjectUtil.isNull(chainConfig)) { + chainConfig = ConfigService.getConfig(apolloParserConfigVO.getChainNamespace()); + String scriptNamespace; + // scriptConfig is optional + if (StrUtil.isNotBlank(scriptNamespace = apolloParserConfigVO.getScriptNamespace())) { + scriptConfig = ConfigService.getConfig(scriptNamespace); + } + } + } catch (Exception e) { + throw new ApolloException(e.getMessage()); + } + } - public String getContent() { + public String getContent() { - try { - // 1. handle chain - Set propertyNames = chainConfig.getPropertyNames(); - if (CollectionUtil.isEmpty(propertyNames)) { - throw new ApolloException(StrUtil.format("There are no chains in namespace : {}", - apolloParserConfigVO.getChainNamespace())); - } - List chainItemContentList = propertyNames.stream() - .map(item -> StrUtil.format(CHAIN_XML_PATTERN, item, chainConfig.getProperty(item, StrUtil.EMPTY))) - .collect(Collectors.toList()); - // merge all chain content - String chainAllContent = CollUtil.join(chainItemContentList, StrUtil.EMPTY); + try { + // 1. handle chain + Set propertyNames = chainConfig.getPropertyNames(); + if (CollectionUtil.isEmpty(propertyNames)) { + throw new ApolloException(StrUtil.format("There are no chains in namespace : {}", + apolloParserConfigVO.getChainNamespace())); + } + List chainItemContentList = propertyNames.stream() + .map(item -> StrUtil.format(CHAIN_XML_PATTERN, item, chainConfig.getProperty(item, StrUtil.EMPTY))) + .collect(Collectors.toList()); + // merge all chain content + String chainAllContent = CollUtil.join(chainItemContentList, StrUtil.EMPTY); - // 2. handle script if needed - String scriptAllContent = StrUtil.EMPTY; - Set scriptNamespaces; - if (Objects.nonNull(scriptConfig) - && CollectionUtil.isNotEmpty(scriptNamespaces = scriptConfig.getPropertyNames())) { + // 2. handle script if needed + String scriptAllContent = StrUtil.EMPTY; + Set scriptNamespaces; + if (Objects.nonNull(scriptConfig) + && CollectionUtil.isNotEmpty(scriptNamespaces = scriptConfig.getPropertyNames())) { - List scriptItemContentList = scriptNamespaces.stream() - .map(item -> convert(item, scriptConfig.getProperty(item, StrUtil.EMPTY))) - .filter(Objects::nonNull) - .map(item -> StrUtil.format(NODE_ITEM_XML_PATTERN, item.getNodeId(), item.getName(), item.getType(), - item.getScript())) - .collect(Collectors.toList()); + List scriptItemContentList = scriptNamespaces.stream() + .map(item -> convert(item, scriptConfig.getProperty(item, StrUtil.EMPTY))) + .filter(Objects::nonNull) + .map(item -> StrUtil.format(NODE_ITEM_XML_PATTERN, item.getNodeId(), item.getName(), item.getType(), + item.getScript())) + .collect(Collectors.toList()); - scriptAllContent = StrUtil.format(NODE_XML_PATTERN, - CollUtil.join(scriptItemContentList, StrUtil.EMPTY)); - } + scriptAllContent = StrUtil.format(NODE_XML_PATTERN, + CollUtil.join(scriptItemContentList, StrUtil.EMPTY)); + } - return StrUtil.format(XML_PATTERN, scriptAllContent, chainAllContent); - } - catch (Exception e) { - throw new ApolloException(e.getMessage()); - } - } + return StrUtil.format(XML_PATTERN, scriptAllContent, chainAllContent); + } catch (Exception e) { + throw new ApolloException(e.getMessage()); + } + } - /** - * listen apollo config change - */ - public void listenApollo() { + /** + * listen apollo config change + */ + public void listenApollo() { + // chain + chainConfig.addChangeListener(changeEvent -> changeEvent.changedKeys().forEach(changeKey -> { + ConfigChange configChange = changeEvent.getChange(changeKey); + String newValue = configChange.getNewValue(); + PropertyChangeType changeType = configChange.getChangeType(); + switch (changeType) { + case ADDED: + case MODIFIED: + LOG.info("starting reload flow config... {} key={} value={},", changeType.name(), changeKey, + newValue); + LiteFlowChainELBuilder.createChain().setChainId(changeKey).setEL(newValue).build(); + break; + case DELETED: + LOG.info("starting reload flow config... delete key={}", changeKey); + FlowBus.removeChain(changeKey); + break; + default: + } + })); - // chain - chainConfig.addChangeListener(changeEvent -> changeEvent.changedKeys().forEach(changeKey -> { - ConfigChange configChange = changeEvent.getChange(changeKey); - String newValue = configChange.getNewValue(); - PropertyChangeType changeType = configChange.getChangeType(); - switch (changeType) { - case ADDED: - case MODIFIED: - LOG.info("starting reload flow config... {} key={} value={},", changeType.name(), changeKey, - newValue); - LiteFlowChainELBuilder.createChain().setChainId(changeKey).setEL(newValue).build(); - break; - case DELETED: - LOG.info("starting reload flow config... delete key={}", changeKey); - FlowBus.removeChain(changeKey); + if (StrUtil.isNotBlank(apolloParserConfigVO.getScriptNamespace())) { + scriptConfig.addChangeListener(changeEvent -> changeEvent.changedKeys().forEach(changeKey -> { + ConfigChange configChange = changeEvent.getChange(changeKey); + String newValue = configChange.getNewValue(); - } - })); + PropertyChangeType changeType = configChange.getChangeType(); + if (DELETED.equals(changeType)) { + newValue = null; + } + NodeSimpleVO nodeSimpleVO = convert(changeKey, newValue); + if (Objects.isNull(nodeSimpleVO)) { + // key不符合规范的时候,直接忽略 + LOG.error("key={} is not a valid node config, ignore it", changeKey); + return; + } + switch (changeType) { + case ADDED: + case MODIFIED: + LOG.info("starting reload flow config... {} key={} value={},", changeType.name(), changeKey, + newValue); - if (StrUtil.isNotBlank(apolloParserConfigVO.getScriptNamespace())) { - scriptConfig.addChangeListener(changeEvent -> changeEvent.changedKeys().forEach(changeKey -> { - ConfigChange configChange = changeEvent.getChange(changeKey); - String newValue = configChange.getNewValue(); + LiteFlowNodeBuilder.createScriptNode() + .setId(nodeSimpleVO.getNodeId()) + .setType(NodeTypeEnum.getEnumByCode(nodeSimpleVO.getType())) + .setName(nodeSimpleVO.getName()) + .setScript(nodeSimpleVO.getScript()) + .build(); + break; + case DELETED: + LOG.info("starting reload flow config... delete key={}", changeKey); + FlowBus.getNodeMap().remove(nodeSimpleVO.getNodeId()); + break; + default: + } + })); + } + } - PropertyChangeType changeType = configChange.getChangeType(); + private NodeSimpleVO convert(String key, String value) { + // 不需要去理解这串正则,就是一个匹配冒号的 + // 一定得是a:b,或是a:b:c...这种完整类型的字符串的 + List matchItemList = ReUtil.findAllGroup0("(?<=[^:]:)[^:]+|[^:]+(?=:[^:])", key); + if (CollUtil.isEmpty(matchItemList)) { + return null; + } - NodeSimpleVO nodeSimpleVO; - switch (changeType) { - case ADDED: - case MODIFIED: - LOG.info("starting reload flow config... {} key={} value={},", changeType.name(), changeKey, - newValue); - nodeSimpleVO = convert(changeKey, newValue); - LiteFlowNodeBuilder.createScriptNode() - .setId(nodeSimpleVO.getNodeId()) - .setType(NodeTypeEnum.getEnumByCode(nodeSimpleVO.getType())) - .setName(nodeSimpleVO.getName()) - .setScript(nodeSimpleVO.getScript()) - .build(); - break; - case DELETED: - LOG.info("starting reload flow config... delete key={}", changeKey); - nodeSimpleVO = convert(changeKey, null); - FlowBus.getNodeMap().remove(nodeSimpleVO.getNodeId()); - } - })); - } - } + NodeSimpleVO nodeSimpleVO = new NodeSimpleVO(); + if (matchItemList.size() > 1) { + nodeSimpleVO.setNodeId(matchItemList.get(0)); + nodeSimpleVO.setType(matchItemList.get(1)); + } - private NodeSimpleVO convert(String key, String value) { - // 不需要去理解这串正则,就是一个匹配冒号的 - // 一定得是a:b,或是a:b:c...这种完整类型的字符串的 - List matchItemList = ReUtil.findAllGroup0("(?<=[^:]:)[^:]+|[^:]+(?=:[^:])", key); - if (CollUtil.isEmpty(matchItemList)) { - return null; - } + if (matchItemList.size() > 2) { + nodeSimpleVO.setName(matchItemList.get(2)); + } - NodeSimpleVO nodeSimpleVO = new NodeSimpleVO(); - if (matchItemList.size() > 1) { - nodeSimpleVO.setNodeId(matchItemList.get(0)); - nodeSimpleVO.setType(matchItemList.get(1)); - } + // set script + nodeSimpleVO.setScript(value); - if (matchItemList.size() > 2) { - nodeSimpleVO.setName(matchItemList.get(2)); - } + return nodeSimpleVO; + } - // set script - nodeSimpleVO.setScript(value); + private static class NodeSimpleVO { - return nodeSimpleVO; - } + private String nodeId; - private static class NodeSimpleVO { + private String type; - private String nodeId; + private String name = StrUtil.EMPTY; - private String type; + private String script; - private String name = StrUtil.EMPTY; + public String getNodeId() { + return nodeId; + } - private String script; + public void setNodeId(String nodeId) { + this.nodeId = nodeId; + } - public String getNodeId() { - return nodeId; - } + public String getType() { + return type; + } - public void setNodeId(String nodeId) { - this.nodeId = nodeId; - } + public void setType(String type) { + this.type = type; + } - public String getType() { - return type; - } + public String getName() { + return name; + } - public void setType(String type) { - this.type = type; - } + public void setName(String name) { + this.name = name; + } - public String getName() { - return name; - } + public String getScript() { + return script; + } - public void setName(String name) { - this.name = name; - } + public void setScript(String script) { + this.script = script; + } - public String getScript() { - return script; - } - - public void setScript(String script) { - this.script = script; - } - - } + } } From 6eee9ce492d273cd0d8bcfcaef44d47b8bda78b8 Mon Sep 17 00:00:00 2001 From: luoyi <972849752@qq.com> Date: Thu, 14 Sep 2023 21:53:07 +0800 Subject: [PATCH 03/53] =?UTF-8?q?enhancement=20#I7XAIB=20=E8=B0=83?= =?UTF-8?q?=E6=95=B4=E5=8F=82=E6=95=B0=E5=91=BD=E5=90=8D=EF=BC=8C=E5=A2=9E?= =?UTF-8?q?=E5=8A=A0=E6=B3=A8=E9=87=8A=E8=AF=B4=E6=98=8E?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../liteflow/enums/ParallelStrategyEnum.java | 2 +- .../flow/element/condition/WhenCondition.java | 8 ++- .../strategy/AllOfParallelExecutor.java | 10 +-- .../strategy/AnyOfParallelExecutor.java | 10 +-- .../strategy/ParallelStrategyExecutor.java | 63 ++++++++++--------- .../strategy/SpecifyParallelExecutor.java | 25 ++++---- 6 files changed, 64 insertions(+), 54 deletions(-) diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/enums/ParallelStrategyEnum.java b/liteflow-core/src/main/java/com/yomahub/liteflow/enums/ParallelStrategyEnum.java index fc69b634e..09c9af437 100644 --- a/liteflow-core/src/main/java/com/yomahub/liteflow/enums/ParallelStrategyEnum.java +++ b/liteflow-core/src/main/java/com/yomahub/liteflow/enums/ParallelStrategyEnum.java @@ -17,7 +17,7 @@ public enum ParallelStrategyEnum { ALL("allOf", "完成全部任务", AllOfParallelExecutor.class), - SPECIFY("must", "完成指定任务", SpecifyParallelExecutor.class); + SPECIFY("must", "完成指定 ID 任务", SpecifyParallelExecutor.class); private String strategyType; diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/flow/element/condition/WhenCondition.java b/liteflow-core/src/main/java/com/yomahub/liteflow/flow/element/condition/WhenCondition.java index f4d3df662..7422a495e 100644 --- a/liteflow-core/src/main/java/com/yomahub/liteflow/flow/element/condition/WhenCondition.java +++ b/liteflow-core/src/main/java/com/yomahub/liteflow/flow/element/condition/WhenCondition.java @@ -15,6 +15,7 @@ import com.yomahub.liteflow.flow.parallel.strategy.ParallelStrategyExecutor; import com.yomahub.liteflow.flow.parallel.strategy.ParallelStrategyHelper; import com.yomahub.liteflow.log.LFLog; import com.yomahub.liteflow.log.LFLoggerManager; +import com.yomahub.liteflow.thread.ExecutorHelper; import java.util.concurrent.TimeUnit; @@ -59,13 +60,16 @@ public class WhenCondition extends Condition { return ConditionTypeEnum.TYPE_WHEN; } - // 使用线程池执行when并发流程 + // 使用线程池执行 when 并发流程 // 这块涉及到挺多的多线程逻辑,所以注释比较详细,看到这里的童鞋可以仔细阅读 private void executeAsyncCondition(Integer slotIndex) throws Exception { + // 获取并发执行策略 ParallelStrategyExecutor parallelStrategyExecutor = ParallelStrategyHelper.loadInstance().buildParallelExecutor(this.getParallelStrategy()); - // 执行逻辑 + + // 执行并发逻辑 parallelStrategyExecutor.execute(this, slotIndex); + } public boolean isIgnoreError() { diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/flow/parallel/strategy/AllOfParallelExecutor.java b/liteflow-core/src/main/java/com/yomahub/liteflow/flow/parallel/strategy/AllOfParallelExecutor.java index c3d6de2a4..aeb20bca8 100644 --- a/liteflow-core/src/main/java/com/yomahub/liteflow/flow/parallel/strategy/AllOfParallelExecutor.java +++ b/liteflow-core/src/main/java/com/yomahub/liteflow/flow/parallel/strategy/AllOfParallelExecutor.java @@ -17,14 +17,14 @@ public class AllOfParallelExecutor extends ParallelStrategyExecutor { @Override public void execute(WhenCondition whenCondition, Integer slotIndex) throws Exception { - // 获取所有 CompletableFuture - List> completableFutureList = this.getCompletableFutureList(whenCondition, slotIndex); + // 获取所有 CompletableFuture 任务 + List> allTaskList = this.getAllTaskList(whenCondition, slotIndex); - // 把这些 CompletableFuture 通过 anyOf 合成一个 CompletableFuture - CompletableFuture resultCompletableFuture = CompletableFuture.allOf(completableFutureList.toArray(new CompletableFuture[] {})); + // 把这些 CompletableFuture 通过 allOf 合成一个 CompletableFuture,表明完成所有任务 + CompletableFuture specifyTask = CompletableFuture.allOf(allTaskList.toArray(new CompletableFuture[] {})); // 结果处理 - this.handleResult(whenCondition, slotIndex, completableFutureList, resultCompletableFuture); + this.handleTaskResult(whenCondition, slotIndex, allTaskList, specifyTask); } diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/flow/parallel/strategy/AnyOfParallelExecutor.java b/liteflow-core/src/main/java/com/yomahub/liteflow/flow/parallel/strategy/AnyOfParallelExecutor.java index 2115db84e..dce311fda 100644 --- a/liteflow-core/src/main/java/com/yomahub/liteflow/flow/parallel/strategy/AnyOfParallelExecutor.java +++ b/liteflow-core/src/main/java/com/yomahub/liteflow/flow/parallel/strategy/AnyOfParallelExecutor.java @@ -17,14 +17,14 @@ public class AnyOfParallelExecutor extends ParallelStrategyExecutor { @Override public void execute(WhenCondition whenCondition, Integer slotIndex) throws Exception { - // 获取所有 CompletableFuture - List> completableFutureList = this.getCompletableFutureList(whenCondition, slotIndex); + // 获取所有 CompletableFuture 任务 + List> allTaskList = this.getAllTaskList(whenCondition, slotIndex); - // 把这些 CompletableFuture 通过 anyOf 合成一个 CompletableFuture - CompletableFuture resultCompletableFuture = CompletableFuture.anyOf(completableFutureList.toArray(new CompletableFuture[] {})); + // 把这些 CompletableFuture 通过 anyOf 合成一个 CompletableFuture,表明完成任一任务 + CompletableFuture specifyTask = CompletableFuture.anyOf(allTaskList.toArray(new CompletableFuture[] {})); // 结果处理 - this.handleResult(whenCondition, slotIndex, completableFutureList, resultCompletableFuture); + this.handleTaskResult(whenCondition, slotIndex, allTaskList, specifyTask); } diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/flow/parallel/strategy/ParallelStrategyExecutor.java b/liteflow-core/src/main/java/com/yomahub/liteflow/flow/parallel/strategy/ParallelStrategyExecutor.java index 56f8c9ba9..85524f28c 100644 --- a/liteflow-core/src/main/java/com/yomahub/liteflow/flow/parallel/strategy/ParallelStrategyExecutor.java +++ b/liteflow-core/src/main/java/com/yomahub/liteflow/flow/parallel/strategy/ParallelStrategyExecutor.java @@ -2,6 +2,7 @@ package com.yomahub.liteflow.flow.parallel.strategy; import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.StrUtil; +import com.yomahub.liteflow.enums.ParallelStrategyEnum; import com.yomahub.liteflow.exception.WhenExecuteException; import com.yomahub.liteflow.flow.element.Executable; import com.yomahub.liteflow.flow.element.condition.FinallyCondition; @@ -46,6 +47,8 @@ public abstract class ParallelStrategyExecutor { */ protected CompletableFuture wrappedFutureObj(Executable executable, ExecutorService parallelExecutor, WhenCondition whenCondition, String currChainName, Integer slotIndex) { + // 套入 CompletableFutureTimeout 方法进行超时判断,如果超时则用 WhenFutureObj.timeOut 返回超时的对象 + // 第 2 个参数是主要的本体 CompletableFuture,传入了 ParallelSupplier 和线程池对象 return CompletableFutureTimeout.completeOnTimeout( WhenFutureObj.timeOut(executable.getId()), CompletableFuture.supplyAsync(new ParallelSupplier(executable, currChainName, slotIndex), parallelExecutor), @@ -58,7 +61,7 @@ public abstract class ParallelStrategyExecutor { * @param whenCondition */ protected void setWhenConditionParams(WhenCondition whenCondition) { - // 获得liteflow的参数 + // 获得 liteflow 的参数 LiteflowConfig liteflowConfig = LiteflowConfigGetter.get(); if (ObjectUtil.isNull(whenCondition.getMaxWaitTime())) { if (ObjectUtil.isNotNull(liteflowConfig.getWhenMaxWaitSeconds())) { @@ -78,26 +81,25 @@ public abstract class ParallelStrategyExecutor { } /** - * 获取所有任务 + * 获取所有任务 CompletableFuture 集合 * @param whenCondition * @param slotIndex * @return */ - protected List> getCompletableFutureList(WhenCondition whenCondition, Integer slotIndex) { + protected List> getAllTaskList(WhenCondition whenCondition, Integer slotIndex) { + String currChainName = whenCondition.getCurrChainId(); - // 此方法其实只会初始化一次Executor,不会每次都会初始化。Executor是唯一的 + // 此方法其实只会初始化一次 Executor,不会每次都会初始化。Executor是唯一的 ExecutorService parallelExecutor = ExecutorHelper.loadInstance().buildWhenExecutor(whenCondition.getThreadExecutorClass()); - // 设置参数 + // 设置 whenCondition 参数 setWhenConditionParams(whenCondition); - // 这里主要是做了封装CompletableFuture对象,用lumbda表达式做了很多事情,这句代码要仔细理清 - // 1.先进行过滤,前置和后置组件过滤掉,因为在EL Chain处理的时候已经提出来了 - // 2.过滤isAccess为false的情况,因为不过滤这个的话,如果加上了any,那么isAccess为false那就是最快的了 - // 3.根据condition.getNodeList()的集合进行流处理,用map进行把executable对象转换成List> - // 4.在转的过程中,套入CompletableFutureTimeout方法进行超时判断,如果超时则用WhenFutureObj.timeOut返回超时的对象 - // 5.第2个参数是主要的本体CompletableFuture,传入了ParallelSupplier和线程池对象 + // 这里主要是做了封装 CompletableFuture 对象,用 lumbda 表达式做了很多事情,这句代码要仔细理清 + // 1.先进行过滤,前置和后置组件过滤掉,因为在 EL Chain 处理的时候已经提出来了 + // 2.过滤 isAccess 为 false 的情况,因为不过滤这个的话,如果加上了 any,那么 isAccess 为 false 那就是最快的了 + // 3.根据 condition.getNodeList() 的集合进行流处理,用 map 进行把 executable 对象转换成 List> List> completableFutureList = whenCondition.getExecutableList() .stream() .filter(executable -> !(executable instanceof PreCondition) && !(executable instanceof FinallyCondition)) @@ -116,33 +118,36 @@ public abstract class ParallelStrategyExecutor { } /** - * 结果处理 - * @param whenCondition - * @param slotIndex - * @param completableFutureList - * @param resultCompletableFuture + * 任务结果处理 + * @param whenCondition 并行组件对象 + * @param slotIndex 当前 slot 的 index + * @param allTaskList 并行组件中所有任务列表 + * @param specifyTask 指定预先完成的任务,详见 {@link ParallelStrategyEnum} * @throws Exception */ - protected void handleResult(WhenCondition whenCondition, Integer slotIndex, List> completableFutureList, CompletableFuture resultCompletableFuture) throws Exception { + protected void handleTaskResult(WhenCondition whenCondition, Integer slotIndex, List> allTaskList, + CompletableFuture specifyTask) throws Exception { + Slot slot = DataBus.getSlot(slotIndex); // 定义是否中断参数 - // 这里为什么要定义成数组呢,因为后面lambda要用到,根据final不能修改引用的原则,这里用了数组对象 + // 这里为什么要定义成数组呢,因为后面 lambda 要用到,根据 final 不能修改引用的原则,这里用了数组对象 final boolean[] interrupted = { false }; try { - // 进行执行,这句执行完后,就意味着所有的任务要么执行完毕,要么超时返回 - resultCompletableFuture.get(); + // 进行执行,这句执行完后有三种可能,所有任务执行完成、任一任务执行完成、指定的任务执行完成 + specifyTask.get(); } catch (InterruptedException | ExecutionException e) { LOG.error("there was an error when executing the CompletableFuture", e); interrupted[0] = true; } - // 拿到已经完成的CompletableFuture - // 如果any为false,那么所有任务都已经完成 - // 如果any为true,那么这里拿到的是第一个完成的任务 - // 这里过滤和转换一起用lumbda做了 - List allCompletableWhenFutureObjList = completableFutureList.stream().filter(f -> { + // 拿到已经完成的 CompletableFuture 对象 + // 如果 any 为 false,那么所有任务都已经完成 + // 如果 any 为 true,那么这里拿到的是第一个完成的任务 + // 如果为 must,那么这里获取到的就是指定的任务 + // 这里过滤和转换一起用 lambda 做了 + List allCompletableWhenFutureObjList = allTaskList.stream().filter(f -> { // 过滤出已经完成的,没完成的就直接终止 if (f.isDone()) { return true; @@ -159,8 +164,8 @@ public abstract class ParallelStrategyExecutor { } }).collect(Collectors.toList()); - // 判断超时,上面已经拿到了所有已经完成的CompletableFuture - // 那我们只要过滤出超时的CompletableFuture + // 判断超时,上面已经拿到了所有已经完成的 CompletableFuture + // 那我们只要过滤出超时的 CompletableFuture List timeOutWhenFutureObjList = allCompletableWhenFutureObjList.stream() .filter(WhenFutureObj::isTimeout) .collect(Collectors.toList()); @@ -169,7 +174,7 @@ public abstract class ParallelStrategyExecutor { timeOutWhenFutureObjList.forEach(whenFutureObj -> LOG.warn( "executing thread has reached max-wait-seconds, thread canceled.Execute-item: [{}]", whenFutureObj.getExecutorName())); - // 当配置了ignoreError = false,出现interrupted或者!f.get()的情况,将抛出WhenExecuteException + // 当配置了 ignoreError = false,出现 interrupted 或者 !f.get() 的情况,将抛出 WhenExecuteException if (!whenCondition.isIgnoreError()) { if (interrupted[0]) { throw new WhenExecuteException(StrUtil @@ -184,7 +189,7 @@ public abstract class ParallelStrategyExecutor { } } } else if (interrupted[0]) { - // 这里由于配置了ignoreError,所以只打印warn日志 + // 这里由于配置了 ignoreError,所以只打印 warn 日志 LOG.warn("executing when condition timeout , but ignore with errorResume."); } } diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/flow/parallel/strategy/SpecifyParallelExecutor.java b/liteflow-core/src/main/java/com/yomahub/liteflow/flow/parallel/strategy/SpecifyParallelExecutor.java index f763eb7d6..4ade6aa52 100644 --- a/liteflow-core/src/main/java/com/yomahub/liteflow/flow/parallel/strategy/SpecifyParallelExecutor.java +++ b/liteflow-core/src/main/java/com/yomahub/liteflow/flow/parallel/strategy/SpecifyParallelExecutor.java @@ -28,9 +28,10 @@ public class SpecifyParallelExecutor extends ParallelStrategyExecutor { String currChainName = whenCondition.getCurrChainId(); + // 设置 whenCondition 参数 this.setWhenConditionParams(whenCondition); - // 此方法其实只会初始化一次Executor,不会每次都会初始化。Executor是唯一的 + // 此方法其实只会初始化一次Executor,不会每次都会初始化。Executor 是唯一的 ExecutorService parallelExecutor = ExecutorHelper.loadInstance().buildWhenExecutor(whenCondition.getThreadExecutorClass()); // 过滤指定 ID 的任务,且该任务只会有一个或者没有 @@ -47,31 +48,31 @@ public class SpecifyParallelExecutor extends ParallelStrategyExecutor { }) .collect(Collectors.partitioningBy(executable -> whenCondition.getSpecifyId().equals(executable.getId()))); - CompletableFuture resultCompletableFuture = null; + CompletableFuture specifyTask = null; - // 处理非指定 task - List> completableFutureList = specifyExecutableMap.get(Boolean.FALSE) + // 处理非指定 task,封装成 CompletableFuture 对象,最终仍是会组合所有任务到集合中 + List> allTaskList = specifyExecutableMap.get(Boolean.FALSE) .stream() .map(executable -> wrappedFutureObj(executable, parallelExecutor, whenCondition, currChainName, slotIndex)) .collect(Collectors.toList()); - if (specifyExecutableMap.containsKey(Boolean.TRUE) && CollUtil.isNotEmpty(specifyExecutableMap.get(Boolean.TRUE))) { + if (CollUtil.isNotEmpty(specifyExecutableMap.get(Boolean.TRUE))) { // 存在 must 指定的 task CompletableFuture specifyCompletableFuture = wrappedFutureObj(specifyExecutableMap.get(Boolean.TRUE).get(0), parallelExecutor, whenCondition, currChainName, slotIndex); // 组合所有任务 - completableFutureList.add(specifyCompletableFuture); - // 设置结果 future - resultCompletableFuture = specifyCompletableFuture; + allTaskList.add(specifyCompletableFuture); + // 设置指定任务 future 对象 + specifyTask = specifyCompletableFuture; } - if (ObjUtil.isNull(resultCompletableFuture)) { + if (ObjUtil.isNull(specifyTask)) { LOG.warn("The specified task[{}] was not found, waiting for all tasks to complete by default.", whenCondition.getSpecifyId()); - // 不存在指定任务,则所有任务都执行 - resultCompletableFuture = CompletableFuture.allOf(completableFutureList.toArray(new CompletableFuture[] {})); + // 不存在指定任务,则需要等待所有任务都执行完成 + specifyTask = CompletableFuture.allOf(allTaskList.toArray(new CompletableFuture[] {})); } // 结果处理 - this.handleResult(whenCondition, slotIndex, completableFutureList, resultCompletableFuture); + this.handleTaskResult(whenCondition, slotIndex, allTaskList, specifyTask); } From 9fbb615e92a471d876eea2df9ddbd5a0d6fbdc7b Mon Sep 17 00:00:00 2001 From: luoyi <972849752@qq.com> Date: Thu, 14 Sep 2023 22:35:26 +0800 Subject: [PATCH 04/53] =?UTF-8?q?enhancement=20#I7XAIB=20=E7=AE=80?= =?UTF-8?q?=E5=8C=96=20SpecifyParallelExecutor=20=E6=89=A7=E8=A1=8C?= =?UTF-8?q?=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../strategy/SpecifyParallelExecutor.java | 50 +++++++++---------- 1 file changed, 23 insertions(+), 27 deletions(-) diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/flow/parallel/strategy/SpecifyParallelExecutor.java b/liteflow-core/src/main/java/com/yomahub/liteflow/flow/parallel/strategy/SpecifyParallelExecutor.java index 4ade6aa52..9474232d4 100644 --- a/liteflow-core/src/main/java/com/yomahub/liteflow/flow/parallel/strategy/SpecifyParallelExecutor.java +++ b/liteflow-core/src/main/java/com/yomahub/liteflow/flow/parallel/strategy/SpecifyParallelExecutor.java @@ -1,19 +1,16 @@ package com.yomahub.liteflow.flow.parallel.strategy; -import cn.hutool.core.collection.CollUtil; import cn.hutool.core.util.ObjUtil; -import com.yomahub.liteflow.flow.element.Executable; import com.yomahub.liteflow.flow.element.condition.FinallyCondition; import com.yomahub.liteflow.flow.element.condition.PreCondition; import com.yomahub.liteflow.flow.element.condition.WhenCondition; import com.yomahub.liteflow.flow.parallel.WhenFutureObj; import com.yomahub.liteflow.thread.ExecutorHelper; +import java.util.ArrayList; import java.util.List; -import java.util.Map; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutorService; -import java.util.stream.Collectors; /** * 完成指定任务执行器,使用 ID 进行比较 @@ -34,8 +31,14 @@ public class SpecifyParallelExecutor extends ParallelStrategyExecutor { // 此方法其实只会初始化一次Executor,不会每次都会初始化。Executor 是唯一的 ExecutorService parallelExecutor = ExecutorHelper.loadInstance().buildWhenExecutor(whenCondition.getThreadExecutorClass()); - // 过滤指定 ID 的任务,且该任务只会有一个或者没有 - Map> specifyExecutableMap = whenCondition.getExecutableList() + // 指定任务 + final CompletableFuture[] specifyTask = { null }; + + // 所有任务集合 + List> allTaskList = new ArrayList<>(); + + // 遍历 when 所有 node,进行筛选及处理 + whenCondition.getExecutableList() .stream() .filter(executable -> !(executable instanceof PreCondition) && !(executable instanceof FinallyCondition)) .filter(executable -> { @@ -46,33 +49,26 @@ public class SpecifyParallelExecutor extends ParallelStrategyExecutor { return false; } }) - .collect(Collectors.partitioningBy(executable -> whenCondition.getSpecifyId().equals(executable.getId()))); + .forEach(executable -> { + // 处理 task,封装成 CompletableFuture 对象 + CompletableFuture completableFutureTask = wrappedFutureObj(executable, parallelExecutor, whenCondition, currChainName, slotIndex); + // 存在 must 指定 ID 的 task,且该任务只会有一个或者没有 + if (whenCondition.getSpecifyId().equals(executable.getId())) { + // 设置指定任务 future 对象 + specifyTask[0] = completableFutureTask; + } + // 组合所有任务 + allTaskList.add(completableFutureTask); + }); - CompletableFuture specifyTask = null; - - // 处理非指定 task,封装成 CompletableFuture 对象,最终仍是会组合所有任务到集合中 - List> allTaskList = specifyExecutableMap.get(Boolean.FALSE) - .stream() - .map(executable -> wrappedFutureObj(executable, parallelExecutor, whenCondition, currChainName, slotIndex)) - .collect(Collectors.toList()); - - if (CollUtil.isNotEmpty(specifyExecutableMap.get(Boolean.TRUE))) { - // 存在 must 指定的 task - CompletableFuture specifyCompletableFuture = wrappedFutureObj(specifyExecutableMap.get(Boolean.TRUE).get(0), parallelExecutor, whenCondition, currChainName, slotIndex); - // 组合所有任务 - allTaskList.add(specifyCompletableFuture); - // 设置指定任务 future 对象 - specifyTask = specifyCompletableFuture; - } - - if (ObjUtil.isNull(specifyTask)) { + if (ObjUtil.isNull(specifyTask[0])) { LOG.warn("The specified task[{}] was not found, waiting for all tasks to complete by default.", whenCondition.getSpecifyId()); // 不存在指定任务,则需要等待所有任务都执行完成 - specifyTask = CompletableFuture.allOf(allTaskList.toArray(new CompletableFuture[] {})); + specifyTask[0] = CompletableFuture.allOf(allTaskList.toArray(new CompletableFuture[] {})); } // 结果处理 - this.handleTaskResult(whenCondition, slotIndex, allTaskList, specifyTask); + this.handleTaskResult(whenCondition, slotIndex, allTaskList, specifyTask[0]); } From d07768d2310383eee09277216cdddc7ee3ac6997 Mon Sep 17 00:00:00 2001 From: houxinyu Date: Sat, 16 Sep 2023 22:13:50 +0800 Subject: [PATCH 05/53] =?UTF-8?q?=E5=A2=9E=E5=8A=A0SQL=E8=BD=AE=E8=AF=A2ch?= =?UTF-8?q?ain=E9=83=A8=E5=88=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../liteflow-rule-sql/pom.xml | 6 + .../liteflow/parser/sql/SQLXmlELParser.java | 19 ++- .../parser/sql/util/ChainPollingTask.java | 149 ++++++++++++++++++ .../liteflow/parser/sql/util/JDBCHelper.java | 52 +++++- .../liteflow/parser/sql/vo/SQLParserVO.java | 32 ++++ 5 files changed, 253 insertions(+), 5 deletions(-) create mode 100644 liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/util/ChainPollingTask.java diff --git a/liteflow-rule-plugin/liteflow-rule-sql/pom.xml b/liteflow-rule-plugin/liteflow-rule-sql/pom.xml index e4933af70..f725f7cb8 100644 --- a/liteflow-rule-plugin/liteflow-rule-sql/pom.xml +++ b/liteflow-rule-plugin/liteflow-rule-sql/pom.xml @@ -20,5 +20,11 @@ true provided + + + cn.hutool + hutool-crypto + ${hutool-crypto.version} + \ No newline at end of file diff --git a/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/SQLXmlELParser.java b/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/SQLXmlELParser.java index ce3bbe536..6f218de4a 100644 --- a/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/SQLXmlELParser.java +++ b/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/SQLXmlELParser.java @@ -5,6 +5,7 @@ import cn.hutool.core.bean.copier.CopyOptions; import cn.hutool.core.map.MapUtil; import cn.hutool.core.text.StrFormatter; import cn.hutool.core.util.StrUtil; +import com.yomahub.liteflow.core.FlowInitHook; import com.yomahub.liteflow.parser.el.ClassXmlFlowELParser; import com.yomahub.liteflow.parser.sql.exception.ELSQLException; import com.yomahub.liteflow.parser.sql.util.JDBCHelper; @@ -23,6 +24,8 @@ import java.util.Objects; */ public class SQLXmlELParser extends ClassXmlFlowELParser { + private static SQLParserVO sqlParserVO; + private static final String ERROR_MSG_PATTERN = "rule-source-ext-data {} is blank"; private static final String ERROR_COMMON_MSG = "rule-source-ext-data is empty"; @@ -34,7 +37,6 @@ public class SQLXmlELParser extends ClassXmlFlowELParser { LiteflowConfig liteflowConfig = LiteflowConfigGetter.get(); try { - SQLParserVO sqlParserVO = null; if (MapUtil.isNotEmpty((liteflowConfig.getRuleSourceExtDataMap()))) { sqlParserVO = BeanUtil.toBean(liteflowConfig.getRuleSourceExtDataMap(), SQLParserVO.class, CopyOptions.create()); @@ -63,7 +65,20 @@ public class SQLXmlELParser extends ClassXmlFlowELParser { @Override public String parseCustom() { - return JDBCHelper.getInstance().getContent(); + try{ + JDBCHelper jdbcHelper = JDBCHelper.getInstance(); + String content = jdbcHelper.getContent(); + if(sqlParserVO.getIfPolling()) { + FlowInitHook.addHook(() -> { + jdbcHelper.listenSQL(); + return true; + }); + } + return content; + } + catch (Exception ex) { + throw new ELSQLException(ex.getMessage()); + } } /** diff --git a/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/util/ChainPollingTask.java b/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/util/ChainPollingTask.java new file mode 100644 index 000000000..7082ee49c --- /dev/null +++ b/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/util/ChainPollingTask.java @@ -0,0 +1,149 @@ +package com.yomahub.liteflow.parser.sql.util; + +import cn.hutool.core.util.StrUtil; +import com.yomahub.liteflow.builder.el.LiteFlowChainELBuilder; +import com.yomahub.liteflow.flow.FlowBus; +import com.yomahub.liteflow.log.LFLog; +import com.yomahub.liteflow.log.LFLoggerManager; +import com.yomahub.liteflow.parser.sql.exception.ELSQLException; +import com.yomahub.liteflow.parser.sql.vo.SQLParserVO; + +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +/** + * 用于轮询chain的定时任务 + * + * @author hxinyu + * @since 2.11.1 + */ +public class ChainPollingTask implements Runnable { + + private static final String SQL_PATTERN = "SELECT {},{} FROM {} WHERE {}=?"; + + private static final String NEW_CHAIN_PATTERN = "SELECT {} FROM {} WHERE {}=? AND {}=?"; + + private static final String SHA_PATTERN = "SHA1({})"; + + public static Connection conn; + + private SQLParserVO sqlParserVO; + + private Map chainSHAMap; + + private static final Integer FETCH_SIZE_MAX = 1000; + + LFLog LOG = LFLoggerManager.getLogger(ChainPollingTask.class); + + public ChainPollingTask(SQLParserVO sqlParserVO, Map chainSHAMap) { + this.sqlParserVO = sqlParserVO; + this.chainSHAMap = chainSHAMap; + conn = LiteFlowJdbcUtil.getConn(sqlParserVO); + } + + @Override + public void run() { + try{ + PreparedStatement stmt; + ResultSet rs; + String chainTableName = sqlParserVO.getChainTableName(); + String elDataField = sqlParserVO.getElDataField(); + String chainNameField = sqlParserVO.getChainNameField(); + String chainApplicationNameField = sqlParserVO.getChainApplicationNameField(); + String applicationName = sqlParserVO.getApplicationName(); + + String SHAField = StrUtil.format(SHA_PATTERN, elDataField); + String sqlCmd = StrUtil.format(SQL_PATTERN, chainNameField, SHAField, chainTableName, + chainApplicationNameField); + stmt = conn.prepareStatement(sqlCmd, ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY); + // 设置游标拉取数量 + stmt.setFetchSize(FETCH_SIZE_MAX); + stmt.setString(1, applicationName); + rs = stmt.executeQuery(); + + Set newChainSet = new HashSet<>(); + + while(rs.next()) { + String chainName = getStringFromResultSet(rs, chainNameField); + String newSHA = getStringFromResultSet(rs, SHAField); + newChainSet.add(chainName); + //如果封装的SHAMap中不存在该chain, 表示该chain为新增 + if(!chainSHAMap.containsKey(chainName)) { + //获取新chain结果 + ResultSet newChainRS = getNewChainRS(elDataField, chainTableName, chainNameField, + chainApplicationNameField, applicationName, chainName); + if(newChainRS.next()) { + String newELData = getStringFromResultSet(newChainRS, elDataField); + //新增chain + LiteFlowChainELBuilder.createChain().setChainId(chainName).setEL(newELData).build(); + LOG.info("starting reload flow config... create key={} new value={},", chainName, newELData); + //加入到shaMap + chainSHAMap.put(chainName, newSHA); + } + } + else if (!StrUtil.equals(newSHA, chainSHAMap.get(chainName))) { + //SHA值发生变化,表示该chain的值已被修改,重新拉取变化的chain + ResultSet newChainRS = getNewChainRS(elDataField, chainTableName, chainNameField, + chainApplicationNameField, applicationName, chainName); + if(newChainRS.next()) { + String newELData = getStringFromResultSet(newChainRS, elDataField); + //修改chain + LiteFlowChainELBuilder.createChain().setChainId(chainName).setEL(newELData).build(); + LOG.info("starting reload flow config... update key={} new value={},", chainName, newELData); + //修改shaMap + chainSHAMap.put(chainName, newSHA); + } + } + //SHA值无变化,表示该chain未改变 + } + + if(chainSHAMap.size() > newChainSet.size()) { + //如果遍历prepareStatement后修改过的SHAMap数量比最新chain总数多, 说明有两种情况: + // 1、删除了chain + // 2、修改了chainName:因为遍历到新的name时会加到SHAMap里,但没有机会删除旧的chain + // 3、上述两者结合 + //在此处遍历chainSHAMap,把不在newChainSet中的chain删除 + for (String chainName : chainSHAMap.keySet()) { + if(!newChainSet.contains(chainName)){ + FlowBus.removeChain(chainName); + LOG.info("starting reload flow config... delete chain={}", chainName); + //修改SHAMap + chainSHAMap.remove(chainName); + } + } + } + + }catch (Exception e) { + LOG.error("[Exception during SQL chain polling] " + e.getMessage(), e); + } + } + + private ResultSet getNewChainRS(String elDataField, String chainTableName, String chainNameField, + String chainApplicationNameField, String applicationName, String chainName) { + ResultSet rs = null; + String sqlCmd = StrUtil.format(NEW_CHAIN_PATTERN, elDataField, chainTableName, + chainNameField, chainApplicationNameField); + try{ + PreparedStatement stmt = conn.prepareStatement(sqlCmd, ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY); + stmt.setString(1, chainName); + stmt.setString(2, applicationName); + rs = stmt.executeQuery(); + }catch (Exception e) { + throw new ELSQLException(e.getMessage()); + } + return rs; + } + + private String getStringFromResultSet(ResultSet rs, String field) throws SQLException { + String data = rs.getString(field); + if (StrUtil.isBlank(data)) { + throw new ELSQLException(StrUtil.format("exist {} field value is empty", field)); + } + return data; + } +} diff --git a/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/util/JDBCHelper.java b/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/util/JDBCHelper.java index 58d374b6e..250242b8f 100644 --- a/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/util/JDBCHelper.java +++ b/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/util/JDBCHelper.java @@ -1,8 +1,11 @@ package com.yomahub.liteflow.parser.sql.util; import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.thread.NamedThreadFactory; +import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.StrUtil; import cn.hutool.core.util.XmlUtil; +import cn.hutool.crypto.digest.DigestUtil; import com.yomahub.liteflow.enums.NodeTypeEnum; import com.yomahub.liteflow.enums.ScriptTypeEnum; import com.yomahub.liteflow.parser.sql.exception.ELSQLException; @@ -12,9 +15,11 @@ import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; -import java.util.ArrayList; -import java.util.List; -import java.util.Objects; +import java.util.*; +import java.util.concurrent.ScheduledThreadPoolExecutor; +import java.util.concurrent.ThreadFactory; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; /** * jdbc 工具类 @@ -48,6 +53,15 @@ public class JDBCHelper { private static JDBCHelper INSTANCE; + //定时任务线程池核心线程数 + private static final int CORE_POOL_SIZE = 2; + + //定时任务线程池 + private static ScheduledThreadPoolExecutor pollExecutor; + + //chain的SHA1加密值 用于轮询时确定elDataField是否变化 + private Map chainSHAMap = new HashMap<>(); + /** * 初始化 INSTANCE */ @@ -58,6 +72,15 @@ public class JDBCHelper { Class.forName(sqlParserVO.getDriverClassName()); } INSTANCE.setSqlParserVO(sqlParserVO); + //创建定时任务线程池 + if (sqlParserVO.getIfPolling() && ObjectUtil.isNull(getPollExecutor())) { + ThreadFactory namedThreadFactory = new NamedThreadFactory("SQL-Polling-", false); + ScheduledThreadPoolExecutor threadPoolExecutor = new ScheduledThreadPoolExecutor( + CORE_POOL_SIZE, + namedThreadFactory, + new ThreadPoolExecutor.DiscardOldestPolicy()); + setPollExecutor(threadPoolExecutor); + } } catch (ClassNotFoundException e) { throw new ELSQLException(e.getMessage()); } @@ -109,6 +132,12 @@ public class JDBCHelper { String chainName = getStringFromResultSet(rs, chainNameField); result.add(StrUtil.format(CHAIN_XML_PATTERN, XmlUtil.escape(chainName), elData)); + + //如果需要轮询 计算该chainData的SHA值 + if(sqlParserVO.getIfPolling()){ + String chainSHA = DigestUtil.sha1Hex(elData); + chainSHAMap.put(chainName, chainSHA); + } } } catch (Exception e) { throw new ELSQLException(e.getMessage()); @@ -129,6 +158,16 @@ public class JDBCHelper { return StrUtil.format(XML_PATTERN, nodesContent, chainsContent); } + /** + * 定时轮询拉取SQL中变化的数据 + */ + public void listenSQL() { + ChainPollingTask chainTask = new ChainPollingTask(sqlParserVO, chainSHAMap); + pollExecutor.scheduleAtFixedRate(chainTask, sqlParserVO.getPollingStartTime().longValue(), + sqlParserVO.getPollingInterval().longValue(), TimeUnit.SECONDS); + } + + /** * 获取脚本节点内容 */ @@ -299,4 +338,11 @@ public class JDBCHelper { this.sqlParserVO = sqlParserVO; } + public static ScheduledThreadPoolExecutor getPollExecutor() { + return pollExecutor; + } + + public static void setPollExecutor(ScheduledThreadPoolExecutor pollExecutor) { + JDBCHelper.pollExecutor = pollExecutor; + } } diff --git a/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/vo/SQLParserVO.java b/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/vo/SQLParserVO.java index b549bafdc..4246b3e2d 100644 --- a/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/vo/SQLParserVO.java +++ b/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/vo/SQLParserVO.java @@ -90,6 +90,15 @@ public class SQLParserVO { */ private String scriptLanguageField; + /*是否开启轮询机制 默认不开启*/ + private Boolean ifPolling = false; + + /*轮询时间间隔(s) 默认60s*/ + private Integer pollingInterval = 60; + + /*规则配置后首次轮询的起始时间 默认为60s*/ + private Integer pollingStartTime = 60; + public String getUrl() { return url; } @@ -225,4 +234,27 @@ public class SQLParserVO { return StrUtil.isBlank(url) && StrUtil.isBlank(username) && StrUtil.isBlank(password) && StrUtil.isBlank(driverClassName); } + public Boolean getIfPolling() { + return ifPolling; + } + + public void setIfPolling(Boolean ifPolling) { + this.ifPolling = ifPolling; + } + + public Integer getPollingInterval() { + return pollingInterval; + } + + public void setPollingInterval(Integer pollingInterval) { + this.pollingInterval = pollingInterval; + } + + public Integer getPollingStartTime() { + return pollingStartTime; + } + + public void setPollingStartTime(Integer pollingStartTime) { + this.pollingStartTime = pollingStartTime; + } } From f67f9a796106a1b24d1026bd141ff32555ea0226 Mon Sep 17 00:00:00 2001 From: houxinyu Date: Sun, 17 Sep 2023 19:23:57 +0800 Subject: [PATCH 06/53] =?UTF-8?q?=E5=A2=9E=E5=8A=A0sql=E6=8F=92=E4=BB=B6?= =?UTF-8?q?=E8=BD=AE=E8=AF=A2=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../parser/sql/util/ChainPollingTask.java | 24 +- .../liteflow/parser/sql/util/JDBCHelper.java | 26 +- .../parser/sql/util/ScriptPollingTask.java | 260 ++++++++++++++++++ .../liteflow/parser/sql/vo/SQLParserVO.java | 4 +- 4 files changed, 300 insertions(+), 14 deletions(-) create mode 100644 liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/util/ScriptPollingTask.java diff --git a/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/util/ChainPollingTask.java b/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/util/ChainPollingTask.java index 7082ee49c..647a7c9de 100644 --- a/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/util/ChainPollingTask.java +++ b/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/util/ChainPollingTask.java @@ -13,6 +13,7 @@ import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.util.HashSet; +import java.util.Iterator; import java.util.Map; import java.util.Set; @@ -49,8 +50,6 @@ public class ChainPollingTask implements Runnable { @Override public void run() { try{ - PreparedStatement stmt; - ResultSet rs; String chainTableName = sqlParserVO.getChainTableName(); String elDataField = sqlParserVO.getElDataField(); String chainNameField = sqlParserVO.getChainNameField(); @@ -60,11 +59,11 @@ public class ChainPollingTask implements Runnable { String SHAField = StrUtil.format(SHA_PATTERN, elDataField); String sqlCmd = StrUtil.format(SQL_PATTERN, chainNameField, SHAField, chainTableName, chainApplicationNameField); - stmt = conn.prepareStatement(sqlCmd, ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY); + PreparedStatement stmt = conn.prepareStatement(sqlCmd, ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY); // 设置游标拉取数量 stmt.setFetchSize(FETCH_SIZE_MAX); stmt.setString(1, applicationName); - rs = stmt.executeQuery(); + ResultSet rs = stmt.executeQuery(); Set newChainSet = new HashSet<>(); @@ -81,7 +80,7 @@ public class ChainPollingTask implements Runnable { String newELData = getStringFromResultSet(newChainRS, elDataField); //新增chain LiteFlowChainELBuilder.createChain().setChainId(chainName).setEL(newELData).build(); - LOG.info("starting reload flow config... create key={} new value={},", chainName, newELData); + LOG.info("starting reload flow config... create chain={} new value={},", chainName, newELData); //加入到shaMap chainSHAMap.put(chainName, newSHA); } @@ -94,7 +93,7 @@ public class ChainPollingTask implements Runnable { String newELData = getStringFromResultSet(newChainRS, elDataField); //修改chain LiteFlowChainELBuilder.createChain().setChainId(chainName).setEL(newELData).build(); - LOG.info("starting reload flow config... update key={} new value={},", chainName, newELData); + LOG.info("starting reload flow config... update chain={} new value={},", chainName, newELData); //修改shaMap chainSHAMap.put(chainName, newSHA); } @@ -108,17 +107,20 @@ public class ChainPollingTask implements Runnable { // 2、修改了chainName:因为遍历到新的name时会加到SHAMap里,但没有机会删除旧的chain // 3、上述两者结合 //在此处遍历chainSHAMap,把不在newChainSet中的chain删除 - for (String chainName : chainSHAMap.keySet()) { - if(!newChainSet.contains(chainName)){ + //这里用iterator是为避免在遍历集合时删除元素导致ConcurrentModificationException + Iterator iterator = chainSHAMap.keySet().iterator(); + while(iterator.hasNext()) { + String chainName = iterator.next(); + if(!newChainSet.contains(chainName)) { FlowBus.removeChain(chainName); LOG.info("starting reload flow config... delete chain={}", chainName); //修改SHAMap - chainSHAMap.remove(chainName); + iterator.remove(); } } } - - }catch (Exception e) { + } + catch (Exception e) { LOG.error("[Exception during SQL chain polling] " + e.getMessage(), e); } } diff --git a/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/util/JDBCHelper.java b/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/util/JDBCHelper.java index 250242b8f..6276ec5db 100644 --- a/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/util/JDBCHelper.java +++ b/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/util/JDBCHelper.java @@ -59,9 +59,12 @@ public class JDBCHelper { //定时任务线程池 private static ScheduledThreadPoolExecutor pollExecutor; - //chain的SHA1加密值 用于轮询时确定elDataField是否变化 + //chain的SHA1加密值 用于轮询时确定chain是否变化 private Map chainSHAMap = new HashMap<>(); + //script的SHA1加密值 用于轮询时确定script是否变化 + private Map scriptSHAMap = new HashMap<>(); + /** * 初始化 INSTANCE */ @@ -162,9 +165,16 @@ public class JDBCHelper { * 定时轮询拉取SQL中变化的数据 */ public void listenSQL() { + //添加轮询chain的定时任务 ChainPollingTask chainTask = new ChainPollingTask(sqlParserVO, chainSHAMap); pollExecutor.scheduleAtFixedRate(chainTask, sqlParserVO.getPollingStartTime().longValue(), sqlParserVO.getPollingInterval().longValue(), TimeUnit.SECONDS); + if (hasScriptData()) { + //添加轮询script的定时任务 + ScriptPollingTask scriptTask = new ScriptPollingTask(sqlParserVO, scriptSHAMap); + pollExecutor.scheduleAtFixedRate(chainTask, sqlParserVO.getPollingStartTime().longValue(), + sqlParserVO.getPollingInterval().longValue(), TimeUnit.SECONDS); + } } @@ -220,6 +230,13 @@ public class JDBCHelper { } result.add(StrUtil.format(NODE_ITEM_XML_PATTERN, XmlUtil.escape(id), XmlUtil.escape(name), type, data)); + + //如果需要轮询 计算该scriptData的SHA值 + if(sqlParserVO.getIfPolling()){ + String scriptKey = StrUtil.join(":", id, name, type); + String scriptSHA = DigestUtil.sha1Hex(data); + scriptSHAMap.put(scriptKey, scriptSHA); + } } } catch (Exception e) { throw new ELSQLException(e.getMessage()); @@ -287,6 +304,13 @@ public class JDBCHelper { result.add(StrUtil.format(NODE_ITEM_WITH_LANGUAGE_XML_PATTERN, XmlUtil.escape(id), XmlUtil.escape(name), type, language, data)); + + //如果需要轮询 计算该scriptData的SHA值 + if(sqlParserVO.getIfPolling()){ + String scriptKey = StrUtil.join(":", id, name, type, language); + String scriptSHA = DigestUtil.sha1Hex(data); + scriptSHAMap.put(scriptKey, scriptSHA); + } } } catch (Exception e) { throw new ELSQLException(e.getMessage()); diff --git a/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/util/ScriptPollingTask.java b/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/util/ScriptPollingTask.java new file mode 100644 index 000000000..5dd40e243 --- /dev/null +++ b/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/util/ScriptPollingTask.java @@ -0,0 +1,260 @@ +package com.yomahub.liteflow.parser.sql.util; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.ReUtil; +import cn.hutool.core.util.StrUtil; +import com.yomahub.liteflow.builder.LiteFlowNodeBuilder; +import com.yomahub.liteflow.enums.NodeTypeEnum; +import com.yomahub.liteflow.flow.FlowBus; +import com.yomahub.liteflow.log.LFLog; +import com.yomahub.liteflow.log.LFLoggerManager; +import com.yomahub.liteflow.parser.sql.exception.ELSQLException; +import com.yomahub.liteflow.parser.sql.vo.SQLParserVO; + +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.*; + +/** + * 用于轮询script的定时任务 + * + * @author hxinyu + * @since 2.11.1 + */ +public class ScriptPollingTask implements Runnable { + + private static final String SQL_PATTERN = "SELECT {},{} FROM {} WHERE {}=?"; + + private static final String NEW_SCRIPT_PATTERN = "SELECT {} FROM {} WHERE {}=? AND {}=?"; + + private static final String CONCAT_PATTERN = "CONCAT_WS(':',{},{},{}) as script_concat"; + + private static final String CONCAT_WITH_LANGUAGE_PATTERN = "CONCAT_WS(':',{},{},{},{}) as script_concat"; + + private static final String SHA_PATTERN = "SHA1({})"; + + private static final String SCRIPT_KEY_FIELD = "script_concat"; + + public static Connection conn; + + private SQLParserVO sqlParserVO; + + private Map scriptSHAMap; + + private static final Integer FETCH_SIZE_MAX = 1000; + + LFLog LOG = LFLoggerManager.getLogger(ScriptPollingTask.class); + + public ScriptPollingTask(SQLParserVO sqlParserVO, Map scriptSHAMap) { + this.sqlParserVO = sqlParserVO; + this.scriptSHAMap = scriptSHAMap; + conn = LiteFlowJdbcUtil.getConn(sqlParserVO); + } + + + @Override + public void run() { + try { + String scriptTableName = sqlParserVO.getScriptTableName(); + String scriptIdField = sqlParserVO.getScriptIdField(); + String scriptDataField = sqlParserVO.getScriptDataField(); + String scriptNameField = sqlParserVO.getScriptNameField(); + String scriptTypeField = sqlParserVO.getScriptTypeField(); + String scriptApplicationNameField = sqlParserVO.getScriptApplicationNameField(); + String applicationName = sqlParserVO.getApplicationName(); + String scriptLanguageField = sqlParserVO.getScriptLanguageField(); + + String SHAField = StrUtil.format(SHA_PATTERN, scriptDataField); + String KeyField; + if (StrUtil.isNotBlank(scriptLanguageField)) { + KeyField = StrUtil.format(CONCAT_WITH_LANGUAGE_PATTERN, scriptIdField, scriptNameField, scriptTypeField, scriptLanguageField); + } else { + KeyField = StrUtil.format(CONCAT_PATTERN, scriptIdField, scriptNameField, scriptTypeField); + } + + String sqlCmd = StrUtil.format(SQL_PATTERN, KeyField, SHAField, scriptTableName, scriptApplicationNameField); + PreparedStatement stmt = conn.prepareStatement(sqlCmd, ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY); + // 设置游标拉取数量 + stmt.setFetchSize(FETCH_SIZE_MAX); + stmt.setString(1, applicationName); + ResultSet rs = stmt.executeQuery(); + + Set newScriptSet = new HashSet<>(); + + while (rs.next()) { + String scriptKey = getStringFromResultSet(rs, SCRIPT_KEY_FIELD); + String newSHA = getStringFromResultSet(rs, SHAField); + newScriptSet.add(scriptKey); + //如果封装的SHAMap中不存在该script 表示该script为新增 + if (!scriptSHAMap.containsKey(scriptKey)) { + //获取新script内容 + NodeSimpleVO scriptVO = convert(scriptKey); + ResultSet newScriptRS = getNewScriptRS(scriptDataField, scriptTableName, scriptIdField, + scriptVO.getNodeId(), scriptApplicationNameField, applicationName); + if(newScriptRS.next()) { + String newScriptData = getStringFromResultSet(newScriptRS, scriptDataField); + //新增script + changeScriptNode(scriptVO, newScriptData); + LOG.info("starting reload flow config... create script={} new value={},", scriptKey, newScriptData); + } + //加入到shaMap + scriptSHAMap.put(scriptKey, newSHA); + } + else if (!StrUtil.equals(newSHA, scriptSHAMap.get(scriptKey))) { + //SHA值发生变化,表示该script的值已被修改,重新拉取变化的script + //获取新script内容 + NodeSimpleVO scriptVO = convert(scriptKey); + ResultSet newScriptRS = getNewScriptRS(scriptDataField, scriptTableName, scriptIdField, + scriptVO.getNodeId(), scriptApplicationNameField, applicationName); + if(newScriptRS.next()) { + String newScriptData = getStringFromResultSet(newScriptRS, scriptDataField); + //修改script + changeScriptNode(scriptVO, newScriptData); + LOG.info("starting reload flow config... update scriptId={} new value={},", scriptVO.getNodeId(), newScriptData); + } + //修改shaMap + scriptSHAMap.put(scriptKey, newSHA); + } + //SHA值无变化,表示该chain未改变 + } + + if(scriptSHAMap.size() > newScriptSet.size()) { + //如果遍历prepareStatement后修改过的SHAMap数量比最新script总数多, 说明有两种情况: + // 1、删除了script + // 2、修改了script的id/name/type:因为遍历到新的script_key时会加到SHAMap里,但没有机会删除旧的script + // 3、上述两者结合 + //在此处遍历scriptSHAMap,把不在newScriptSet中的script删除 + //这里用iterator是为避免在遍历集合时删除元素导致ConcurrentModificationException + Iterator iterator = scriptSHAMap.keySet().iterator(); + while(iterator.hasNext()){ + String scriptKey = iterator.next(); + if (!newScriptSet.contains(scriptKey)) { + NodeSimpleVO scriptVO = convert(scriptKey); + //删除script + FlowBus.getNodeMap().remove(scriptVO.getNodeId()); + LOG.info("starting reload flow config... delete script={}", scriptKey); + //修改SHAMap + iterator.remove(); + } + } + } + + } catch (Exception e) { + LOG.error("[Exception during SQL script polling] " + e.getMessage(), e); + } + } + + private ResultSet getNewScriptRS(String scriptDataField, String scriptTableName, String scriptIdField, + String scriptId, String scriptApplicationNameField, String applicationName) { + ResultSet rs = null; + String sqlCmd = StrUtil.format(NEW_SCRIPT_PATTERN, scriptDataField, scriptTableName, + scriptIdField, scriptApplicationNameField); + try{ + PreparedStatement stmt = conn.prepareStatement(sqlCmd, ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY); + stmt.setString(1, scriptId); + stmt.setString(2, applicationName); + rs = stmt.executeQuery(); + }catch (Exception e) { + throw new ELSQLException(e.getMessage()); + } + return rs; + } + + private String getStringFromResultSet(ResultSet rs, String field) throws SQLException { + String data = rs.getString(field); + if (StrUtil.isBlank(data)) { + throw new ELSQLException(StrUtil.format("exist {} field value is empty", field)); + } + return data; + } + + /*script节点的修改/添加*/ + private void changeScriptNode(NodeSimpleVO nodeSimpleVO, String newValue) { + // 有语言类型 + if (StrUtil.isNotBlank(nodeSimpleVO.getLanguage())) { + LiteFlowNodeBuilder.createScriptNode() + .setId(nodeSimpleVO.getNodeId()) + .setType(NodeTypeEnum.getEnumByCode(nodeSimpleVO.getType())) + .setName(nodeSimpleVO.getName()) + .setScript(newValue) + .setLanguage(nodeSimpleVO.getLanguage()) + .build(); + } + // 没有语言类型 + else { + LiteFlowNodeBuilder.createScriptNode() + .setId(nodeSimpleVO.getNodeId()) + .setType(NodeTypeEnum.getEnumByCode(nodeSimpleVO.getType())) + .setName(nodeSimpleVO.getName()) + .setScript(newValue) + .build(); + } + } + + private NodeSimpleVO convert(String scriptKey){ + List matchItemList = ReUtil.findAllGroup0("(?<=[^:]:)[^:]+|[^:]+(?=:[^:])", scriptKey); + if (CollUtil.isEmpty(matchItemList)) { + return null; + } + NodeSimpleVO nodeSimpleVO = new NodeSimpleVO(); + if (matchItemList.size() > 1) { + nodeSimpleVO.setNodeId(matchItemList.get(0)); + nodeSimpleVO.setType(matchItemList.get(1)); + } + + if (matchItemList.size() > 2) { + nodeSimpleVO.setName(matchItemList.get(2)); + } + + if (matchItemList.size() > 3) { + nodeSimpleVO.setLanguage(matchItemList.get(3)); + } + + return nodeSimpleVO; + } + + class NodeSimpleVO { + + private String nodeId; + + private String type; + + private String name = StrUtil.EMPTY; + + private String language; + + public String getNodeId() { + return nodeId; + } + + public void setNodeId(String nodeId) { + this.nodeId = nodeId; + } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getLanguage() { + return language; + } + + public void setLanguage(String language) { + this.language = language; + } + } +} diff --git a/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/vo/SQLParserVO.java b/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/vo/SQLParserVO.java index 4246b3e2d..b2f9f3c16 100644 --- a/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/vo/SQLParserVO.java +++ b/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/vo/SQLParserVO.java @@ -93,8 +93,8 @@ public class SQLParserVO { /*是否开启轮询机制 默认不开启*/ private Boolean ifPolling = false; - /*轮询时间间隔(s) 默认60s*/ - private Integer pollingInterval = 60; + /*轮询时间间隔(s) 默认120s*/ + private Integer pollingInterval = 120; /*规则配置后首次轮询的起始时间 默认为60s*/ private Integer pollingStartTime = 60; From 75de390d852a5acd149fbc2e384b38e770060f69 Mon Sep 17 00:00:00 2001 From: houxinyu Date: Mon, 18 Sep 2023 00:36:06 +0800 Subject: [PATCH 07/53] add test --- .../liteflow/parser/sql/vo/SQLParserVO.java | 2 +- .../.gitignore | 33 +++++++++ .../pom.xml | 68 +++++++++++++++++++ .../com/yomahub/liteflow/test/BaseTest.java | 27 ++++++++ .../yomahub/liteflow/test/sql/cmp/ACmp.java | 22 ++++++ .../yomahub/liteflow/test/sql/cmp/BCmp.java | 22 ++++++ .../yomahub/liteflow/test/sql/cmp/CCmp.java | 22 ++++++ .../application-polling-xml.properties | 0 8 files changed, 195 insertions(+), 1 deletion(-) create mode 100644 liteflow-testcase-el/liteflow-testcase-el-sql-springboot-polling/.gitignore create mode 100644 liteflow-testcase-el/liteflow-testcase-el-sql-springboot-polling/pom.xml create mode 100644 liteflow-testcase-el/liteflow-testcase-el-sql-springboot-polling/src/test/java/com/yomahub/liteflow/test/BaseTest.java create mode 100644 liteflow-testcase-el/liteflow-testcase-el-sql-springboot-polling/src/test/java/com/yomahub/liteflow/test/sql/cmp/ACmp.java create mode 100644 liteflow-testcase-el/liteflow-testcase-el-sql-springboot-polling/src/test/java/com/yomahub/liteflow/test/sql/cmp/BCmp.java create mode 100644 liteflow-testcase-el/liteflow-testcase-el-sql-springboot-polling/src/test/java/com/yomahub/liteflow/test/sql/cmp/CCmp.java create mode 100644 liteflow-testcase-el/liteflow-testcase-el-sql-springboot-polling/src/test/resources/application-polling-xml.properties diff --git a/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/vo/SQLParserVO.java b/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/vo/SQLParserVO.java index b2f9f3c16..e1479025e 100644 --- a/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/vo/SQLParserVO.java +++ b/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/vo/SQLParserVO.java @@ -90,7 +90,7 @@ public class SQLParserVO { */ private String scriptLanguageField; - /*是否开启轮询机制 默认不开启*/ + /*轮询机制是否开启 默认不开启*/ private Boolean ifPolling = false; /*轮询时间间隔(s) 默认120s*/ diff --git a/liteflow-testcase-el/liteflow-testcase-el-sql-springboot-polling/.gitignore b/liteflow-testcase-el/liteflow-testcase-el-sql-springboot-polling/.gitignore new file mode 100644 index 000000000..549e00a2a --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-sql-springboot-polling/.gitignore @@ -0,0 +1,33 @@ +HELP.md +target/ +!.mvn/wrapper/maven-wrapper.jar +!**/src/main/**/target/ +!**/src/test/**/target/ + +### STS ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache + +### IntelliJ IDEA ### +.idea +*.iws +*.iml +*.ipr + +### NetBeans ### +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ +build/ +!**/src/main/**/build/ +!**/src/test/**/build/ + +### VS Code ### +.vscode/ diff --git a/liteflow-testcase-el/liteflow-testcase-el-sql-springboot-polling/pom.xml b/liteflow-testcase-el/liteflow-testcase-el-sql-springboot-polling/pom.xml new file mode 100644 index 000000000..334c00ab4 --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-sql-springboot-polling/pom.xml @@ -0,0 +1,68 @@ + + + + liteflow-testcase-el + com.yomahub + ${revision} + ../pom.xml + + 4.0.0 + + liteflow-testcase-el-sql-springboot-polling + + + 2.1.214 + 2.6.8 + + + + + com.yomahub + liteflow-spring-boot-starter + ${revision} + + + + com.yomahub + liteflow-rule-sql + ${revision} + test + + + + org.springframework.boot + spring-boot-starter-test + + + + org.springframework.boot + spring-boot-starter-data-jpa + ${jpa.version} + test + + + + com.h2database + h2 + ${h2.version} + test + + + + com.yomahub + liteflow-script-groovy + ${revision} + test + + + + com.yomahub + liteflow-script-graaljs + ${revision} + test + + + + diff --git a/liteflow-testcase-el/liteflow-testcase-el-sql-springboot-polling/src/test/java/com/yomahub/liteflow/test/BaseTest.java b/liteflow-testcase-el/liteflow-testcase-el-sql-springboot-polling/src/test/java/com/yomahub/liteflow/test/BaseTest.java new file mode 100644 index 000000000..a06c46f17 --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-sql-springboot-polling/src/test/java/com/yomahub/liteflow/test/BaseTest.java @@ -0,0 +1,27 @@ +package com.yomahub.liteflow.test; + +import com.yomahub.liteflow.core.FlowInitHook; +import com.yomahub.liteflow.flow.FlowBus; +import com.yomahub.liteflow.property.LiteflowConfigGetter; +import com.yomahub.liteflow.spi.holder.SpiFactoryCleaner; +import com.yomahub.liteflow.spring.ComponentScanner; +import com.yomahub.liteflow.thread.ExecutorHelper; +import org.junit.jupiter.api.AfterAll; + +/** + * @author hxinyu + * @since 2.11.1 + */ +public class BaseTest { + + @AfterAll + public static void cleanScanCache() { + ComponentScanner.cleanCache(); + FlowBus.cleanCache(); + ExecutorHelper.loadInstance().clearExecutorServiceMap(); + SpiFactoryCleaner.clean(); + LiteflowConfigGetter.clean(); + FlowInitHook.cleanHook(); + } + +} \ No newline at end of file diff --git a/liteflow-testcase-el/liteflow-testcase-el-sql-springboot-polling/src/test/java/com/yomahub/liteflow/test/sql/cmp/ACmp.java b/liteflow-testcase-el/liteflow-testcase-el-sql-springboot-polling/src/test/java/com/yomahub/liteflow/test/sql/cmp/ACmp.java new file mode 100644 index 000000000..11ffb1a7c --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-sql-springboot-polling/src/test/java/com/yomahub/liteflow/test/sql/cmp/ACmp.java @@ -0,0 +1,22 @@ +/** + *

Title: liteflow

+ *

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

+ * + * @author Bryan.Zhang + * @email weenyc31@163.com + * @Date 2020/4/1 + */ +package com.yomahub.liteflow.test.sql.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!"); + } + +} \ No newline at end of file diff --git a/liteflow-testcase-el/liteflow-testcase-el-sql-springboot-polling/src/test/java/com/yomahub/liteflow/test/sql/cmp/BCmp.java b/liteflow-testcase-el/liteflow-testcase-el-sql-springboot-polling/src/test/java/com/yomahub/liteflow/test/sql/cmp/BCmp.java new file mode 100644 index 000000000..9601ee2cf --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-sql-springboot-polling/src/test/java/com/yomahub/liteflow/test/sql/cmp/BCmp.java @@ -0,0 +1,22 @@ +/** + *

Title: liteflow

+ *

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

+ * + * @author Bryan.Zhang + * @email weenyc31@163.com + * @Date 2020/4/1 + */ +package com.yomahub.liteflow.test.sql.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-sql-springboot-polling/src/test/java/com/yomahub/liteflow/test/sql/cmp/CCmp.java b/liteflow-testcase-el/liteflow-testcase-el-sql-springboot-polling/src/test/java/com/yomahub/liteflow/test/sql/cmp/CCmp.java new file mode 100644 index 000000000..2274a153e --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-sql-springboot-polling/src/test/java/com/yomahub/liteflow/test/sql/cmp/CCmp.java @@ -0,0 +1,22 @@ +/** + *

Title: liteflow

+ *

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

+ * + * @author Bryan.Zhang + * @email weenyc31@163.com + * @Date 2020/4/1 + */ +package com.yomahub.liteflow.test.sql.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!"); + } + +} \ No newline at end of file diff --git a/liteflow-testcase-el/liteflow-testcase-el-sql-springboot-polling/src/test/resources/application-polling-xml.properties b/liteflow-testcase-el/liteflow-testcase-el-sql-springboot-polling/src/test/resources/application-polling-xml.properties new file mode 100644 index 000000000..e69de29bb From d7c6383b09d5aecc8b22c33385b247a8c7d56138 Mon Sep 17 00:00:00 2001 From: luoyi <972849752@qq.com> Date: Mon, 18 Sep 2023 20:58:25 +0800 Subject: [PATCH 08/53] =?UTF-8?q?enhancement=20#I7XAIB=20=E8=B0=83?= =?UTF-8?q?=E6=95=B4=20When=20=E4=BB=BB=E5=8A=A1=E5=91=BD=E5=90=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../flow/parallel/strategy/AllOfParallelExecutor.java | 6 +++--- .../flow/parallel/strategy/AnyOfParallelExecutor.java | 6 +++--- .../flow/parallel/strategy/ParallelStrategyExecutor.java | 8 ++++---- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/flow/parallel/strategy/AllOfParallelExecutor.java b/liteflow-core/src/main/java/com/yomahub/liteflow/flow/parallel/strategy/AllOfParallelExecutor.java index aeb20bca8..313e02d4d 100644 --- a/liteflow-core/src/main/java/com/yomahub/liteflow/flow/parallel/strategy/AllOfParallelExecutor.java +++ b/liteflow-core/src/main/java/com/yomahub/liteflow/flow/parallel/strategy/AllOfParallelExecutor.java @@ -18,13 +18,13 @@ public class AllOfParallelExecutor extends ParallelStrategyExecutor { public void execute(WhenCondition whenCondition, Integer slotIndex) throws Exception { // 获取所有 CompletableFuture 任务 - List> allTaskList = this.getAllTaskList(whenCondition, slotIndex); + List> whenAllTaskList = this.getWhenAllTaskList(whenCondition, slotIndex); // 把这些 CompletableFuture 通过 allOf 合成一个 CompletableFuture,表明完成所有任务 - CompletableFuture specifyTask = CompletableFuture.allOf(allTaskList.toArray(new CompletableFuture[] {})); + CompletableFuture specifyTask = CompletableFuture.allOf(whenAllTaskList.toArray(new CompletableFuture[] {})); // 结果处理 - this.handleTaskResult(whenCondition, slotIndex, allTaskList, specifyTask); + this.handleTaskResult(whenCondition, slotIndex, whenAllTaskList, specifyTask); } diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/flow/parallel/strategy/AnyOfParallelExecutor.java b/liteflow-core/src/main/java/com/yomahub/liteflow/flow/parallel/strategy/AnyOfParallelExecutor.java index dce311fda..02fcc4646 100644 --- a/liteflow-core/src/main/java/com/yomahub/liteflow/flow/parallel/strategy/AnyOfParallelExecutor.java +++ b/liteflow-core/src/main/java/com/yomahub/liteflow/flow/parallel/strategy/AnyOfParallelExecutor.java @@ -18,13 +18,13 @@ public class AnyOfParallelExecutor extends ParallelStrategyExecutor { public void execute(WhenCondition whenCondition, Integer slotIndex) throws Exception { // 获取所有 CompletableFuture 任务 - List> allTaskList = this.getAllTaskList(whenCondition, slotIndex); + List> whenAllTaskList = this.getWhenAllTaskList(whenCondition, slotIndex); // 把这些 CompletableFuture 通过 anyOf 合成一个 CompletableFuture,表明完成任一任务 - CompletableFuture specifyTask = CompletableFuture.anyOf(allTaskList.toArray(new CompletableFuture[] {})); + CompletableFuture specifyTask = CompletableFuture.anyOf(whenAllTaskList.toArray(new CompletableFuture[] {})); // 结果处理 - this.handleTaskResult(whenCondition, slotIndex, allTaskList, specifyTask); + this.handleTaskResult(whenCondition, slotIndex, whenAllTaskList, specifyTask); } diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/flow/parallel/strategy/ParallelStrategyExecutor.java b/liteflow-core/src/main/java/com/yomahub/liteflow/flow/parallel/strategy/ParallelStrategyExecutor.java index 85524f28c..95adb04ee 100644 --- a/liteflow-core/src/main/java/com/yomahub/liteflow/flow/parallel/strategy/ParallelStrategyExecutor.java +++ b/liteflow-core/src/main/java/com/yomahub/liteflow/flow/parallel/strategy/ParallelStrategyExecutor.java @@ -86,7 +86,7 @@ public abstract class ParallelStrategyExecutor { * @param slotIndex * @return */ - protected List> getAllTaskList(WhenCondition whenCondition, Integer slotIndex) { + protected List> getWhenAllTaskList(WhenCondition whenCondition, Integer slotIndex) { String currChainName = whenCondition.getCurrChainId(); @@ -121,11 +121,11 @@ public abstract class ParallelStrategyExecutor { * 任务结果处理 * @param whenCondition 并行组件对象 * @param slotIndex 当前 slot 的 index - * @param allTaskList 并行组件中所有任务列表 + * @param whenAllTaskList 并行组件中所有任务列表 * @param specifyTask 指定预先完成的任务,详见 {@link ParallelStrategyEnum} * @throws Exception */ - protected void handleTaskResult(WhenCondition whenCondition, Integer slotIndex, List> allTaskList, + protected void handleTaskResult(WhenCondition whenCondition, Integer slotIndex, List> whenAllTaskList, CompletableFuture specifyTask) throws Exception { Slot slot = DataBus.getSlot(slotIndex); @@ -147,7 +147,7 @@ public abstract class ParallelStrategyExecutor { // 如果 any 为 true,那么这里拿到的是第一个完成的任务 // 如果为 must,那么这里获取到的就是指定的任务 // 这里过滤和转换一起用 lambda 做了 - List allCompletableWhenFutureObjList = allTaskList.stream().filter(f -> { + List allCompletableWhenFutureObjList = whenAllTaskList.stream().filter(f -> { // 过滤出已经完成的,没完成的就直接终止 if (f.isDone()) { return true; From 9ff47e902c1fd1f7d6fe75ecc59ae2dcda056a41 Mon Sep 17 00:00:00 2001 From: houxinyu Date: Wed, 20 Sep 2023 13:54:06 +0800 Subject: [PATCH 09/53] =?UTF-8?q?=E5=A2=9E=E5=8A=A0SQL=E8=BD=AE=E8=AF=A2?= =?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 --- .../parser/sql/util/ChainPollingTask.java | 17 +- .../liteflow/parser/sql/util/JDBCHelper.java | 6 +- .../parser/sql/util/ScriptPollingTask.java | 21 +- .../SQLWithXmlELSpringbootPollingTest.java | 181 ++++++++++++++++++ .../resources/application-poll-xml.properties | 29 +++ .../application-polling-xml.properties | 0 .../src/test/resources/sql/data.sql | 14 ++ .../src/test/resources/sql/schema.sql | 20 ++ 8 files changed, 275 insertions(+), 13 deletions(-) create mode 100644 liteflow-testcase-el/liteflow-testcase-el-sql-springboot-polling/src/test/java/com/yomahub/liteflow/test/sql/SQLWithXmlELSpringbootPollingTest.java create mode 100644 liteflow-testcase-el/liteflow-testcase-el-sql-springboot-polling/src/test/resources/application-poll-xml.properties delete mode 100644 liteflow-testcase-el/liteflow-testcase-el-sql-springboot-polling/src/test/resources/application-polling-xml.properties create mode 100644 liteflow-testcase-el/liteflow-testcase-el-sql-springboot-polling/src/test/resources/sql/data.sql create mode 100644 liteflow-testcase-el/liteflow-testcase-el-sql-springboot-polling/src/test/resources/sql/schema.sql diff --git a/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/util/ChainPollingTask.java b/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/util/ChainPollingTask.java index 647a7c9de..cac3bf033 100644 --- a/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/util/ChainPollingTask.java +++ b/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/util/ChainPollingTask.java @@ -29,7 +29,11 @@ public class ChainPollingTask implements Runnable { private static final String NEW_CHAIN_PATTERN = "SELECT {} FROM {} WHERE {}=? AND {}=?"; - private static final String SHA_PATTERN = "SHA1({})"; + private static final String SHA_PATTERN = "SHA1({}) AS SHA1"; + + private static final String SHA_PATTERN_FOR_H2 = "RAWTOHEX(HASH('SHA-1', {})) AS SHA1"; + + private static final String SHA_FIELD_NAME = "SHA1"; public static Connection conn; @@ -57,6 +61,11 @@ public class ChainPollingTask implements Runnable { String applicationName = sqlParserVO.getApplicationName(); String SHAField = StrUtil.format(SHA_PATTERN, elDataField); + //h2数据库计算SHA的函数与MySQL不同 + if(StrUtil.equals(sqlParserVO.getDriverClassName(), "org.h2.Driver")){ + SHAField = StrUtil.format(SHA_PATTERN_FOR_H2, elDataField); + } + String sqlCmd = StrUtil.format(SQL_PATTERN, chainNameField, SHAField, chainTableName, chainApplicationNameField); PreparedStatement stmt = conn.prepareStatement(sqlCmd, ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY); @@ -69,7 +78,7 @@ public class ChainPollingTask implements Runnable { while(rs.next()) { String chainName = getStringFromResultSet(rs, chainNameField); - String newSHA = getStringFromResultSet(rs, SHAField); + String newSHA = getStringFromResultSet(rs, SHA_FIELD_NAME); newChainSet.add(chainName); //如果封装的SHAMap中不存在该chain, 表示该chain为新增 if(!chainSHAMap.containsKey(chainName)) { @@ -80,7 +89,7 @@ public class ChainPollingTask implements Runnable { String newELData = getStringFromResultSet(newChainRS, elDataField); //新增chain LiteFlowChainELBuilder.createChain().setChainId(chainName).setEL(newELData).build(); - LOG.info("starting reload flow config... create chain={} new value={},", chainName, newELData); + LOG.info("starting reload flow config... create chain={}, new value={},", chainName, newELData); //加入到shaMap chainSHAMap.put(chainName, newSHA); } @@ -93,7 +102,7 @@ public class ChainPollingTask implements Runnable { String newELData = getStringFromResultSet(newChainRS, elDataField); //修改chain LiteFlowChainELBuilder.createChain().setChainId(chainName).setEL(newELData).build(); - LOG.info("starting reload flow config... update chain={} new value={},", chainName, newELData); + LOG.info("starting reload flow config... update chain={}, new value={},", chainName, newELData); //修改shaMap chainSHAMap.put(chainName, newSHA); } diff --git a/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/util/JDBCHelper.java b/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/util/JDBCHelper.java index 6276ec5db..5b9c2083b 100644 --- a/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/util/JDBCHelper.java +++ b/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/util/JDBCHelper.java @@ -172,7 +172,7 @@ public class JDBCHelper { if (hasScriptData()) { //添加轮询script的定时任务 ScriptPollingTask scriptTask = new ScriptPollingTask(sqlParserVO, scriptSHAMap); - pollExecutor.scheduleAtFixedRate(chainTask, sqlParserVO.getPollingStartTime().longValue(), + pollExecutor.scheduleAtFixedRate(scriptTask, sqlParserVO.getPollingStartTime().longValue(), sqlParserVO.getPollingInterval().longValue(), TimeUnit.SECONDS); } } @@ -233,7 +233,7 @@ public class JDBCHelper { //如果需要轮询 计算该scriptData的SHA值 if(sqlParserVO.getIfPolling()){ - String scriptKey = StrUtil.join(":", id, name, type); + String scriptKey = StrUtil.join(":", id, type, name); String scriptSHA = DigestUtil.sha1Hex(data); scriptSHAMap.put(scriptKey, scriptSHA); } @@ -307,7 +307,7 @@ public class JDBCHelper { //如果需要轮询 计算该scriptData的SHA值 if(sqlParserVO.getIfPolling()){ - String scriptKey = StrUtil.join(":", id, name, type, language); + String scriptKey = StrUtil.join(":", id, type, name, language); String scriptSHA = DigestUtil.sha1Hex(data); scriptSHAMap.put(scriptKey, scriptSHA); } diff --git a/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/util/ScriptPollingTask.java b/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/util/ScriptPollingTask.java index 5dd40e243..89c7a91ad 100644 --- a/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/util/ScriptPollingTask.java +++ b/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/util/ScriptPollingTask.java @@ -33,7 +33,11 @@ public class ScriptPollingTask implements Runnable { private static final String CONCAT_WITH_LANGUAGE_PATTERN = "CONCAT_WS(':',{},{},{},{}) as script_concat"; - private static final String SHA_PATTERN = "SHA1({})"; + private static final String SHA_PATTERN = "SHA1({}) AS SHA1"; + + private static final String SHA_PATTERN_FOR_H2 = "RAWTOHEX(HASH('SHA-1', {})) AS SHA1"; + + private static final String SHA_FIELD_NAME = "SHA1"; private static final String SCRIPT_KEY_FIELD = "script_concat"; @@ -67,11 +71,16 @@ public class ScriptPollingTask implements Runnable { String scriptLanguageField = sqlParserVO.getScriptLanguageField(); String SHAField = StrUtil.format(SHA_PATTERN, scriptDataField); + //h2数据库计算SHA的函数与MySQL不同 + if(StrUtil.equals(sqlParserVO.getDriverClassName(), "org.h2.Driver")){ + SHAField = StrUtil.format(SHA_PATTERN_FOR_H2, scriptDataField); + } + String KeyField; if (StrUtil.isNotBlank(scriptLanguageField)) { - KeyField = StrUtil.format(CONCAT_WITH_LANGUAGE_PATTERN, scriptIdField, scriptNameField, scriptTypeField, scriptLanguageField); + KeyField = StrUtil.format(CONCAT_WITH_LANGUAGE_PATTERN, scriptIdField, scriptTypeField, scriptNameField, scriptLanguageField); } else { - KeyField = StrUtil.format(CONCAT_PATTERN, scriptIdField, scriptNameField, scriptTypeField); + KeyField = StrUtil.format(CONCAT_PATTERN, scriptIdField, scriptTypeField, scriptNameField); } String sqlCmd = StrUtil.format(SQL_PATTERN, KeyField, SHAField, scriptTableName, scriptApplicationNameField); @@ -85,7 +94,7 @@ public class ScriptPollingTask implements Runnable { while (rs.next()) { String scriptKey = getStringFromResultSet(rs, SCRIPT_KEY_FIELD); - String newSHA = getStringFromResultSet(rs, SHAField); + String newSHA = getStringFromResultSet(rs, SHA_FIELD_NAME); newScriptSet.add(scriptKey); //如果封装的SHAMap中不存在该script 表示该script为新增 if (!scriptSHAMap.containsKey(scriptKey)) { @@ -97,7 +106,7 @@ public class ScriptPollingTask implements Runnable { String newScriptData = getStringFromResultSet(newScriptRS, scriptDataField); //新增script changeScriptNode(scriptVO, newScriptData); - LOG.info("starting reload flow config... create script={} new value={},", scriptKey, newScriptData); + LOG.info("starting reload flow config... create script={}, new value={},", scriptKey, newScriptData); } //加入到shaMap scriptSHAMap.put(scriptKey, newSHA); @@ -112,7 +121,7 @@ public class ScriptPollingTask implements Runnable { String newScriptData = getStringFromResultSet(newScriptRS, scriptDataField); //修改script changeScriptNode(scriptVO, newScriptData); - LOG.info("starting reload flow config... update scriptId={} new value={},", scriptVO.getNodeId(), newScriptData); + LOG.info("starting reload flow config... update scriptId={}, new value={},", scriptVO.getNodeId(), newScriptData); } //修改shaMap scriptSHAMap.put(scriptKey, newSHA); diff --git a/liteflow-testcase-el/liteflow-testcase-el-sql-springboot-polling/src/test/java/com/yomahub/liteflow/test/sql/SQLWithXmlELSpringbootPollingTest.java b/liteflow-testcase-el/liteflow-testcase-el-sql-springboot-polling/src/test/java/com/yomahub/liteflow/test/sql/SQLWithXmlELSpringbootPollingTest.java new file mode 100644 index 000000000..833af55a3 --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-sql-springboot-polling/src/test/java/com/yomahub/liteflow/test/sql/SQLWithXmlELSpringbootPollingTest.java @@ -0,0 +1,181 @@ +package com.yomahub.liteflow.test.sql; + +import com.yomahub.liteflow.core.FlowExecutor; +import com.yomahub.liteflow.core.FlowInitHook; +import com.yomahub.liteflow.flow.FlowBus; +import com.yomahub.liteflow.flow.LiteflowResponse; +import com.yomahub.liteflow.log.LFLog; +import com.yomahub.liteflow.log.LFLoggerManager; +import com.yomahub.liteflow.parser.sql.exception.ELSQLException; +import com.yomahub.liteflow.parser.sql.util.JDBCHelper; +import com.yomahub.liteflow.parser.sql.vo.SQLParserVO; +import com.yomahub.liteflow.property.LiteflowConfig; +import com.yomahub.liteflow.property.LiteflowConfigGetter; +import com.yomahub.liteflow.slot.DefaultContext; +import com.yomahub.liteflow.spi.holder.SpiFactoryCleaner; +import com.yomahub.liteflow.spring.ComponentScanner; +import com.yomahub.liteflow.test.BaseTest; +import com.yomahub.liteflow.thread.ExecutorHelper; +import com.yomahub.liteflow.util.JsonUtil; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.test.context.TestPropertySource; +import org.springframework.test.context.junit.jupiter.SpringExtension; + +import javax.annotation.Resource; +import java.lang.reflect.Field; +import java.sql.*; +import java.util.concurrent.ScheduledThreadPoolExecutor; + +/** + * @author hxinyu + * @since 2.11.1 + */ +@ExtendWith(SpringExtension.class) +@TestPropertySource(value = "classpath:/application-poll-xml.properties") +@SpringBootTest(classes = SQLWithXmlELSpringbootPollingTest.class) +@EnableAutoConfiguration +@ComponentScan({ "com.yomahub.liteflow.test.sql.cmp" }) +public class SQLWithXmlELSpringbootPollingTest extends BaseTest { + + @Resource + private FlowExecutor flowExecutor; + + static LFLog LOG = LFLoggerManager.getLogger(SQLWithXmlELSpringbootPollingTest.class); + + @AfterAll + public static void after(){ + try{ + //关闭定时轮询线程池 + Field pollExecutor = JDBCHelper.class.getDeclaredField("pollExecutor"); + pollExecutor.setAccessible(true); + ScheduledThreadPoolExecutor threadPoolExecutor = (ScheduledThreadPoolExecutor) pollExecutor.get(null); + threadPoolExecutor.shutdownNow(); + LOG.info("[SQL Polling thread pool closed]"); + }catch (Exception ignored) { + LOG.error("[SQL Polling thread pool not closed]", ignored); + } + } + + @Test + public void testSQLWithXml() throws InterruptedException { + LiteflowResponse response = flowExecutor.execute2Resp("chain1", "arg"); + Assertions.assertEquals("a==>b==>c", response.getExecuteStepStr()); + + // 修改chain + changeData(); + Thread.sleep(4000); + Assertions.assertEquals("a==>c==>b", flowExecutor.execute2Resp("chain1", "arg").getExecuteStepStr()); + + // 新增chain + insertData(); + Thread.sleep(4000); + Assertions.assertEquals("a==>b", flowExecutor.execute2Resp("chain5", "arg").getExecuteStepStr()); + } + + + @Test + public void testSQLWithScriptXml() throws InterruptedException { + LiteflowResponse response = flowExecutor.execute2Resp("chain2", "arg"); + Assertions.assertTrue(response.isSuccess()); + Assertions.assertEquals("x1[if 脚本]==>a==>b", response.getExecuteStepStrWithoutTime()); + + // 修改script + changeScriptData(); + Thread.sleep(4000); + Assertions.assertEquals("x1[if 脚本]", flowExecutor.execute2Resp("chain2", "arg").getExecuteStepStr()); + + // 新増script + insertScriptData(); + Thread.sleep(4000); + response = flowExecutor.execute2Resp("chain6", "arg"); + DefaultContext context = response.getFirstContextBean(); + Assertions.assertEquals("a==>x3[x3脚本]", response.getExecuteStepStrWithoutTime()); + Assertions.assertEquals("hello", context.getData("test")); + } + + /** + * 修改chain数据 + */ + private void changeData() { + LiteflowConfig liteflowConfig = LiteflowConfigGetter.get(); + SQLParserVO sqlParserVO = JsonUtil.parseObject(liteflowConfig.getRuleSourceExtData(), SQLParserVO.class); + Connection connection; + try { + connection = DriverManager.getConnection(sqlParserVO.getUrl(), sqlParserVO.getUsername(), + sqlParserVO.getPassword()); + Statement statement = connection.createStatement(); + statement.executeUpdate("UPDATE EL_TABLE SET EL_DATA='THEN(a, c, b);' WHERE chain_name='chain1'"); + } + catch (SQLException e) { + throw new ELSQLException(e.getMessage()); + } + } + + /** + * 增加chain数据 + */ + private void insertData() { + LiteflowConfig liteflowConfig = LiteflowConfigGetter.get(); + SQLParserVO sqlParserVO = JsonUtil.parseObject(liteflowConfig.getRuleSourceExtData(), SQLParserVO.class); + Connection connection; + try { + connection = DriverManager.getConnection(sqlParserVO.getUrl(), sqlParserVO.getUsername(), + sqlParserVO.getPassword()); + Statement statement = connection.createStatement(); + statement.executeUpdate("INSERT INTO EL_TABLE (APPLICATION_NAME,CHAIN_NAME,EL_DATA) values ('demo','chain5','THEN(a, b);')"); + } + catch (SQLException e) { + throw new ELSQLException(e.getMessage()); + } + } + + /** + * 修改脚本数据 + */ + private void changeScriptData() { + LiteflowConfig liteflowConfig = LiteflowConfigGetter.get(); + SQLParserVO sqlParserVO = JsonUtil.parseObject(liteflowConfig.getRuleSourceExtData(), SQLParserVO.class); + Connection connection; + try { + connection = DriverManager.getConnection(sqlParserVO.getUrl(), sqlParserVO.getUsername(), + sqlParserVO.getPassword()); + Statement statement = connection.createStatement(); + //修改script data + statement.executeUpdate( + "UPDATE SCRIPT_NODE_TABLE SET SCRIPT_NODE_DATA='return false;' WHERE SCRIPT_NODE_ID='x1'"); + //修改script名 + statement.executeUpdate( + "UPDATE SCRIPT_NODE_TABLE SET SCRIPT_NODE_NAME='x0_script' WHERE SCRIPT_NODE_ID='x0'"); + } + catch (SQLException e) { + throw new ELSQLException(e.getMessage()); + } + } + + /** + * 增加脚本数据 + */ + private void insertScriptData() { + LiteflowConfig liteflowConfig = LiteflowConfigGetter.get(); + SQLParserVO sqlParserVO = JsonUtil.parseObject(liteflowConfig.getRuleSourceExtData(), SQLParserVO.class); + Connection connection; + try { + connection = DriverManager.getConnection(sqlParserVO.getUrl(), sqlParserVO.getUsername(), + sqlParserVO.getPassword()); + Statement statement = connection.createStatement(); + statement.executeUpdate( + "INSERT INTO SCRIPT_NODE_TABLE (APPLICATION_NAME,SCRIPT_NODE_ID,SCRIPT_NODE_NAME,SCRIPT_NODE_TYPE,SCRIPT_NODE_DATA,SCRIPT_LANGUAGE) values ('demo','x3','x3脚本','script','defaultContext.setData(\"test\",\"hello\");','groovy');"); + statement.executeUpdate( + "INSERT INTO EL_TABLE (APPLICATION_NAME,CHAIN_NAME,EL_DATA) values ('demo','chain6','THEN(a, x3);');"); + } + catch (SQLException e) { + throw new ELSQLException(e.getMessage()); + } + } +} diff --git a/liteflow-testcase-el/liteflow-testcase-el-sql-springboot-polling/src/test/resources/application-poll-xml.properties b/liteflow-testcase-el/liteflow-testcase-el-sql-springboot-polling/src/test/resources/application-poll-xml.properties new file mode 100644 index 000000000..4b662547f --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-sql-springboot-polling/src/test/resources/application-poll-xml.properties @@ -0,0 +1,29 @@ +liteflow.rule-source-ext-data={\ + "url":"jdbc:h2:mem:test_db;MODE=MySQL",\ + "driverClassName":"org.h2.Driver",\ + "username":"root",\ + "password":"123456",\ + "applicationName":"demo",\ + "chainTableName":"EL_TABLE",\ + "chainApplicationNameField":"application_name",\ + "chainNameField":"chain_name",\ + "elDataField":"EL_DATA",\ + "scriptTableName":"script_node_table",\ + "scriptApplicationNameField":"application_name",\ + "scriptIdField":"script_node_id",\ + "scriptNameField":"script_node_name",\ + "scriptDataField":"script_node_data",\ + "scriptLanguageField":"script_language",\ + "scriptTypeField":"script_node_type",\ + "ifPolling":true,\ + "pollingInterval":2,\ + "pollingStartTime":2\ + } + +spring.datasource.driver-class-name=org.h2.Driver +spring.datasource.url=jdbc:h2:mem:test_db;MODE=MySQL +spring.datasource.username=root +spring.datasource.password=123456 +spring.datasource.schema=classpath:/sql/schema.sql +spring.datasource.data=classpath:/sql/data.sql +spring.datasource.platform=h2 \ No newline at end of file diff --git a/liteflow-testcase-el/liteflow-testcase-el-sql-springboot-polling/src/test/resources/application-polling-xml.properties b/liteflow-testcase-el/liteflow-testcase-el-sql-springboot-polling/src/test/resources/application-polling-xml.properties deleted file mode 100644 index e69de29bb..000000000 diff --git a/liteflow-testcase-el/liteflow-testcase-el-sql-springboot-polling/src/test/resources/sql/data.sql b/liteflow-testcase-el/liteflow-testcase-el-sql-springboot-polling/src/test/resources/sql/data.sql new file mode 100644 index 000000000..5900dfa0a --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-sql-springboot-polling/src/test/resources/sql/data.sql @@ -0,0 +1,14 @@ +DELETE FROM EL_TABLE; + +INSERT INTO EL_TABLE (APPLICATION_NAME,CHAIN_NAME,EL_DATA) values ('demo','chain1','THEN(a, b, c);'); +INSERT INTO EL_TABLE (APPLICATION_NAME,CHAIN_NAME,EL_DATA) values ('demo','chain2','IF(x1, THEN(a, b));'); +INSERT INTO EL_TABLE (APPLICATION_NAME,CHAIN_NAME,EL_DATA) values ('demo','chain3','IF(x0, THEN(a, b));'); +INSERT INTO EL_TABLE (APPLICATION_NAME,CHAIN_NAME,EL_DATA) values ('demo','','IF(x0, THEN(a, b));'); +INSERT INTO EL_TABLE (APPLICATION_NAME,CHAIN_NAME,EL_DATA) values ('demo','chain4','IF(x2, IF(x0, THEN(a, b)));'); + +DELETE FROM SCRIPT_NODE_TABLE; + +INSERT INTO SCRIPT_NODE_TABLE (APPLICATION_NAME,SCRIPT_NODE_ID,SCRIPT_NODE_NAME,SCRIPT_NODE_TYPE,SCRIPT_NODE_DATA,SCRIPT_LANGUAGE) values ('demo','x0','if 脚本','if_script','return true','groovy'); +INSERT INTO SCRIPT_NODE_TABLE (APPLICATION_NAME,SCRIPT_NODE_ID,SCRIPT_NODE_NAME,SCRIPT_NODE_TYPE,SCRIPT_NODE_DATA,SCRIPT_LANGUAGE) values ('demo','x1','if 脚本','if_script','return true','groovy'); + +INSERT INTO SCRIPT_NODE_TABLE (APPLICATION_NAME,SCRIPT_NODE_ID,SCRIPT_NODE_NAME,SCRIPT_NODE_TYPE,SCRIPT_NODE_DATA,SCRIPT_LANGUAGE) values ('demo','x2','python脚本','if_script','return true','js'); diff --git a/liteflow-testcase-el/liteflow-testcase-el-sql-springboot-polling/src/test/resources/sql/schema.sql b/liteflow-testcase-el/liteflow-testcase-el-sql-springboot-polling/src/test/resources/sql/schema.sql new file mode 100644 index 000000000..fa60f098a --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-sql-springboot-polling/src/test/resources/sql/schema.sql @@ -0,0 +1,20 @@ +create table IF NOT EXISTS `EL_TABLE` +( + `id` bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY, + `application_name` varchar(32) NOT NULL, + `chain_name` varchar(32) NOT NULL, + `el_data` varchar(1024) NOT NULL, + PRIMARY KEY (`id`) +); + +create table IF NOT EXISTS `script_node_table` +( + `id` bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY, + `application_name` varchar(32) NOT NULL, + `script_node_id` varchar(32) NOT NULL, + `script_node_name` varchar(32) NOT NULL, + `script_node_type` varchar(32) NOT NULL, + `script_node_data` varchar(1024) NOT NULL, + `script_language` varchar(1024) NOT NULL, + PRIMARY KEY (`id`) +); \ No newline at end of file From 5f6650b5c81eaaa95e7f273fb00a84c0200e9f75 Mon Sep 17 00:00:00 2001 From: houxinyu Date: Wed, 20 Sep 2023 20:40:31 +0800 Subject: [PATCH 10/53] =?UTF-8?q?=E4=BC=98=E5=8C=96SQL=E8=BD=AE=E8=AF=A2&?= =?UTF-8?q?=E6=8A=BD=E5=8F=96=E7=BB=9F=E4=B8=80=E6=AD=A3=E5=88=99=E8=BD=AC?= =?UTF-8?q?=E6=8D=A2=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../parser/helper/NodeConvertHelper.java | 108 +++++++++++ .../parser/apollo/util/ApolloParseHelper.java | 1 + .../parser/redis/mode/RedisParserHelper.java | 72 +------- .../mode/polling/RedisParserPollingMode.java | 3 +- .../redis/mode/polling/ScriptPollingTask.java | 3 +- .../subscribe/RedisParserSubscribeMode.java | 5 +- .../parser/sql/util/ChainPollingTask.java | 78 +++----- .../liteflow/parser/sql/util/JDBCHelper.java | 4 +- .../parser/sql/util/ScriptPollingTask.java | 168 +++--------------- .../parser/zk/util/ZkParserHelper.java | 81 +-------- 10 files changed, 172 insertions(+), 351 deletions(-) create mode 100644 liteflow-core/src/main/java/com/yomahub/liteflow/parser/helper/NodeConvertHelper.java diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/parser/helper/NodeConvertHelper.java b/liteflow-core/src/main/java/com/yomahub/liteflow/parser/helper/NodeConvertHelper.java new file mode 100644 index 000000000..b4309eaa9 --- /dev/null +++ b/liteflow-core/src/main/java/com/yomahub/liteflow/parser/helper/NodeConvertHelper.java @@ -0,0 +1,108 @@ +package com.yomahub.liteflow.parser.helper; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.ReUtil; +import cn.hutool.core.util.StrUtil; +import com.yomahub.liteflow.builder.LiteFlowNodeBuilder; +import com.yomahub.liteflow.enums.NodeTypeEnum; + +import java.util.List; + +/** + * 冒号形式节点NodeSimpleVO转换 通用 Helper + * + * @author hxinyu + */ +public class NodeConvertHelper { + + /*script节点的修改/添加*/ + public static void changeScriptNode(NodeSimpleVO nodeSimpleVO, String newValue) { + // 有语言类型 + if (StrUtil.isNotBlank(nodeSimpleVO.getLanguage())) { + LiteFlowNodeBuilder.createScriptNode() + .setId(nodeSimpleVO.getNodeId()) + .setType(NodeTypeEnum.getEnumByCode(nodeSimpleVO.getType())) + .setName(nodeSimpleVO.getName()) + .setScript(newValue) + .setLanguage(nodeSimpleVO.getLanguage()) + .build(); + } + // 没有语言类型 + else { + LiteFlowNodeBuilder.createScriptNode() + .setId(nodeSimpleVO.getNodeId()) + .setType(NodeTypeEnum.getEnumByCode(nodeSimpleVO.getType())) + .setName(nodeSimpleVO.getName()) + .setScript(newValue) + .build(); + } + } + + public static NodeSimpleVO convert(String scriptKey){ + // 不需要去理解这串正则,就是一个匹配冒号的 + // 一定得是a:b,或是a:b:c...这种完整类型的字符串的 + List matchItemList = ReUtil.findAllGroup0("(?<=[^:]:)[^:]+|[^:]+(?=:[^:])", scriptKey); + if (CollUtil.isEmpty(matchItemList)) { + return null; + } + NodeSimpleVO nodeSimpleVO = new NodeSimpleVO(); + if (matchItemList.size() > 1) { + nodeSimpleVO.setNodeId(matchItemList.get(0)); + nodeSimpleVO.setType(matchItemList.get(1)); + } + + if (matchItemList.size() > 2) { + nodeSimpleVO.setName(matchItemList.get(2)); + } + + if (matchItemList.size() > 3) { + nodeSimpleVO.setLanguage(matchItemList.get(3)); + } + + return nodeSimpleVO; + } + + + public static class NodeSimpleVO { + + private String nodeId; + + private String type; + + private String name = StrUtil.EMPTY; + + private String language; + + public String getNodeId() { + return nodeId; + } + + public void setNodeId(String nodeId) { + this.nodeId = nodeId; + } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getLanguage() { + return language; + } + + public void setLanguage(String language) { + this.language = language; + } + } +} \ No newline at end of file diff --git a/liteflow-rule-plugin/liteflow-rule-apollo/src/main/java/com/yomahub/liteflow/parser/apollo/util/ApolloParseHelper.java b/liteflow-rule-plugin/liteflow-rule-apollo/src/main/java/com/yomahub/liteflow/parser/apollo/util/ApolloParseHelper.java index 468704be1..b8a4511c4 100644 --- a/liteflow-rule-plugin/liteflow-rule-apollo/src/main/java/com/yomahub/liteflow/parser/apollo/util/ApolloParseHelper.java +++ b/liteflow-rule-plugin/liteflow-rule-apollo/src/main/java/com/yomahub/liteflow/parser/apollo/util/ApolloParseHelper.java @@ -15,6 +15,7 @@ import com.yomahub.liteflow.enums.NodeTypeEnum; import com.yomahub.liteflow.flow.FlowBus; import com.yomahub.liteflow.parser.apollo.exception.ApolloException; import com.yomahub.liteflow.parser.apollo.vo.ApolloParserConfigVO; +import com.yomahub.liteflow.parser.helper.NodeConvertHelper; import com.yomahub.liteflow.spi.holder.ContextAwareHolder; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/mode/RedisParserHelper.java b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/mode/RedisParserHelper.java index eb60d2cdd..345fc9e2e 100644 --- a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/mode/RedisParserHelper.java +++ b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/mode/RedisParserHelper.java @@ -8,6 +8,7 @@ import com.yomahub.liteflow.builder.LiteFlowNodeBuilder; import com.yomahub.liteflow.enums.NodeTypeEnum; import com.yomahub.liteflow.log.LFLog; import com.yomahub.liteflow.log.LFLoggerManager; +import com.yomahub.liteflow.parser.helper.NodeConvertHelper; import com.yomahub.liteflow.parser.redis.vo.RedisParserVO; import org.redisson.config.Config; import org.redisson.config.SentinelServersConfig; @@ -112,7 +113,7 @@ public interface RedisParserHelper { * @param newValue 新的script值 */ static void changeScriptNode(String scriptFieldValue, String newValue) { - NodeSimpleVO nodeSimpleVO = convert(scriptFieldValue); + NodeConvertHelper.NodeSimpleVO nodeSimpleVO = NodeConvertHelper.convert(scriptFieldValue); // 有语言类型 if (StrUtil.isNotBlank(nodeSimpleVO.getLanguage())) { LiteFlowNodeBuilder.createScriptNode() @@ -133,73 +134,4 @@ public interface RedisParserHelper { .build(); } } - - static NodeSimpleVO convert(String str) { - // 不需要去理解这串正则,就是一个匹配冒号的 - // 一定得是a:b,或是a:b:c...这种完整类型的字符串的 - List matchItemList = ReUtil.findAllGroup0("(?<=[^:]:)[^:]+|[^:]+(?=:[^:])", str); - if (CollUtil.isEmpty(matchItemList)) { - return null; - } - - NodeSimpleVO nodeSimpleVO = new NodeSimpleVO(); - if (matchItemList.size() > 1) { - nodeSimpleVO.setNodeId(matchItemList.get(0)); - nodeSimpleVO.setType(matchItemList.get(1)); - } - - if (matchItemList.size() > 2) { - nodeSimpleVO.setName(matchItemList.get(2)); - } - - if (matchItemList.size() > 3) { - nodeSimpleVO.setLanguage(matchItemList.get(3)); - } - - return nodeSimpleVO; - } - - class NodeSimpleVO { - - private String nodeId; - - private String type; - - private String name = StrUtil.EMPTY; - - private String language; - - public String getNodeId() { - return nodeId; - } - - public void setNodeId(String nodeId) { - this.nodeId = nodeId; - } - - public String getType() { - return type; - } - - public void setType(String type) { - this.type = type; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public String getLanguage() { - return language; - } - - public void setLanguage(String language) { - this.language = language; - } - - } } diff --git a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/mode/polling/RedisParserPollingMode.java b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/mode/polling/RedisParserPollingMode.java index 662b801b5..352bf1f9e 100644 --- a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/mode/polling/RedisParserPollingMode.java +++ b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/mode/polling/RedisParserPollingMode.java @@ -6,6 +6,7 @@ import cn.hutool.core.thread.NamedThreadFactory; import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.StrUtil; import cn.hutool.crypto.digest.DigestUtil; +import com.yomahub.liteflow.parser.helper.NodeConvertHelper; import com.yomahub.liteflow.parser.redis.exception.RedisException; import com.yomahub.liteflow.parser.redis.mode.RClient; import com.yomahub.liteflow.parser.redis.mode.RedisMode; @@ -148,7 +149,7 @@ public class RedisParserPollingMode implements RedisParserHelper { List scriptItemContentList = new ArrayList<>(); for (String scriptFieldValue : scriptFieldSet) { - NodeSimpleVO nodeSimpleVO = RedisParserHelper.convert(scriptFieldValue); + NodeConvertHelper.NodeSimpleVO nodeSimpleVO = NodeConvertHelper.convert(scriptFieldValue); if (ObjectUtil.isNull(nodeSimpleVO)) { throw new RedisException( StrUtil.format("The name of the redis field [{}] in scriptKey [{}] is invalid", diff --git a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/mode/polling/ScriptPollingTask.java b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/mode/polling/ScriptPollingTask.java index a23965c37..40d4704e6 100644 --- a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/mode/polling/ScriptPollingTask.java +++ b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/mode/polling/ScriptPollingTask.java @@ -5,6 +5,7 @@ import cn.hutool.crypto.digest.DigestUtil; import com.yomahub.liteflow.flow.FlowBus; import com.yomahub.liteflow.log.LFLog; import com.yomahub.liteflow.log.LFLoggerManager; +import com.yomahub.liteflow.parser.helper.NodeConvertHelper; import com.yomahub.liteflow.parser.redis.mode.RClient; import com.yomahub.liteflow.parser.redis.mode.RedisParserHelper; import com.yomahub.liteflow.parser.redis.vo.RedisParserVO; @@ -68,7 +69,7 @@ public class ScriptPollingTask implements Runnable { String newSHA = scriptClient.evalSha(valueLua, scriptKey, scriptFieldValue); if (StrUtil.equals(newSHA, "nil")) { //新SHA值为nil, 即未获取到该script,表示该script已被删除 - RedisParserHelper.NodeSimpleVO nodeSimpleVO = RedisParserHelper.convert(scriptFieldValue); + NodeConvertHelper.NodeSimpleVO nodeSimpleVO = NodeConvertHelper.convert(scriptFieldValue); FlowBus.getNodeMap().remove(nodeSimpleVO.getNodeId()); LOG.info("starting reload flow config... delete key={}", scriptFieldValue); diff --git a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/mode/subscribe/RedisParserSubscribeMode.java b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/mode/subscribe/RedisParserSubscribeMode.java index b115baec5..aff895cd9 100644 --- a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/mode/subscribe/RedisParserSubscribeMode.java +++ b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/mode/subscribe/RedisParserSubscribeMode.java @@ -6,6 +6,7 @@ import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.StrUtil; import com.yomahub.liteflow.builder.el.LiteFlowChainELBuilder; import com.yomahub.liteflow.flow.FlowBus; +import com.yomahub.liteflow.parser.helper.NodeConvertHelper; import com.yomahub.liteflow.parser.redis.exception.RedisException; import com.yomahub.liteflow.parser.redis.mode.RClient; import com.yomahub.liteflow.parser.redis.mode.RedisMode; @@ -109,7 +110,7 @@ public class RedisParserSubscribeMode implements RedisParserHelper { for (Map.Entry entry : scriptMap.entrySet()) { String scriptFieldValue = entry.getKey(); String scriptData = entry.getValue(); - NodeSimpleVO nodeSimpleVO = RedisParserHelper.convert(scriptFieldValue); + NodeConvertHelper.NodeSimpleVO nodeSimpleVO = NodeConvertHelper.convert(scriptFieldValue); if (ObjectUtil.isNull(nodeSimpleVO)) { throw new RedisException( StrUtil.format("The name of the redis field [{}] in scriptKey [{}] is invalid", @@ -193,7 +194,7 @@ public class RedisParserSubscribeMode implements RedisParserHelper { //删除 script scriptClient.addListener(scriptKey, (EntryRemovedListener) event -> { LOG.info("starting reload flow config... delete key={}", event.getKey()); - NodeSimpleVO nodeSimpleVO = RedisParserHelper.convert(event.getKey()); + NodeConvertHelper.NodeSimpleVO nodeSimpleVO = NodeConvertHelper.convert(event.getKey()); FlowBus.getNodeMap().remove(nodeSimpleVO.getNodeId()); }); } diff --git a/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/util/ChainPollingTask.java b/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/util/ChainPollingTask.java index cac3bf033..a8de50f4f 100644 --- a/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/util/ChainPollingTask.java +++ b/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/util/ChainPollingTask.java @@ -1,6 +1,7 @@ package com.yomahub.liteflow.parser.sql.util; import cn.hutool.core.util.StrUtil; +import cn.hutool.crypto.digest.DigestUtil; import com.yomahub.liteflow.builder.el.LiteFlowChainELBuilder; import com.yomahub.liteflow.flow.FlowBus; import com.yomahub.liteflow.log.LFLog; @@ -29,12 +30,6 @@ public class ChainPollingTask implements Runnable { private static final String NEW_CHAIN_PATTERN = "SELECT {} FROM {} WHERE {}=? AND {}=?"; - private static final String SHA_PATTERN = "SHA1({}) AS SHA1"; - - private static final String SHA_PATTERN_FOR_H2 = "RAWTOHEX(HASH('SHA-1', {})) AS SHA1"; - - private static final String SHA_FIELD_NAME = "SHA1"; - public static Connection conn; private SQLParserVO sqlParserVO; @@ -53,6 +48,8 @@ public class ChainPollingTask implements Runnable { @Override public void run() { + PreparedStatement stmt = null; + ResultSet rs = null; try{ String chainTableName = sqlParserVO.getChainTableName(); String elDataField = sqlParserVO.getElDataField(); @@ -60,52 +57,37 @@ public class ChainPollingTask implements Runnable { String chainApplicationNameField = sqlParserVO.getChainApplicationNameField(); String applicationName = sqlParserVO.getApplicationName(); - String SHAField = StrUtil.format(SHA_PATTERN, elDataField); - //h2数据库计算SHA的函数与MySQL不同 - if(StrUtil.equals(sqlParserVO.getDriverClassName(), "org.h2.Driver")){ - SHAField = StrUtil.format(SHA_PATTERN_FOR_H2, elDataField); - } - - String sqlCmd = StrUtil.format(SQL_PATTERN, chainNameField, SHAField, chainTableName, + String sqlCmd = StrUtil.format(SQL_PATTERN, chainNameField, elDataField, chainTableName, chainApplicationNameField); - PreparedStatement stmt = conn.prepareStatement(sqlCmd, ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY); + stmt = conn.prepareStatement(sqlCmd, ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY); // 设置游标拉取数量 stmt.setFetchSize(FETCH_SIZE_MAX); stmt.setString(1, applicationName); - ResultSet rs = stmt.executeQuery(); + rs = stmt.executeQuery(); Set newChainSet = new HashSet<>(); while(rs.next()) { String chainName = getStringFromResultSet(rs, chainNameField); - String newSHA = getStringFromResultSet(rs, SHA_FIELD_NAME); + String newData = getStringFromResultSet(rs, elDataField); + String newSHA = DigestUtil.sha1Hex(newData); newChainSet.add(chainName); //如果封装的SHAMap中不存在该chain, 表示该chain为新增 if(!chainSHAMap.containsKey(chainName)) { - //获取新chain结果 - ResultSet newChainRS = getNewChainRS(elDataField, chainTableName, chainNameField, - chainApplicationNameField, applicationName, chainName); - if(newChainRS.next()) { - String newELData = getStringFromResultSet(newChainRS, elDataField); - //新增chain - LiteFlowChainELBuilder.createChain().setChainId(chainName).setEL(newELData).build(); - LOG.info("starting reload flow config... create chain={}, new value={},", chainName, newELData); - //加入到shaMap - chainSHAMap.put(chainName, newSHA); - } + //新增chain + LiteFlowChainELBuilder.createChain().setChainId(chainName).setEL(newData).build(); + LOG.info("starting reload flow config... create chain={}, new value={},", chainName, newData); + //加入到shaMap + chainSHAMap.put(chainName, newSHA); + } else if (!StrUtil.equals(newSHA, chainSHAMap.get(chainName))) { //SHA值发生变化,表示该chain的值已被修改,重新拉取变化的chain - ResultSet newChainRS = getNewChainRS(elDataField, chainTableName, chainNameField, - chainApplicationNameField, applicationName, chainName); - if(newChainRS.next()) { - String newELData = getStringFromResultSet(newChainRS, elDataField); - //修改chain - LiteFlowChainELBuilder.createChain().setChainId(chainName).setEL(newELData).build(); - LOG.info("starting reload flow config... update chain={}, new value={},", chainName, newELData); - //修改shaMap - chainSHAMap.put(chainName, newSHA); - } + //修改chain + LiteFlowChainELBuilder.createChain().setChainId(chainName).setEL(newData).build(); + LOG.info("starting reload flow config... update chain={}, new value={},", chainName, newData); + //修改shaMap + chainSHAMap.put(chainName, newSHA); } //SHA值无变化,表示该chain未改变 } @@ -128,28 +110,14 @@ public class ChainPollingTask implements Runnable { } } } - } - catch (Exception e) { + } catch (Exception e) { LOG.error("[Exception during SQL chain polling] " + e.getMessage(), e); + } finally { + // 关闭连接 + LiteFlowJdbcUtil.close(null, stmt, rs); } } - private ResultSet getNewChainRS(String elDataField, String chainTableName, String chainNameField, - String chainApplicationNameField, String applicationName, String chainName) { - ResultSet rs = null; - String sqlCmd = StrUtil.format(NEW_CHAIN_PATTERN, elDataField, chainTableName, - chainNameField, chainApplicationNameField); - try{ - PreparedStatement stmt = conn.prepareStatement(sqlCmd, ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY); - stmt.setString(1, chainName); - stmt.setString(2, applicationName); - rs = stmt.executeQuery(); - }catch (Exception e) { - throw new ELSQLException(e.getMessage()); - } - return rs; - } - private String getStringFromResultSet(ResultSet rs, String field) throws SQLException { String data = rs.getString(field); if (StrUtil.isBlank(data)) { diff --git a/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/util/JDBCHelper.java b/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/util/JDBCHelper.java index 5b9c2083b..5be349ed7 100644 --- a/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/util/JDBCHelper.java +++ b/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/util/JDBCHelper.java @@ -60,10 +60,10 @@ public class JDBCHelper { private static ScheduledThreadPoolExecutor pollExecutor; //chain的SHA1加密值 用于轮询时确定chain是否变化 - private Map chainSHAMap = new HashMap<>(); + private Map chainSHAMap = new HashMap<>(); //script的SHA1加密值 用于轮询时确定script是否变化 - private Map scriptSHAMap = new HashMap<>(); + private Map scriptSHAMap = new HashMap<>(); /** * 初始化 INSTANCE diff --git a/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/util/ScriptPollingTask.java b/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/util/ScriptPollingTask.java index 89c7a91ad..af05f195e 100644 --- a/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/util/ScriptPollingTask.java +++ b/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/util/ScriptPollingTask.java @@ -1,13 +1,11 @@ package com.yomahub.liteflow.parser.sql.util; -import cn.hutool.core.collection.CollUtil; -import cn.hutool.core.util.ReUtil; import cn.hutool.core.util.StrUtil; -import com.yomahub.liteflow.builder.LiteFlowNodeBuilder; -import com.yomahub.liteflow.enums.NodeTypeEnum; +import cn.hutool.crypto.digest.DigestUtil; import com.yomahub.liteflow.flow.FlowBus; import com.yomahub.liteflow.log.LFLog; import com.yomahub.liteflow.log.LFLoggerManager; +import com.yomahub.liteflow.parser.helper.NodeConvertHelper; import com.yomahub.liteflow.parser.sql.exception.ELSQLException; import com.yomahub.liteflow.parser.sql.vo.SQLParserVO; @@ -33,12 +31,6 @@ public class ScriptPollingTask implements Runnable { private static final String CONCAT_WITH_LANGUAGE_PATTERN = "CONCAT_WS(':',{},{},{},{}) as script_concat"; - private static final String SHA_PATTERN = "SHA1({}) AS SHA1"; - - private static final String SHA_PATTERN_FOR_H2 = "RAWTOHEX(HASH('SHA-1', {})) AS SHA1"; - - private static final String SHA_FIELD_NAME = "SHA1"; - private static final String SCRIPT_KEY_FIELD = "script_concat"; public static Connection conn; @@ -60,6 +52,8 @@ public class ScriptPollingTask implements Runnable { @Override public void run() { + PreparedStatement stmt = null; + ResultSet rs = null; try { String scriptTableName = sqlParserVO.getScriptTableName(); String scriptIdField = sqlParserVO.getScriptIdField(); @@ -70,12 +64,6 @@ public class ScriptPollingTask implements Runnable { String applicationName = sqlParserVO.getApplicationName(); String scriptLanguageField = sqlParserVO.getScriptLanguageField(); - String SHAField = StrUtil.format(SHA_PATTERN, scriptDataField); - //h2数据库计算SHA的函数与MySQL不同 - if(StrUtil.equals(sqlParserVO.getDriverClassName(), "org.h2.Driver")){ - SHAField = StrUtil.format(SHA_PATTERN_FOR_H2, scriptDataField); - } - String KeyField; if (StrUtil.isNotBlank(scriptLanguageField)) { KeyField = StrUtil.format(CONCAT_WITH_LANGUAGE_PATTERN, scriptIdField, scriptTypeField, scriptNameField, scriptLanguageField); @@ -83,46 +71,37 @@ public class ScriptPollingTask implements Runnable { KeyField = StrUtil.format(CONCAT_PATTERN, scriptIdField, scriptTypeField, scriptNameField); } - String sqlCmd = StrUtil.format(SQL_PATTERN, KeyField, SHAField, scriptTableName, scriptApplicationNameField); - PreparedStatement stmt = conn.prepareStatement(sqlCmd, ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY); + String sqlCmd = StrUtil.format(SQL_PATTERN, KeyField, scriptDataField, scriptTableName, scriptApplicationNameField); + stmt = conn.prepareStatement(sqlCmd, ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY); // 设置游标拉取数量 stmt.setFetchSize(FETCH_SIZE_MAX); stmt.setString(1, applicationName); - ResultSet rs = stmt.executeQuery(); + rs = stmt.executeQuery(); Set newScriptSet = new HashSet<>(); while (rs.next()) { String scriptKey = getStringFromResultSet(rs, SCRIPT_KEY_FIELD); - String newSHA = getStringFromResultSet(rs, SHA_FIELD_NAME); + String newData = getStringFromResultSet(rs, scriptDataField); + String newSHA = DigestUtil.sha1Hex(newData); newScriptSet.add(scriptKey); //如果封装的SHAMap中不存在该script 表示该script为新增 if (!scriptSHAMap.containsKey(scriptKey)) { - //获取新script内容 - NodeSimpleVO scriptVO = convert(scriptKey); - ResultSet newScriptRS = getNewScriptRS(scriptDataField, scriptTableName, scriptIdField, - scriptVO.getNodeId(), scriptApplicationNameField, applicationName); - if(newScriptRS.next()) { - String newScriptData = getStringFromResultSet(newScriptRS, scriptDataField); - //新增script - changeScriptNode(scriptVO, newScriptData); - LOG.info("starting reload flow config... create script={}, new value={},", scriptKey, newScriptData); - } + NodeConvertHelper.NodeSimpleVO scriptVO = NodeConvertHelper.convert(scriptKey); + //新增script + NodeConvertHelper.changeScriptNode(scriptVO, newData); + LOG.info("starting reload flow config... create script={}, new value={},", scriptKey, newData); + //加入到shaMap scriptSHAMap.put(scriptKey, newSHA); } else if (!StrUtil.equals(newSHA, scriptSHAMap.get(scriptKey))) { //SHA值发生变化,表示该script的值已被修改,重新拉取变化的script - //获取新script内容 - NodeSimpleVO scriptVO = convert(scriptKey); - ResultSet newScriptRS = getNewScriptRS(scriptDataField, scriptTableName, scriptIdField, - scriptVO.getNodeId(), scriptApplicationNameField, applicationName); - if(newScriptRS.next()) { - String newScriptData = getStringFromResultSet(newScriptRS, scriptDataField); - //修改script - changeScriptNode(scriptVO, newScriptData); - LOG.info("starting reload flow config... update scriptId={}, new value={},", scriptVO.getNodeId(), newScriptData); - } + NodeConvertHelper.NodeSimpleVO scriptVO = NodeConvertHelper.convert(scriptKey); + //修改script + NodeConvertHelper.changeScriptNode(scriptVO, newData); + LOG.info("starting reload flow config... update scriptId={}, new value={},", scriptVO.getNodeId(), newData); + //修改shaMap scriptSHAMap.put(scriptKey, newSHA); } @@ -140,7 +119,7 @@ public class ScriptPollingTask implements Runnable { while(iterator.hasNext()){ String scriptKey = iterator.next(); if (!newScriptSet.contains(scriptKey)) { - NodeSimpleVO scriptVO = convert(scriptKey); + NodeConvertHelper.NodeSimpleVO scriptVO = NodeConvertHelper.convert(scriptKey); //删除script FlowBus.getNodeMap().remove(scriptVO.getNodeId()); LOG.info("starting reload flow config... delete script={}", scriptKey); @@ -152,25 +131,12 @@ public class ScriptPollingTask implements Runnable { } catch (Exception e) { LOG.error("[Exception during SQL script polling] " + e.getMessage(), e); + } finally { + // 关闭连接 + LiteFlowJdbcUtil.close(null, stmt, rs); } } - private ResultSet getNewScriptRS(String scriptDataField, String scriptTableName, String scriptIdField, - String scriptId, String scriptApplicationNameField, String applicationName) { - ResultSet rs = null; - String sqlCmd = StrUtil.format(NEW_SCRIPT_PATTERN, scriptDataField, scriptTableName, - scriptIdField, scriptApplicationNameField); - try{ - PreparedStatement stmt = conn.prepareStatement(sqlCmd, ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY); - stmt.setString(1, scriptId); - stmt.setString(2, applicationName); - rs = stmt.executeQuery(); - }catch (Exception e) { - throw new ELSQLException(e.getMessage()); - } - return rs; - } - private String getStringFromResultSet(ResultSet rs, String field) throws SQLException { String data = rs.getString(field); if (StrUtil.isBlank(data)) { @@ -178,92 +144,4 @@ public class ScriptPollingTask implements Runnable { } return data; } - - /*script节点的修改/添加*/ - private void changeScriptNode(NodeSimpleVO nodeSimpleVO, String newValue) { - // 有语言类型 - if (StrUtil.isNotBlank(nodeSimpleVO.getLanguage())) { - LiteFlowNodeBuilder.createScriptNode() - .setId(nodeSimpleVO.getNodeId()) - .setType(NodeTypeEnum.getEnumByCode(nodeSimpleVO.getType())) - .setName(nodeSimpleVO.getName()) - .setScript(newValue) - .setLanguage(nodeSimpleVO.getLanguage()) - .build(); - } - // 没有语言类型 - else { - LiteFlowNodeBuilder.createScriptNode() - .setId(nodeSimpleVO.getNodeId()) - .setType(NodeTypeEnum.getEnumByCode(nodeSimpleVO.getType())) - .setName(nodeSimpleVO.getName()) - .setScript(newValue) - .build(); - } - } - - private NodeSimpleVO convert(String scriptKey){ - List matchItemList = ReUtil.findAllGroup0("(?<=[^:]:)[^:]+|[^:]+(?=:[^:])", scriptKey); - if (CollUtil.isEmpty(matchItemList)) { - return null; - } - NodeSimpleVO nodeSimpleVO = new NodeSimpleVO(); - if (matchItemList.size() > 1) { - nodeSimpleVO.setNodeId(matchItemList.get(0)); - nodeSimpleVO.setType(matchItemList.get(1)); - } - - if (matchItemList.size() > 2) { - nodeSimpleVO.setName(matchItemList.get(2)); - } - - if (matchItemList.size() > 3) { - nodeSimpleVO.setLanguage(matchItemList.get(3)); - } - - return nodeSimpleVO; - } - - class NodeSimpleVO { - - private String nodeId; - - private String type; - - private String name = StrUtil.EMPTY; - - private String language; - - public String getNodeId() { - return nodeId; - } - - public void setNodeId(String nodeId) { - this.nodeId = nodeId; - } - - public String getType() { - return type; - } - - public void setType(String type) { - this.type = type; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public String getLanguage() { - return language; - } - - public void setLanguage(String language) { - this.language = language; - } - } } diff --git a/liteflow-rule-plugin/liteflow-rule-zk/src/main/java/com/yomahub/liteflow/parser/zk/util/ZkParserHelper.java b/liteflow-rule-plugin/liteflow-rule-zk/src/main/java/com/yomahub/liteflow/parser/zk/util/ZkParserHelper.java index c994b2b56..c70633949 100644 --- a/liteflow-rule-plugin/liteflow-rule-zk/src/main/java/com/yomahub/liteflow/parser/zk/util/ZkParserHelper.java +++ b/liteflow-rule-plugin/liteflow-rule-zk/src/main/java/com/yomahub/liteflow/parser/zk/util/ZkParserHelper.java @@ -10,6 +10,7 @@ import com.yomahub.liteflow.builder.LiteFlowNodeBuilder; import com.yomahub.liteflow.builder.el.LiteFlowChainELBuilder; import com.yomahub.liteflow.enums.NodeTypeEnum; import com.yomahub.liteflow.flow.FlowBus; +import com.yomahub.liteflow.parser.helper.NodeConvertHelper; import com.yomahub.liteflow.parser.zk.exception.ZkException; import com.yomahub.liteflow.parser.zk.vo.ZkParserVO; import org.apache.curator.framework.CuratorFramework; @@ -87,7 +88,7 @@ public class ZkParserHelper { List scriptItemContentList = new ArrayList<>(); for (String scriptNodeValue : scriptNodeValueList) { - NodeSimpleVO nodeSimpleVO = convert(scriptNodeValue); + NodeConvertHelper.NodeSimpleVO nodeSimpleVO = NodeConvertHelper.convert(scriptNodeValue); if (Objects.isNull(nodeSimpleVO)) { throw new ZkException(StrUtil.format("The name of the zk node is invalid:{}", scriptNodeValue)); } @@ -179,12 +180,12 @@ public class ZkParserHelper { .contains(type)) { LOG.info("starting reload flow config... {} path={} value={},", type.name(), path, value); String scriptNodeValue = FileNameUtil.getName(path); - NodeSimpleVO nodeSimpleVO = convert(scriptNodeValue); + NodeConvertHelper.NodeSimpleVO nodeSimpleVO = NodeConvertHelper.convert(scriptNodeValue); // 有语言类型 if (StrUtil.isNotBlank(nodeSimpleVO.getLanguage())) { LiteFlowNodeBuilder.createScriptNode() .setId(nodeSimpleVO.getNodeId()) - .setType(NodeTypeEnum.getEnumByCode(nodeSimpleVO.type)) + .setType(NodeTypeEnum.getEnumByCode(nodeSimpleVO.getType())) .setName(nodeSimpleVO.getName()) .setScript(value) .setLanguage(nodeSimpleVO.getLanguage()) @@ -194,7 +195,7 @@ public class ZkParserHelper { else { LiteFlowNodeBuilder.createScriptNode() .setId(nodeSimpleVO.getNodeId()) - .setType(NodeTypeEnum.getEnumByCode(nodeSimpleVO.type)) + .setType(NodeTypeEnum.getEnumByCode(nodeSimpleVO.getType())) .setName(nodeSimpleVO.getName()) .setScript(value) .build(); @@ -203,80 +204,10 @@ public class ZkParserHelper { else if (CuratorCacheListener.Type.NODE_DELETED.equals(type)) { LOG.info("starting reload flow config... delete path={}", path); String scriptNodeValue = FileNameUtil.getName(path); - NodeSimpleVO nodeSimpleVO = convert(scriptNodeValue); + NodeConvertHelper.NodeSimpleVO nodeSimpleVO = NodeConvertHelper.convert(scriptNodeValue); FlowBus.getNodeMap().remove(nodeSimpleVO.getNodeId()); } }); } } - - public NodeSimpleVO convert(String str) { - // 不需要去理解这串正则,就是一个匹配冒号的 - // 一定得是a:b,或是a:b:c...这种完整类型的字符串的 - List matchItemList = ReUtil.findAllGroup0("(?<=[^:]:)[^:]+|[^:]+(?=:[^:])", str); - if (CollUtil.isEmpty(matchItemList)) { - return null; - } - - NodeSimpleVO nodeSimpleVO = new NodeSimpleVO(); - if (matchItemList.size() > 1) { - nodeSimpleVO.setNodeId(matchItemList.get(0)); - nodeSimpleVO.setType(matchItemList.get(1)); - } - - if (matchItemList.size() > 2) { - nodeSimpleVO.setName(matchItemList.get(2)); - } - - if (matchItemList.size() > 3) { - nodeSimpleVO.setLanguage(matchItemList.get(3)); - } - - return nodeSimpleVO; - } - - private static class NodeSimpleVO { - - private String nodeId; - - private String type; - - private String name = ""; - - private String language; - - public String getNodeId() { - return nodeId; - } - - public void setNodeId(String nodeId) { - this.nodeId = nodeId; - } - - public String getType() { - return type; - } - - public void setType(String type) { - this.type = type; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public String getLanguage() { - return language; - } - - public void setLanguage(String language) { - this.language = language; - } - - } - } From 7fdb5829f55b06f48e38092337b10397b416c90d Mon Sep 17 00:00:00 2001 From: luoyi <972849752@qq.com> Date: Wed, 20 Sep 2023 22:55:31 +0800 Subject: [PATCH 11/53] =?UTF-8?q?enhancement=20#I821F1=20=E5=88=9D?= =?UTF-8?q?=E5=A7=8B=E5=8C=96=E6=97=B6=E5=A2=9E=E5=8A=A0=20Chain=20?= =?UTF-8?q?=E5=BC=95=E7=94=A8=E5=88=A4=E6=96=AD=EF=BC=8C=E9=81=BF=E5=85=8D?= =?UTF-8?q?=E6=AD=BB=E5=BE=AA=E7=8E=AF=E8=80=8C=E5=AF=BC=E8=87=B4=E5=A0=86?= =?UTF-8?q?=E6=A0=88=E6=BA=A2=E5=87=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../builder/el/LiteFlowChainELBuilder.java | 15 +++-- .../yomahub/liteflow/core/FlowExecutor.java | 57 ++++++++++++++++++- .../liteflow/parser/helper/ParserHelper.java | 17 ++++-- ...FlowInDifferentConfigELSpringbootTest.java | 37 ++++++++++++ .../endlessLoop/FlowJsonELSpringBootTest.java | 37 ++++++++++++ .../endlessLoop/FlowXMLELSpringBootTest.java | 37 ++++++++++++ .../endlessLoop/FlowYmlELSpringBootTest.java | 37 ++++++++++++ .../endlessLoop/application-json.properties | 1 + ...plication-subInDifferentConfig1.properties | 2 + .../endlessLoop/application-xml.properties | 1 + .../endlessLoop/application-yml.properties | 1 + .../subflow/endlessLoop/flow-sub1.el.xml | 6 ++ .../subflow/endlessLoop/flow-sub2.el.yml | 6 ++ .../subflow/endlessLoop/flow.el.json | 18 ++++++ .../resources/subflow/endlessLoop/flow.el.xml | 16 ++++++ .../resources/subflow/endlessLoop/flow.el.yml | 8 +++ 16 files changed, 282 insertions(+), 14 deletions(-) create mode 100644 liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/subflow/endlessLoop/FlowInDifferentConfigELSpringbootTest.java create mode 100644 liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/subflow/endlessLoop/FlowJsonELSpringBootTest.java create mode 100644 liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/subflow/endlessLoop/FlowXMLELSpringBootTest.java create mode 100644 liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/subflow/endlessLoop/FlowYmlELSpringBootTest.java create mode 100644 liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/subflow/endlessLoop/application-json.properties create mode 100644 liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/subflow/endlessLoop/application-subInDifferentConfig1.properties create mode 100644 liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/subflow/endlessLoop/application-xml.properties create mode 100644 liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/subflow/endlessLoop/application-yml.properties create mode 100644 liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/subflow/endlessLoop/flow-sub1.el.xml create mode 100644 liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/subflow/endlessLoop/flow-sub2.el.yml create mode 100644 liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/subflow/endlessLoop/flow.el.json create mode 100644 liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/subflow/endlessLoop/flow.el.xml create mode 100644 liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/subflow/endlessLoop/flow.el.yml 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 97e3de3e5..bb61ce5a4 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 @@ -15,8 +15,8 @@ import com.yomahub.liteflow.exception.ELParseException; import com.yomahub.liteflow.exception.FlowSystemException; import com.yomahub.liteflow.flow.FlowBus; import com.yomahub.liteflow.flow.element.Chain; -import com.yomahub.liteflow.flow.element.Node; import com.yomahub.liteflow.flow.element.Condition; +import com.yomahub.liteflow.flow.element.Node; import com.yomahub.liteflow.log.LFLog; import com.yomahub.liteflow.log.LFLoggerManager; @@ -108,12 +108,15 @@ public class LiteFlowChainELBuilder { return this; } + /** + *

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

+ *

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

+ * + * @param chainId + * @return LiteFlowChainELBuilder + */ public LiteFlowChainELBuilder setChainId(String chainId) { - if (FlowBus.containChain(chainId)) { - this.chain = FlowBus.getChain(chainId); - } else { - this.chain.setChainId(chainId); - } + this.chain.setChainId(chainId); return this; } 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 830ad1025..f333a384e 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,9 +15,7 @@ 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.Chain; -import com.yomahub.liteflow.flow.element.Node; -import com.yomahub.liteflow.flow.element.Rollbackable; +import com.yomahub.liteflow.flow.element.*; import com.yomahub.liteflow.flow.entity.CmpStep; import com.yomahub.liteflow.flow.id.IdGeneratorHolder; import com.yomahub.liteflow.log.LFLog; @@ -195,6 +193,9 @@ public class FlowExecutor { } } + // 检查构建生成的 chain 的有效性 + checkValidOfChain(); + // 执行钩子 if (isStart) { FlowInitHook.executeHook(); @@ -214,6 +215,56 @@ 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 节点 + * @throws CyclicDependencyException + */ + private void checkValidOfChain(Chain currentChain, Set associatedChainIdSet) { + // 判断 completedChainIdSet 中是否已经存在对应的 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 { + // chain 重复,说明子 chain 中引用了自身或其父 chain,存在死循环情况 + throw new CyclicDependencyException(StrUtil.format("There is a circular dependency in the chain[{}], please check carefully.", currentChain.getChainId())); + } + } + // 此方法就是从原有的配置源主动拉取新的进行刷新 // 和FlowBus.refreshFlowMetaData的区别就是一个为主动拉取,一个为被动监听到新的内容进行刷新 public void reloadRule() { diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/parser/helper/ParserHelper.java b/liteflow-core/src/main/java/com/yomahub/liteflow/parser/helper/ParserHelper.java index eb239f76f..89eb4177b 100644 --- a/liteflow-core/src/main/java/com/yomahub/liteflow/parser/helper/ParserHelper.java +++ b/liteflow-core/src/main/java/com/yomahub/liteflow/parser/helper/ParserHelper.java @@ -13,7 +13,10 @@ import com.yomahub.liteflow.flow.FlowBus; import org.dom4j.Document; import org.dom4j.Element; -import java.util.*; +import java.util.Iterator; +import java.util.List; +import java.util.Optional; +import java.util.Set; import java.util.function.Consumer; import java.util.regex.Pattern; @@ -237,8 +240,10 @@ public class ParserHelper { // 构建chainBuilder String chainId = Optional.ofNullable(chainNode.get(ID)).orElse(chainNode.get(NAME)).textValue(); String el = chainNode.get(VALUE).textValue(); - LiteFlowChainELBuilder chainELBuilder = LiteFlowChainELBuilder.createChain().setChainId(chainId); - chainELBuilder.setEL(el).build(); + LiteFlowChainELBuilder.createChain() + .setChainId(chainId) + .setEL(el) + .build(); } /** @@ -250,8 +255,10 @@ public class ParserHelper { String chainId = Optional.ofNullable(e.attributeValue(ID)).orElse(e.attributeValue(NAME)); String text = e.getText(); String el = RegexUtil.removeComments(text); - LiteFlowChainELBuilder chainELBuilder = LiteFlowChainELBuilder.createChain().setChainId(chainId); - chainELBuilder.setEL(el).build(); + LiteFlowChainELBuilder.createChain() + .setChainId(chainId) + .setEL(el) + .build(); } /** diff --git a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/subflow/endlessLoop/FlowInDifferentConfigELSpringbootTest.java b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/subflow/endlessLoop/FlowInDifferentConfigELSpringbootTest.java new file mode 100644 index 000000000..331297ab3 --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/subflow/endlessLoop/FlowInDifferentConfigELSpringbootTest.java @@ -0,0 +1,37 @@ +package com.yomahub.liteflow.test.subflow.endlessLoop; + +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; + +/** + * 测试多文件情况下 chain 死循环逻辑 + * + * @author luo yi + * @since 2.11.0 + */ +@TestPropertySource(value = "classpath:/subflow/endlessLoop/application-subInDifferentConfig1.properties") +@SpringBootTest(classes = FlowInDifferentConfigELSpringbootTest.class) +@EnableAutoConfiguration +@ComponentScan({ "com.yomahub.liteflow.test.subflow.cmp1", "com.yomahub.liteflow.test.subflow.cmp2" }) +public class FlowInDifferentConfigELSpringbootTest extends BaseTest { + + @Resource + private FlowExecutor flowExecutor; + + // 测试 chain 死循环 + @Test + public void testChainEndlessLoop() { + LiteflowResponse response = flowExecutor.execute2Resp("chain1", "it's a request"); + Assertions.assertFalse(response.isSuccess()); + } + +} diff --git a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/subflow/endlessLoop/FlowJsonELSpringBootTest.java b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/subflow/endlessLoop/FlowJsonELSpringBootTest.java new file mode 100644 index 000000000..3a9a01a53 --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/subflow/endlessLoop/FlowJsonELSpringBootTest.java @@ -0,0 +1,37 @@ +package com.yomahub.liteflow.test.subflow.endlessLoop; + +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; + +/** + * 测试 json 文件情况下 chain 死循环逻辑 + * + * @author luo yi + * @since 2.11.0 + */ +@TestPropertySource(value = "classpath:/subflow/endlessLoop/application-json.properties") +@SpringBootTest(classes = FlowJsonELSpringBootTest.class) +@EnableAutoConfiguration +@ComponentScan({ "com.yomahub.liteflow.test.subflow.cmp1" }) +public class FlowJsonELSpringBootTest extends BaseTest { + + @Resource + private FlowExecutor flowExecutor; + + // 测试 chain 死循环 + @Test + public void testChainEndlessLoop() { + LiteflowResponse response = flowExecutor.execute2Resp("chain7", "it's a request"); + Assertions.assertFalse(response.isSuccess()); + } + +} diff --git a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/subflow/endlessLoop/FlowXMLELSpringBootTest.java b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/subflow/endlessLoop/FlowXMLELSpringBootTest.java new file mode 100644 index 000000000..f686e4150 --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/subflow/endlessLoop/FlowXMLELSpringBootTest.java @@ -0,0 +1,37 @@ +package com.yomahub.liteflow.test.subflow.endlessLoop; + +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; + +/** + * 测试 xml 文件情况下 chain 死循环逻辑 + * + * @author luo yi + * @since 2.11.0 + */ +@TestPropertySource(value = "classpath:/subflow/endlessLoop/application-xml.properties") +@SpringBootTest(classes = FlowXMLELSpringBootTest.class) +@EnableAutoConfiguration +@ComponentScan({ "com.yomahub.liteflow.test.subflow.cmp1" }) +public class FlowXMLELSpringBootTest extends BaseTest { + + @Resource + private FlowExecutor flowExecutor; + + // 测试 chain 死循环 + @Test + public void testChainEndlessLoop() { + LiteflowResponse response = flowExecutor.execute2Resp("chain1", "it's a request"); + Assertions.assertFalse(response.isSuccess()); + } + +} diff --git a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/subflow/endlessLoop/FlowYmlELSpringBootTest.java b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/subflow/endlessLoop/FlowYmlELSpringBootTest.java new file mode 100644 index 000000000..b0829cb26 --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/subflow/endlessLoop/FlowYmlELSpringBootTest.java @@ -0,0 +1,37 @@ +package com.yomahub.liteflow.test.subflow.endlessLoop; + +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; + +/** + * 测试 yml 文件情况下 chain 死循环逻辑 + * + * @author luo yi + * @since 2.11.0 + */ +@TestPropertySource(value = "classpath:/subflow/endlessLoop/application-yml.properties") +@SpringBootTest(classes = FlowYmlELSpringBootTest.class) +@EnableAutoConfiguration +@ComponentScan({ "com.yomahub.liteflow.test.subflow.cmp1" }) +public class FlowYmlELSpringBootTest extends BaseTest { + + @Resource + private FlowExecutor flowExecutor; + + // 测试 chain 死循环 + @Test + public void testChainEndlessLoop() { + LiteflowResponse response = flowExecutor.execute2Resp("chain5", "it's a request"); + Assertions.assertFalse(response.isSuccess()); + } + +} diff --git a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/subflow/endlessLoop/application-json.properties b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/subflow/endlessLoop/application-json.properties new file mode 100644 index 000000000..f19fd93f5 --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/subflow/endlessLoop/application-json.properties @@ -0,0 +1 @@ +liteflow.rule-source=subflow/endlessLoop/flow.el.json \ No newline at end of file diff --git a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/subflow/endlessLoop/application-subInDifferentConfig1.properties b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/subflow/endlessLoop/application-subInDifferentConfig1.properties new file mode 100644 index 000000000..418d38274 --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/subflow/endlessLoop/application-subInDifferentConfig1.properties @@ -0,0 +1,2 @@ +liteflow.rule-source=subflow/endlessLoop/flow-sub1.el.xml,subflow/endlessLoop/flow-sub2.el.yml +liteflow.support-multiple-type=true \ No newline at end of file diff --git a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/subflow/endlessLoop/application-xml.properties b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/subflow/endlessLoop/application-xml.properties new file mode 100644 index 000000000..d2261bca5 --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/subflow/endlessLoop/application-xml.properties @@ -0,0 +1 @@ +liteflow.rule-source=subflow/endlessLoop/flow.el.xml \ No newline at end of file diff --git a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/subflow/endlessLoop/application-yml.properties b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/subflow/endlessLoop/application-yml.properties new file mode 100644 index 000000000..a9088ce2e --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/subflow/endlessLoop/application-yml.properties @@ -0,0 +1 @@ +liteflow.rule-source=subflow/endlessLoop/flow.el.yml \ No newline at end of file diff --git a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/subflow/endlessLoop/flow-sub1.el.xml b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/subflow/endlessLoop/flow-sub1.el.xml new file mode 100644 index 000000000..3f1a585ab --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/subflow/endlessLoop/flow-sub1.el.xml @@ -0,0 +1,6 @@ + + + + THEN(a, b); + + \ No newline at end of file diff --git a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/subflow/endlessLoop/flow-sub2.el.yml b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/subflow/endlessLoop/flow-sub2.el.yml new file mode 100644 index 000000000..6861be3cc --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/subflow/endlessLoop/flow-sub2.el.yml @@ -0,0 +1,6 @@ +flow: + chain: + - name: chain2 + value: "THEN(c, d, chain3);" + - name: chain3 + value: "THEN(a, chain2);" \ No newline at end of file diff --git a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/subflow/endlessLoop/flow.el.json b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/subflow/endlessLoop/flow.el.json new file mode 100644 index 000000000..1a54d6c6c --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/subflow/endlessLoop/flow.el.json @@ -0,0 +1,18 @@ +{ + "flow": { + "chain": [ + { + "name": "chain7", + "value": "THEN(a, chain8);" + }, + { + "name": "chain8", + "value": "THEN(b, chain9);" + }, + { + "name": "chain9", + "value": "WHEN(c, chain7);" + } + ] + } +} \ No newline at end of file diff --git a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/subflow/endlessLoop/flow.el.xml b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/subflow/endlessLoop/flow.el.xml new file mode 100644 index 000000000..d615bf81d --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/subflow/endlessLoop/flow.el.xml @@ -0,0 +1,16 @@ + + + + + THEN(a, chain2); + + + + THEN(b, chain3); + + + + THEN(c, chain1); + + + \ No newline at end of file diff --git a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/subflow/endlessLoop/flow.el.yml b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/subflow/endlessLoop/flow.el.yml new file mode 100644 index 000000000..1699d501b --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/subflow/endlessLoop/flow.el.yml @@ -0,0 +1,8 @@ +flow: + chain: + - name: chain4 + value: "THEN(a, chain5);" + - name: chain5 + value: "THEN(b, chain6);" + - name: chain6 + value: "THEN(c, chain5);" \ No newline at end of file From e93a8179cd620af84c7c66abc401b655f40a51fa Mon Sep 17 00:00:00 2001 From: houxinyu Date: Fri, 22 Sep 2023 16:59:27 +0800 Subject: [PATCH 12/53] =?UTF-8?q?=E4=BC=98=E5=8C=96sql=E8=BD=AE=E8=AF=A2?= =?UTF-8?q?=E8=BF=9E=E6=8E=A5=E7=AE=A1=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../liteflow/parser/redis/mode/RedisParserHelper.java | 4 ---- .../yomahub/liteflow/parser/sql/util/ChainPollingTask.java | 6 +++--- .../yomahub/liteflow/parser/sql/util/ScriptPollingTask.java | 6 +++--- .../com/yomahub/liteflow/parser/zk/util/ZkParserHelper.java | 1 - 4 files changed, 6 insertions(+), 11 deletions(-) diff --git a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/mode/RedisParserHelper.java b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/mode/RedisParserHelper.java index 345fc9e2e..68bb1bc68 100644 --- a/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/mode/RedisParserHelper.java +++ b/liteflow-rule-plugin/liteflow-rule-redis/src/main/java/com/yomahub/liteflow/parser/redis/mode/RedisParserHelper.java @@ -1,8 +1,6 @@ package com.yomahub.liteflow.parser.redis.mode; -import cn.hutool.core.collection.CollUtil; import cn.hutool.core.text.StrFormatter; -import cn.hutool.core.util.ReUtil; import cn.hutool.core.util.StrUtil; import com.yomahub.liteflow.builder.LiteFlowNodeBuilder; import com.yomahub.liteflow.enums.NodeTypeEnum; @@ -13,8 +11,6 @@ import com.yomahub.liteflow.parser.redis.vo.RedisParserVO; import org.redisson.config.Config; import org.redisson.config.SentinelServersConfig; -import java.util.List; - /** * Redis 解析器通用接口 * diff --git a/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/util/ChainPollingTask.java b/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/util/ChainPollingTask.java index a8de50f4f..7e7172715 100644 --- a/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/util/ChainPollingTask.java +++ b/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/util/ChainPollingTask.java @@ -30,7 +30,7 @@ public class ChainPollingTask implements Runnable { private static final String NEW_CHAIN_PATTERN = "SELECT {} FROM {} WHERE {}=? AND {}=?"; - public static Connection conn; + private Connection conn; private SQLParserVO sqlParserVO; @@ -43,11 +43,11 @@ public class ChainPollingTask implements Runnable { public ChainPollingTask(SQLParserVO sqlParserVO, Map chainSHAMap) { this.sqlParserVO = sqlParserVO; this.chainSHAMap = chainSHAMap; - conn = LiteFlowJdbcUtil.getConn(sqlParserVO); } @Override public void run() { + conn = LiteFlowJdbcUtil.getConn(sqlParserVO); PreparedStatement stmt = null; ResultSet rs = null; try{ @@ -114,7 +114,7 @@ public class ChainPollingTask implements Runnable { LOG.error("[Exception during SQL chain polling] " + e.getMessage(), e); } finally { // 关闭连接 - LiteFlowJdbcUtil.close(null, stmt, rs); + LiteFlowJdbcUtil.close(conn, stmt, rs); } } diff --git a/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/util/ScriptPollingTask.java b/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/util/ScriptPollingTask.java index af05f195e..7e920e14c 100644 --- a/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/util/ScriptPollingTask.java +++ b/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/util/ScriptPollingTask.java @@ -33,7 +33,7 @@ public class ScriptPollingTask implements Runnable { private static final String SCRIPT_KEY_FIELD = "script_concat"; - public static Connection conn; + private Connection conn; private SQLParserVO sqlParserVO; @@ -46,12 +46,12 @@ public class ScriptPollingTask implements Runnable { public ScriptPollingTask(SQLParserVO sqlParserVO, Map scriptSHAMap) { this.sqlParserVO = sqlParserVO; this.scriptSHAMap = scriptSHAMap; - conn = LiteFlowJdbcUtil.getConn(sqlParserVO); } @Override public void run() { + conn = LiteFlowJdbcUtil.getConn(sqlParserVO); PreparedStatement stmt = null; ResultSet rs = null; try { @@ -133,7 +133,7 @@ public class ScriptPollingTask implements Runnable { LOG.error("[Exception during SQL script polling] " + e.getMessage(), e); } finally { // 关闭连接 - LiteFlowJdbcUtil.close(null, stmt, rs); + LiteFlowJdbcUtil.close(conn, stmt, rs); } } diff --git a/liteflow-rule-plugin/liteflow-rule-zk/src/main/java/com/yomahub/liteflow/parser/zk/util/ZkParserHelper.java b/liteflow-rule-plugin/liteflow-rule-zk/src/main/java/com/yomahub/liteflow/parser/zk/util/ZkParserHelper.java index c70633949..28f81702e 100644 --- a/liteflow-rule-plugin/liteflow-rule-zk/src/main/java/com/yomahub/liteflow/parser/zk/util/ZkParserHelper.java +++ b/liteflow-rule-plugin/liteflow-rule-zk/src/main/java/com/yomahub/liteflow/parser/zk/util/ZkParserHelper.java @@ -4,7 +4,6 @@ import cn.hutool.core.collection.CollUtil; import cn.hutool.core.collection.CollectionUtil; import cn.hutool.core.collection.ListUtil; import cn.hutool.core.io.file.FileNameUtil; -import cn.hutool.core.util.ReUtil; import cn.hutool.core.util.StrUtil; import com.yomahub.liteflow.builder.LiteFlowNodeBuilder; import com.yomahub.liteflow.builder.el.LiteFlowChainELBuilder; From 4adbd1a53262e65a706d501f9405d02c30d84781 Mon Sep 17 00:00:00 2001 From: houxinyu Date: Fri, 22 Sep 2023 23:03:36 +0800 Subject: [PATCH 13/53] =?UTF-8?q?=E4=BC=98=E5=8C=96sql=E8=BD=AE=E8=AF=A2?= =?UTF-8?q?=E9=83=A8=E5=88=86=E6=B5=8B=E8=AF=95=E7=94=A8=E4=BE=8B=E5=8F=8A?= =?UTF-8?q?=E5=91=BD=E5=90=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../liteflow/parser/sql/SQLXmlELParser.java | 2 +- .../liteflow/parser/sql/util/JDBCHelper.java | 16 ++--- .../liteflow/parser/sql/vo/SQLParserVO.java | 30 ++++---- .../.gitignore | 33 --------- .../pom.xml | 68 ------------------- .../com/yomahub/liteflow/test/BaseTest.java | 27 -------- .../yomahub/liteflow/test/sql/cmp/ACmp.java | 22 ------ .../yomahub/liteflow/test/sql/cmp/BCmp.java | 22 ------ .../yomahub/liteflow/test/sql/cmp/CCmp.java | 22 ------ .../src/test/resources/sql/data.sql | 14 ---- .../src/test/resources/sql/schema.sql | 20 ------ .../SQLWithXmlELSpringbootPollingTest.java | 10 ++- .../resources/application-poll-xml.properties | 6 +- .../src/test/resources/sql/data.sql | 4 +- 14 files changed, 33 insertions(+), 263 deletions(-) delete mode 100644 liteflow-testcase-el/liteflow-testcase-el-sql-springboot-polling/.gitignore delete mode 100644 liteflow-testcase-el/liteflow-testcase-el-sql-springboot-polling/pom.xml delete mode 100644 liteflow-testcase-el/liteflow-testcase-el-sql-springboot-polling/src/test/java/com/yomahub/liteflow/test/BaseTest.java delete mode 100644 liteflow-testcase-el/liteflow-testcase-el-sql-springboot-polling/src/test/java/com/yomahub/liteflow/test/sql/cmp/ACmp.java delete mode 100644 liteflow-testcase-el/liteflow-testcase-el-sql-springboot-polling/src/test/java/com/yomahub/liteflow/test/sql/cmp/BCmp.java delete mode 100644 liteflow-testcase-el/liteflow-testcase-el-sql-springboot-polling/src/test/java/com/yomahub/liteflow/test/sql/cmp/CCmp.java delete mode 100644 liteflow-testcase-el/liteflow-testcase-el-sql-springboot-polling/src/test/resources/sql/data.sql delete mode 100644 liteflow-testcase-el/liteflow-testcase-el-sql-springboot-polling/src/test/resources/sql/schema.sql rename liteflow-testcase-el/{liteflow-testcase-el-sql-springboot-polling => liteflow-testcase-el-sql-springboot}/src/test/java/com/yomahub/liteflow/test/sql/SQLWithXmlELSpringbootPollingTest.java (96%) rename liteflow-testcase-el/{liteflow-testcase-el-sql-springboot-polling => liteflow-testcase-el-sql-springboot}/src/test/resources/application-poll-xml.properties (91%) diff --git a/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/SQLXmlELParser.java b/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/SQLXmlELParser.java index 6f218de4a..98fa7f640 100644 --- a/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/SQLXmlELParser.java +++ b/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/SQLXmlELParser.java @@ -68,7 +68,7 @@ public class SQLXmlELParser extends ClassXmlFlowELParser { try{ JDBCHelper jdbcHelper = JDBCHelper.getInstance(); String content = jdbcHelper.getContent(); - if(sqlParserVO.getIfPolling()) { + if(sqlParserVO.getPollingEnabled()) { FlowInitHook.addHook(() -> { jdbcHelper.listenSQL(); return true; diff --git a/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/util/JDBCHelper.java b/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/util/JDBCHelper.java index 5be349ed7..8eb6dc4b8 100644 --- a/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/util/JDBCHelper.java +++ b/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/util/JDBCHelper.java @@ -76,7 +76,7 @@ public class JDBCHelper { } INSTANCE.setSqlParserVO(sqlParserVO); //创建定时任务线程池 - if (sqlParserVO.getIfPolling() && ObjectUtil.isNull(getPollExecutor())) { + if (sqlParserVO.getPollingEnabled() && ObjectUtil.isNull(getPollExecutor())) { ThreadFactory namedThreadFactory = new NamedThreadFactory("SQL-Polling-", false); ScheduledThreadPoolExecutor threadPoolExecutor = new ScheduledThreadPoolExecutor( CORE_POOL_SIZE, @@ -137,7 +137,7 @@ public class JDBCHelper { result.add(StrUtil.format(CHAIN_XML_PATTERN, XmlUtil.escape(chainName), elData)); //如果需要轮询 计算该chainData的SHA值 - if(sqlParserVO.getIfPolling()){ + if(sqlParserVO.getPollingEnabled()){ String chainSHA = DigestUtil.sha1Hex(elData); chainSHAMap.put(chainName, chainSHA); } @@ -167,13 +167,13 @@ public class JDBCHelper { public void listenSQL() { //添加轮询chain的定时任务 ChainPollingTask chainTask = new ChainPollingTask(sqlParserVO, chainSHAMap); - pollExecutor.scheduleAtFixedRate(chainTask, sqlParserVO.getPollingStartTime().longValue(), - sqlParserVO.getPollingInterval().longValue(), TimeUnit.SECONDS); + pollExecutor.scheduleAtFixedRate(chainTask, sqlParserVO.getPollingStartSeconds().longValue(), + sqlParserVO.getPollingIntervalSeconds().longValue(), TimeUnit.SECONDS); if (hasScriptData()) { //添加轮询script的定时任务 ScriptPollingTask scriptTask = new ScriptPollingTask(sqlParserVO, scriptSHAMap); - pollExecutor.scheduleAtFixedRate(scriptTask, sqlParserVO.getPollingStartTime().longValue(), - sqlParserVO.getPollingInterval().longValue(), TimeUnit.SECONDS); + pollExecutor.scheduleAtFixedRate(scriptTask, sqlParserVO.getPollingStartSeconds().longValue(), + sqlParserVO.getPollingIntervalSeconds().longValue(), TimeUnit.SECONDS); } } @@ -232,7 +232,7 @@ public class JDBCHelper { result.add(StrUtil.format(NODE_ITEM_XML_PATTERN, XmlUtil.escape(id), XmlUtil.escape(name), type, data)); //如果需要轮询 计算该scriptData的SHA值 - if(sqlParserVO.getIfPolling()){ + if(sqlParserVO.getPollingEnabled()){ String scriptKey = StrUtil.join(":", id, type, name); String scriptSHA = DigestUtil.sha1Hex(data); scriptSHAMap.put(scriptKey, scriptSHA); @@ -306,7 +306,7 @@ public class JDBCHelper { type, language, data)); //如果需要轮询 计算该scriptData的SHA值 - if(sqlParserVO.getIfPolling()){ + if(sqlParserVO.getPollingEnabled()){ String scriptKey = StrUtil.join(":", id, type, name, language); String scriptSHA = DigestUtil.sha1Hex(data); scriptSHAMap.put(scriptKey, scriptSHA); diff --git a/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/vo/SQLParserVO.java b/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/vo/SQLParserVO.java index e1479025e..2e7bf0cd0 100644 --- a/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/vo/SQLParserVO.java +++ b/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/vo/SQLParserVO.java @@ -91,13 +91,13 @@ public class SQLParserVO { private String scriptLanguageField; /*轮询机制是否开启 默认不开启*/ - private Boolean ifPolling = false; + private Boolean pollingEnabled = false; /*轮询时间间隔(s) 默认120s*/ - private Integer pollingInterval = 120; + private Integer pollingIntervalSeconds = 120; /*规则配置后首次轮询的起始时间 默认为60s*/ - private Integer pollingStartTime = 60; + private Integer pollingStartSeconds = 60; public String getUrl() { return url; @@ -234,27 +234,27 @@ public class SQLParserVO { return StrUtil.isBlank(url) && StrUtil.isBlank(username) && StrUtil.isBlank(password) && StrUtil.isBlank(driverClassName); } - public Boolean getIfPolling() { - return ifPolling; + public Boolean getPollingEnabled() { + return pollingEnabled; } - public void setIfPolling(Boolean ifPolling) { - this.ifPolling = ifPolling; + public void setPollingEnabled(Boolean pollingEnabled) { + this.pollingEnabled = pollingEnabled; } - public Integer getPollingInterval() { - return pollingInterval; + public Integer getPollingIntervalSeconds() { + return pollingIntervalSeconds; } - public void setPollingInterval(Integer pollingInterval) { - this.pollingInterval = pollingInterval; + public void setPollingIntervalSeconds(Integer pollingIntervalSeconds) { + this.pollingIntervalSeconds = pollingIntervalSeconds; } - public Integer getPollingStartTime() { - return pollingStartTime; + public Integer getPollingStartSeconds() { + return pollingStartSeconds; } - public void setPollingStartTime(Integer pollingStartTime) { - this.pollingStartTime = pollingStartTime; + public void setPollingStartSeconds(Integer pollingStartSeconds) { + this.pollingStartSeconds = pollingStartSeconds; } } diff --git a/liteflow-testcase-el/liteflow-testcase-el-sql-springboot-polling/.gitignore b/liteflow-testcase-el/liteflow-testcase-el-sql-springboot-polling/.gitignore deleted file mode 100644 index 549e00a2a..000000000 --- a/liteflow-testcase-el/liteflow-testcase-el-sql-springboot-polling/.gitignore +++ /dev/null @@ -1,33 +0,0 @@ -HELP.md -target/ -!.mvn/wrapper/maven-wrapper.jar -!**/src/main/**/target/ -!**/src/test/**/target/ - -### STS ### -.apt_generated -.classpath -.factorypath -.project -.settings -.springBeans -.sts4-cache - -### IntelliJ IDEA ### -.idea -*.iws -*.iml -*.ipr - -### NetBeans ### -/nbproject/private/ -/nbbuild/ -/dist/ -/nbdist/ -/.nb-gradle/ -build/ -!**/src/main/**/build/ -!**/src/test/**/build/ - -### VS Code ### -.vscode/ diff --git a/liteflow-testcase-el/liteflow-testcase-el-sql-springboot-polling/pom.xml b/liteflow-testcase-el/liteflow-testcase-el-sql-springboot-polling/pom.xml deleted file mode 100644 index 334c00ab4..000000000 --- a/liteflow-testcase-el/liteflow-testcase-el-sql-springboot-polling/pom.xml +++ /dev/null @@ -1,68 +0,0 @@ - - - - liteflow-testcase-el - com.yomahub - ${revision} - ../pom.xml - - 4.0.0 - - liteflow-testcase-el-sql-springboot-polling - - - 2.1.214 - 2.6.8 - - - - - com.yomahub - liteflow-spring-boot-starter - ${revision} - - - - com.yomahub - liteflow-rule-sql - ${revision} - test - - - - org.springframework.boot - spring-boot-starter-test - - - - org.springframework.boot - spring-boot-starter-data-jpa - ${jpa.version} - test - - - - com.h2database - h2 - ${h2.version} - test - - - - com.yomahub - liteflow-script-groovy - ${revision} - test - - - - com.yomahub - liteflow-script-graaljs - ${revision} - test - - - - diff --git a/liteflow-testcase-el/liteflow-testcase-el-sql-springboot-polling/src/test/java/com/yomahub/liteflow/test/BaseTest.java b/liteflow-testcase-el/liteflow-testcase-el-sql-springboot-polling/src/test/java/com/yomahub/liteflow/test/BaseTest.java deleted file mode 100644 index a06c46f17..000000000 --- a/liteflow-testcase-el/liteflow-testcase-el-sql-springboot-polling/src/test/java/com/yomahub/liteflow/test/BaseTest.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.yomahub.liteflow.test; - -import com.yomahub.liteflow.core.FlowInitHook; -import com.yomahub.liteflow.flow.FlowBus; -import com.yomahub.liteflow.property.LiteflowConfigGetter; -import com.yomahub.liteflow.spi.holder.SpiFactoryCleaner; -import com.yomahub.liteflow.spring.ComponentScanner; -import com.yomahub.liteflow.thread.ExecutorHelper; -import org.junit.jupiter.api.AfterAll; - -/** - * @author hxinyu - * @since 2.11.1 - */ -public class BaseTest { - - @AfterAll - public static void cleanScanCache() { - ComponentScanner.cleanCache(); - FlowBus.cleanCache(); - ExecutorHelper.loadInstance().clearExecutorServiceMap(); - SpiFactoryCleaner.clean(); - LiteflowConfigGetter.clean(); - FlowInitHook.cleanHook(); - } - -} \ No newline at end of file diff --git a/liteflow-testcase-el/liteflow-testcase-el-sql-springboot-polling/src/test/java/com/yomahub/liteflow/test/sql/cmp/ACmp.java b/liteflow-testcase-el/liteflow-testcase-el-sql-springboot-polling/src/test/java/com/yomahub/liteflow/test/sql/cmp/ACmp.java deleted file mode 100644 index 11ffb1a7c..000000000 --- a/liteflow-testcase-el/liteflow-testcase-el-sql-springboot-polling/src/test/java/com/yomahub/liteflow/test/sql/cmp/ACmp.java +++ /dev/null @@ -1,22 +0,0 @@ -/** - *

Title: liteflow

- *

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

- * - * @author Bryan.Zhang - * @email weenyc31@163.com - * @Date 2020/4/1 - */ -package com.yomahub.liteflow.test.sql.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!"); - } - -} \ No newline at end of file diff --git a/liteflow-testcase-el/liteflow-testcase-el-sql-springboot-polling/src/test/java/com/yomahub/liteflow/test/sql/cmp/BCmp.java b/liteflow-testcase-el/liteflow-testcase-el-sql-springboot-polling/src/test/java/com/yomahub/liteflow/test/sql/cmp/BCmp.java deleted file mode 100644 index 9601ee2cf..000000000 --- a/liteflow-testcase-el/liteflow-testcase-el-sql-springboot-polling/src/test/java/com/yomahub/liteflow/test/sql/cmp/BCmp.java +++ /dev/null @@ -1,22 +0,0 @@ -/** - *

Title: liteflow

- *

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

- * - * @author Bryan.Zhang - * @email weenyc31@163.com - * @Date 2020/4/1 - */ -package com.yomahub.liteflow.test.sql.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-sql-springboot-polling/src/test/java/com/yomahub/liteflow/test/sql/cmp/CCmp.java b/liteflow-testcase-el/liteflow-testcase-el-sql-springboot-polling/src/test/java/com/yomahub/liteflow/test/sql/cmp/CCmp.java deleted file mode 100644 index 2274a153e..000000000 --- a/liteflow-testcase-el/liteflow-testcase-el-sql-springboot-polling/src/test/java/com/yomahub/liteflow/test/sql/cmp/CCmp.java +++ /dev/null @@ -1,22 +0,0 @@ -/** - *

Title: liteflow

- *

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

- * - * @author Bryan.Zhang - * @email weenyc31@163.com - * @Date 2020/4/1 - */ -package com.yomahub.liteflow.test.sql.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!"); - } - -} \ No newline at end of file diff --git a/liteflow-testcase-el/liteflow-testcase-el-sql-springboot-polling/src/test/resources/sql/data.sql b/liteflow-testcase-el/liteflow-testcase-el-sql-springboot-polling/src/test/resources/sql/data.sql deleted file mode 100644 index 5900dfa0a..000000000 --- a/liteflow-testcase-el/liteflow-testcase-el-sql-springboot-polling/src/test/resources/sql/data.sql +++ /dev/null @@ -1,14 +0,0 @@ -DELETE FROM EL_TABLE; - -INSERT INTO EL_TABLE (APPLICATION_NAME,CHAIN_NAME,EL_DATA) values ('demo','chain1','THEN(a, b, c);'); -INSERT INTO EL_TABLE (APPLICATION_NAME,CHAIN_NAME,EL_DATA) values ('demo','chain2','IF(x1, THEN(a, b));'); -INSERT INTO EL_TABLE (APPLICATION_NAME,CHAIN_NAME,EL_DATA) values ('demo','chain3','IF(x0, THEN(a, b));'); -INSERT INTO EL_TABLE (APPLICATION_NAME,CHAIN_NAME,EL_DATA) values ('demo','','IF(x0, THEN(a, b));'); -INSERT INTO EL_TABLE (APPLICATION_NAME,CHAIN_NAME,EL_DATA) values ('demo','chain4','IF(x2, IF(x0, THEN(a, b)));'); - -DELETE FROM SCRIPT_NODE_TABLE; - -INSERT INTO SCRIPT_NODE_TABLE (APPLICATION_NAME,SCRIPT_NODE_ID,SCRIPT_NODE_NAME,SCRIPT_NODE_TYPE,SCRIPT_NODE_DATA,SCRIPT_LANGUAGE) values ('demo','x0','if 脚本','if_script','return true','groovy'); -INSERT INTO SCRIPT_NODE_TABLE (APPLICATION_NAME,SCRIPT_NODE_ID,SCRIPT_NODE_NAME,SCRIPT_NODE_TYPE,SCRIPT_NODE_DATA,SCRIPT_LANGUAGE) values ('demo','x1','if 脚本','if_script','return true','groovy'); - -INSERT INTO SCRIPT_NODE_TABLE (APPLICATION_NAME,SCRIPT_NODE_ID,SCRIPT_NODE_NAME,SCRIPT_NODE_TYPE,SCRIPT_NODE_DATA,SCRIPT_LANGUAGE) values ('demo','x2','python脚本','if_script','return true','js'); diff --git a/liteflow-testcase-el/liteflow-testcase-el-sql-springboot-polling/src/test/resources/sql/schema.sql b/liteflow-testcase-el/liteflow-testcase-el-sql-springboot-polling/src/test/resources/sql/schema.sql deleted file mode 100644 index fa60f098a..000000000 --- a/liteflow-testcase-el/liteflow-testcase-el-sql-springboot-polling/src/test/resources/sql/schema.sql +++ /dev/null @@ -1,20 +0,0 @@ -create table IF NOT EXISTS `EL_TABLE` -( - `id` bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY, - `application_name` varchar(32) NOT NULL, - `chain_name` varchar(32) NOT NULL, - `el_data` varchar(1024) NOT NULL, - PRIMARY KEY (`id`) -); - -create table IF NOT EXISTS `script_node_table` -( - `id` bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY, - `application_name` varchar(32) NOT NULL, - `script_node_id` varchar(32) NOT NULL, - `script_node_name` varchar(32) NOT NULL, - `script_node_type` varchar(32) NOT NULL, - `script_node_data` varchar(1024) NOT NULL, - `script_language` varchar(1024) NOT NULL, - PRIMARY KEY (`id`) -); \ No newline at end of file diff --git a/liteflow-testcase-el/liteflow-testcase-el-sql-springboot-polling/src/test/java/com/yomahub/liteflow/test/sql/SQLWithXmlELSpringbootPollingTest.java b/liteflow-testcase-el/liteflow-testcase-el-sql-springboot/src/test/java/com/yomahub/liteflow/test/sql/SQLWithXmlELSpringbootPollingTest.java similarity index 96% rename from liteflow-testcase-el/liteflow-testcase-el-sql-springboot-polling/src/test/java/com/yomahub/liteflow/test/sql/SQLWithXmlELSpringbootPollingTest.java rename to liteflow-testcase-el/liteflow-testcase-el-sql-springboot/src/test/java/com/yomahub/liteflow/test/sql/SQLWithXmlELSpringbootPollingTest.java index 833af55a3..e358fe2e3 100644 --- a/liteflow-testcase-el/liteflow-testcase-el-sql-springboot-polling/src/test/java/com/yomahub/liteflow/test/sql/SQLWithXmlELSpringbootPollingTest.java +++ b/liteflow-testcase-el/liteflow-testcase-el-sql-springboot/src/test/java/com/yomahub/liteflow/test/sql/SQLWithXmlELSpringbootPollingTest.java @@ -1,8 +1,6 @@ package com.yomahub.liteflow.test.sql; import com.yomahub.liteflow.core.FlowExecutor; -import com.yomahub.liteflow.core.FlowInitHook; -import com.yomahub.liteflow.flow.FlowBus; import com.yomahub.liteflow.flow.LiteflowResponse; import com.yomahub.liteflow.log.LFLog; import com.yomahub.liteflow.log.LFLoggerManager; @@ -12,10 +10,7 @@ import com.yomahub.liteflow.parser.sql.vo.SQLParserVO; import com.yomahub.liteflow.property.LiteflowConfig; import com.yomahub.liteflow.property.LiteflowConfigGetter; import com.yomahub.liteflow.slot.DefaultContext; -import com.yomahub.liteflow.spi.holder.SpiFactoryCleaner; -import com.yomahub.liteflow.spring.ComponentScanner; import com.yomahub.liteflow.test.BaseTest; -import com.yomahub.liteflow.thread.ExecutorHelper; import com.yomahub.liteflow.util.JsonUtil; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.Assertions; @@ -29,7 +24,10 @@ import org.springframework.test.context.junit.jupiter.SpringExtension; import javax.annotation.Resource; import java.lang.reflect.Field; -import java.sql.*; +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.SQLException; +import java.sql.Statement; import java.util.concurrent.ScheduledThreadPoolExecutor; /** diff --git a/liteflow-testcase-el/liteflow-testcase-el-sql-springboot-polling/src/test/resources/application-poll-xml.properties b/liteflow-testcase-el/liteflow-testcase-el-sql-springboot/src/test/resources/application-poll-xml.properties similarity index 91% rename from liteflow-testcase-el/liteflow-testcase-el-sql-springboot-polling/src/test/resources/application-poll-xml.properties rename to liteflow-testcase-el/liteflow-testcase-el-sql-springboot/src/test/resources/application-poll-xml.properties index 4b662547f..1962f270b 100644 --- a/liteflow-testcase-el/liteflow-testcase-el-sql-springboot-polling/src/test/resources/application-poll-xml.properties +++ b/liteflow-testcase-el/liteflow-testcase-el-sql-springboot/src/test/resources/application-poll-xml.properties @@ -15,9 +15,9 @@ liteflow.rule-source-ext-data={\ "scriptDataField":"script_node_data",\ "scriptLanguageField":"script_language",\ "scriptTypeField":"script_node_type",\ - "ifPolling":true,\ - "pollingInterval":2,\ - "pollingStartTime":2\ + "pollingEnabled":true,\ + "pollingIntervalSeconds":2,\ + "pollingStartSeconds":2\ } spring.datasource.driver-class-name=org.h2.Driver diff --git a/liteflow-testcase-el/liteflow-testcase-el-sql-springboot/src/test/resources/sql/data.sql b/liteflow-testcase-el/liteflow-testcase-el-sql-springboot/src/test/resources/sql/data.sql index dda527ee6..5900dfa0a 100644 --- a/liteflow-testcase-el/liteflow-testcase-el-sql-springboot/src/test/resources/sql/data.sql +++ b/liteflow-testcase-el/liteflow-testcase-el-sql-springboot/src/test/resources/sql/data.sql @@ -1,7 +1,7 @@ DELETE FROM EL_TABLE; INSERT INTO EL_TABLE (APPLICATION_NAME,CHAIN_NAME,EL_DATA) values ('demo','chain1','THEN(a, b, c);'); -INSERT INTO EL_TABLE (APPLICATION_NAME,CHAIN_NAME,EL_DATA) values ('demo','chain2','THEN(a, b, c);'); +INSERT INTO EL_TABLE (APPLICATION_NAME,CHAIN_NAME,EL_DATA) values ('demo','chain2','IF(x1, THEN(a, b));'); INSERT INTO EL_TABLE (APPLICATION_NAME,CHAIN_NAME,EL_DATA) values ('demo','chain3','IF(x0, THEN(a, b));'); INSERT INTO EL_TABLE (APPLICATION_NAME,CHAIN_NAME,EL_DATA) values ('demo','','IF(x0, THEN(a, b));'); INSERT INTO EL_TABLE (APPLICATION_NAME,CHAIN_NAME,EL_DATA) values ('demo','chain4','IF(x2, IF(x0, THEN(a, b)));'); @@ -9,6 +9,6 @@ INSERT INTO EL_TABLE (APPLICATION_NAME,CHAIN_NAME,EL_DATA) values ('demo','chain DELETE FROM SCRIPT_NODE_TABLE; INSERT INTO SCRIPT_NODE_TABLE (APPLICATION_NAME,SCRIPT_NODE_ID,SCRIPT_NODE_NAME,SCRIPT_NODE_TYPE,SCRIPT_NODE_DATA,SCRIPT_LANGUAGE) values ('demo','x0','if 脚本','if_script','return true','groovy'); -INSERT INTO SCRIPT_NODE_TABLE (APPLICATION_NAME,SCRIPT_NODE_ID,SCRIPT_NODE_NAME,SCRIPT_NODE_TYPE,SCRIPT_NODE_DATA,SCRIPT_LANGUAGE) values ('demo','x1','if 脚本','if_script','return false','groovy'); +INSERT INTO SCRIPT_NODE_TABLE (APPLICATION_NAME,SCRIPT_NODE_ID,SCRIPT_NODE_NAME,SCRIPT_NODE_TYPE,SCRIPT_NODE_DATA,SCRIPT_LANGUAGE) values ('demo','x1','if 脚本','if_script','return true','groovy'); INSERT INTO SCRIPT_NODE_TABLE (APPLICATION_NAME,SCRIPT_NODE_ID,SCRIPT_NODE_NAME,SCRIPT_NODE_TYPE,SCRIPT_NODE_DATA,SCRIPT_LANGUAGE) values ('demo','x2','python脚本','if_script','return true','js'); From ea7cbf8b098e8e682ab294fc5a66f6006847426c Mon Sep 17 00:00:00 2001 From: houxinyu Date: Fri, 22 Sep 2023 23:09:53 +0800 Subject: [PATCH 14/53] =?UTF-8?q?=E5=8E=BB=E9=99=A4=E5=A4=9A=E4=BD=99?= =?UTF-8?q?=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/yomahub/liteflow/parser/sql/util/ChainPollingTask.java | 2 -- .../com/yomahub/liteflow/parser/sql/util/ScriptPollingTask.java | 2 -- 2 files changed, 4 deletions(-) diff --git a/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/util/ChainPollingTask.java b/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/util/ChainPollingTask.java index 7e7172715..ac6b9be84 100644 --- a/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/util/ChainPollingTask.java +++ b/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/util/ChainPollingTask.java @@ -28,8 +28,6 @@ public class ChainPollingTask implements Runnable { private static final String SQL_PATTERN = "SELECT {},{} FROM {} WHERE {}=?"; - private static final String NEW_CHAIN_PATTERN = "SELECT {} FROM {} WHERE {}=? AND {}=?"; - private Connection conn; private SQLParserVO sqlParserVO; diff --git a/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/util/ScriptPollingTask.java b/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/util/ScriptPollingTask.java index 7e920e14c..5a68e6f7f 100644 --- a/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/util/ScriptPollingTask.java +++ b/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/util/ScriptPollingTask.java @@ -25,8 +25,6 @@ public class ScriptPollingTask implements Runnable { private static final String SQL_PATTERN = "SELECT {},{} FROM {} WHERE {}=?"; - private static final String NEW_SCRIPT_PATTERN = "SELECT {} FROM {} WHERE {}=? AND {}=?"; - private static final String CONCAT_PATTERN = "CONCAT_WS(':',{},{},{}) as script_concat"; private static final String CONCAT_WITH_LANGUAGE_PATTERN = "CONCAT_WS(':',{},{},{},{}) as script_concat"; From ca9449f531036fb572284dd1e1820e077e931759 Mon Sep 17 00:00:00 2001 From: luoyi <972849752@qq.com> Date: Fri, 22 Sep 2023 23:38:58 +0800 Subject: [PATCH 15/53] =?UTF-8?q?enhancement=20#I821F1=20=E5=A2=9E?= =?UTF-8?q?=E5=8A=A0=E6=B5=8B=E8=AF=95=E6=A1=88=E4=BE=8B=EF=BC=8C=E8=B0=83?= =?UTF-8?q?=E6=95=B4=E6=B3=A8=E9=87=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../yomahub/liteflow/core/FlowExecutor.java | 30 +++++++++- .../FlowInDifferentConfigTest.java | 31 ++++++++++ .../subflow/endlessLopp/FlowJsonTest.java | 29 ++++++++++ .../test/subflow/endlessLopp/FlowXMLTest.java | 29 ++++++++++ .../test/subflow/endlessLopp/FlowYMLTest.java | 29 ++++++++++ .../subflow/endlessLoop/flow-main.el.xml | 17 ++++++ .../subflow/endlessLoop/flow-sub1.el.xml | 6 ++ .../subflow/endlessLoop/flow.el.json | 58 +++++++++++++++++++ .../resources/subflow/endlessLoop/flow.el.xml | 25 ++++++++ .../resources/subflow/endlessLoop/flow.el.yml | 28 +++++++++ 10 files changed, 279 insertions(+), 3 deletions(-) create mode 100644 liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/java/com/yomahub/liteflow/test/subflow/endlessLopp/FlowInDifferentConfigTest.java create mode 100644 liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/java/com/yomahub/liteflow/test/subflow/endlessLopp/FlowJsonTest.java create mode 100644 liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/java/com/yomahub/liteflow/test/subflow/endlessLopp/FlowXMLTest.java create mode 100644 liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/java/com/yomahub/liteflow/test/subflow/endlessLopp/FlowYMLTest.java create mode 100644 liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/resources/subflow/endlessLoop/flow-main.el.xml create mode 100644 liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/resources/subflow/endlessLoop/flow-sub1.el.xml create mode 100644 liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/resources/subflow/endlessLoop/flow.el.json create mode 100644 liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/resources/subflow/endlessLoop/flow.el.xml create mode 100644 liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/resources/subflow/endlessLoop/flow.el.yml 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 f333a384e..fea85b472 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 @@ -216,53 +216,77 @@ public class FlowExecutor { } /** - * 检查 chain 的有效性,同时重新构建 FlowBus 的 chain,将调用的子 chain 连起来 + * 检查 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) { - // 判断 completedChainIdSet 中是否已经存在对应的 chain + + // 判断 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(StrUtil.format("There is a circular dependency in the chain[{}], please check carefully.", currentChain.getChainId())); + throw new CyclicDependencyException(errorMessage); + } + } // 此方法就是从原有的配置源主动拉取新的进行刷新 diff --git a/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/java/com/yomahub/liteflow/test/subflow/endlessLopp/FlowInDifferentConfigTest.java b/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/java/com/yomahub/liteflow/test/subflow/endlessLopp/FlowInDifferentConfigTest.java new file mode 100644 index 000000000..24d21cc48 --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/java/com/yomahub/liteflow/test/subflow/endlessLopp/FlowInDifferentConfigTest.java @@ -0,0 +1,31 @@ + +package com.yomahub.liteflow.test.subflow.endlessLopp; + +import com.yomahub.liteflow.core.FlowExecutorHolder; +import com.yomahub.liteflow.exception.CyclicDependencyException; +import com.yomahub.liteflow.property.LiteflowConfig; +import com.yomahub.liteflow.property.LiteflowConfigGetter; +import com.yomahub.liteflow.test.BaseTest; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + + +/** + * 测试多文件情况下 chain 死循环逻辑 + * + * @author luo yi + * @since 2.11.1 + */ +public class FlowInDifferentConfigTest extends BaseTest { + + // 测试 chain 死循环 + @Test + public void testChainEndlessLoop() { + Assertions.assertThrows(CyclicDependencyException.class, () -> { + LiteflowConfig config = LiteflowConfigGetter.get(); + config.setRuleSource("subflow/endlessLoop/flow-main.el.xml,subflow/endlessLoop/flow-sub1.el.xml"); + FlowExecutorHolder.loadInstance(config); + }); + } + +} diff --git a/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/java/com/yomahub/liteflow/test/subflow/endlessLopp/FlowJsonTest.java b/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/java/com/yomahub/liteflow/test/subflow/endlessLopp/FlowJsonTest.java new file mode 100644 index 000000000..12b6f8c42 --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/java/com/yomahub/liteflow/test/subflow/endlessLopp/FlowJsonTest.java @@ -0,0 +1,29 @@ +package com.yomahub.liteflow.test.subflow.endlessLopp; + +import com.yomahub.liteflow.core.FlowExecutorHolder; +import com.yomahub.liteflow.exception.CyclicDependencyException; +import com.yomahub.liteflow.property.LiteflowConfig; +import com.yomahub.liteflow.property.LiteflowConfigGetter; +import com.yomahub.liteflow.test.BaseTest; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +/** + * 测试 json 文件情况下 chain 死循环逻辑 + * + * @author luo yi + * @since 2.11.1 + */ +public class FlowJsonTest extends BaseTest { + + // 测试 chain 死循环 + @Test + public void testChainEndlessLoop() { + Assertions.assertThrows(CyclicDependencyException.class, () -> { + LiteflowConfig config = LiteflowConfigGetter.get(); + config.setRuleSource("subflow/endlessLoop/flow.el.json"); + FlowExecutorHolder.loadInstance(config); + }); + } + +} diff --git a/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/java/com/yomahub/liteflow/test/subflow/endlessLopp/FlowXMLTest.java b/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/java/com/yomahub/liteflow/test/subflow/endlessLopp/FlowXMLTest.java new file mode 100644 index 000000000..465c4b4f2 --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/java/com/yomahub/liteflow/test/subflow/endlessLopp/FlowXMLTest.java @@ -0,0 +1,29 @@ +package com.yomahub.liteflow.test.subflow.endlessLopp; + +import com.yomahub.liteflow.core.FlowExecutorHolder; +import com.yomahub.liteflow.exception.CyclicDependencyException; +import com.yomahub.liteflow.property.LiteflowConfig; +import com.yomahub.liteflow.property.LiteflowConfigGetter; +import com.yomahub.liteflow.test.BaseTest; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +/** + * 测试 xml 文件情况下 chain 死循环逻辑 + * + * @author luo yi + * @since 2.11.1 + */ +public class FlowXMLTest extends BaseTest { + + // 测试 chain 死循环 + @Test + public void testChainEndlessLoop() { + Assertions.assertThrows(CyclicDependencyException.class, () -> { + LiteflowConfig config = LiteflowConfigGetter.get(); + config.setRuleSource("subflow/endlessLoop/flow.el.xml"); + FlowExecutorHolder.loadInstance(config); + }); + } + +} diff --git a/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/java/com/yomahub/liteflow/test/subflow/endlessLopp/FlowYMLTest.java b/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/java/com/yomahub/liteflow/test/subflow/endlessLopp/FlowYMLTest.java new file mode 100644 index 000000000..e586b7d8e --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/java/com/yomahub/liteflow/test/subflow/endlessLopp/FlowYMLTest.java @@ -0,0 +1,29 @@ +package com.yomahub.liteflow.test.subflow.endlessLopp; + +import com.yomahub.liteflow.core.FlowExecutorHolder; +import com.yomahub.liteflow.exception.CyclicDependencyException; +import com.yomahub.liteflow.property.LiteflowConfig; +import com.yomahub.liteflow.property.LiteflowConfigGetter; +import com.yomahub.liteflow.test.BaseTest; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +/** + * 测试 yml 文件情况下 chain 死循环逻辑 + * + * @author luo yi + * @since 2.11.1 + */ +public class FlowYMLTest extends BaseTest { + + // 测试 chain 死循环 + @Test + public void testChainEndlessLoop() { + Assertions.assertThrows(CyclicDependencyException.class, () -> { + LiteflowConfig config = LiteflowConfigGetter.get(); + config.setRuleSource("subflow/endlessLoop/flow.el.yml"); + FlowExecutorHolder.loadInstance(config); + }); + } + +} diff --git a/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/resources/subflow/endlessLoop/flow-main.el.xml b/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/resources/subflow/endlessLoop/flow-main.el.xml new file mode 100644 index 000000000..4f479f6e5 --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/resources/subflow/endlessLoop/flow-main.el.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + THEN(a, b, chain2); + + \ No newline at end of file diff --git a/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/resources/subflow/endlessLoop/flow-sub1.el.xml b/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/resources/subflow/endlessLoop/flow-sub1.el.xml new file mode 100644 index 000000000..39b89324e --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/resources/subflow/endlessLoop/flow-sub1.el.xml @@ -0,0 +1,6 @@ + + + + THEN(b, a, chain1); + + \ No newline at end of file diff --git a/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/resources/subflow/endlessLoop/flow.el.json b/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/resources/subflow/endlessLoop/flow.el.json new file mode 100644 index 000000000..e1012cc73 --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/resources/subflow/endlessLoop/flow.el.json @@ -0,0 +1,58 @@ +{ + "flow": { + "nodes": { + "node": [ + { + "id": "a", + "class": "com.yomahub.liteflow.test.subflow.cmp1.ACmp" + }, + { + "id": "b", + "class": "com.yomahub.liteflow.test.subflow.cmp1.BCmp" + }, + { + "id": "c", + "class": "com.yomahub.liteflow.test.subflow.cmp1.CCmp" + }, + { + "id": "d", + "class": "com.yomahub.liteflow.test.subflow.cmp1.DCmp" + }, + { + "id": "e", + "class": "com.yomahub.liteflow.test.subflow.cmp1.ECmp" + }, + { + "id": "f", + "class": "com.yomahub.liteflow.test.subflow.cmp2.FCmp" + }, + { + "id": "g", + "class": "com.yomahub.liteflow.test.subflow.cmp2.GCmp" + }, + { + "id": "h", + "class": "com.yomahub.liteflow.test.subflow.cmp2.HCmp" + }, + { + "id": "M", + "class": "com.yomahub.liteflow.test.subflow.cmp2.MCmp" + } + ] + }, + "chain": [ + { + "name": "chain7", + "value": "THEN(a, chain8);" + }, + { + "name": "chain8", + "value": "THEN(b, chain9);" + }, + { + "name": "chain9", + "value": "WHEN(c, chain7);" + } + ] + } +} \ No newline at end of file diff --git a/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/resources/subflow/endlessLoop/flow.el.xml b/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/resources/subflow/endlessLoop/flow.el.xml new file mode 100644 index 000000000..38120c94f --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/resources/subflow/endlessLoop/flow.el.xml @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + THEN(a, chain2); + + + + THEN(b, chain3); + + + + THEN(c, chain1); + + \ No newline at end of file diff --git a/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/resources/subflow/endlessLoop/flow.el.yml b/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/resources/subflow/endlessLoop/flow.el.yml new file mode 100644 index 000000000..efdf7b431 --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/resources/subflow/endlessLoop/flow.el.yml @@ -0,0 +1,28 @@ +flow: + nodes: + node: + - id: a + class: com.yomahub.liteflow.test.subflow.cmp1.ACmp + - id: b + class: com.yomahub.liteflow.test.subflow.cmp1.BCmp + - id: c + class: com.yomahub.liteflow.test.subflow.cmp1.CCmp + - id: d + class: com.yomahub.liteflow.test.subflow.cmp1.DCmp + - id: e + class: com.yomahub.liteflow.test.subflow.cmp1.ECmp + - id: f + class: com.yomahub.liteflow.test.subflow.cmp2.FCmp + - id: g + class: com.yomahub.liteflow.test.subflow.cmp2.GCmp + - id: h + class: com.yomahub.liteflow.test.subflow.cmp2.HCmp + - id: h + class: com.yomahub.liteflow.test.subflow.cmp2.MCmp + chain: + - name: chain4 + value: "THEN(a, chain5);" + - name: chain5 + value: "THEN(b, chain6);" + - name: chain6 + value: "THEN(c, chain5);" \ No newline at end of file From 570b95c84fddcda7546c6eb114eae7df232a881f Mon Sep 17 00:00:00 2001 From: luoyi <972849752@qq.com> Date: Fri, 22 Sep 2023 23:40:41 +0800 Subject: [PATCH 16/53] =?UTF-8?q?enhancement=20#I821F1=20=E8=B0=83?= =?UTF-8?q?=E6=95=B4=E6=B5=8B=E8=AF=95=E6=A1=88=E4=BE=8B=E7=89=88=E6=9C=AC?= =?UTF-8?q?=E5=8F=B7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../endlessLoop/FlowInDifferentConfigELSpringbootTest.java | 2 +- .../test/subflow/endlessLoop/FlowJsonELSpringBootTest.java | 2 +- .../test/subflow/endlessLoop/FlowXMLELSpringBootTest.java | 2 +- .../test/subflow/endlessLoop/FlowYmlELSpringBootTest.java | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/subflow/endlessLoop/FlowInDifferentConfigELSpringbootTest.java b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/subflow/endlessLoop/FlowInDifferentConfigELSpringbootTest.java index 331297ab3..ca5ea0fed 100644 --- a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/subflow/endlessLoop/FlowInDifferentConfigELSpringbootTest.java +++ b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/subflow/endlessLoop/FlowInDifferentConfigELSpringbootTest.java @@ -16,7 +16,7 @@ import javax.annotation.Resource; * 测试多文件情况下 chain 死循环逻辑 * * @author luo yi - * @since 2.11.0 + * @since 2.11.1 */ @TestPropertySource(value = "classpath:/subflow/endlessLoop/application-subInDifferentConfig1.properties") @SpringBootTest(classes = FlowInDifferentConfigELSpringbootTest.class) diff --git a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/subflow/endlessLoop/FlowJsonELSpringBootTest.java b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/subflow/endlessLoop/FlowJsonELSpringBootTest.java index 3a9a01a53..b0d97aa1b 100644 --- a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/subflow/endlessLoop/FlowJsonELSpringBootTest.java +++ b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/subflow/endlessLoop/FlowJsonELSpringBootTest.java @@ -16,7 +16,7 @@ import javax.annotation.Resource; * 测试 json 文件情况下 chain 死循环逻辑 * * @author luo yi - * @since 2.11.0 + * @since 2.11.1 */ @TestPropertySource(value = "classpath:/subflow/endlessLoop/application-json.properties") @SpringBootTest(classes = FlowJsonELSpringBootTest.class) diff --git a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/subflow/endlessLoop/FlowXMLELSpringBootTest.java b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/subflow/endlessLoop/FlowXMLELSpringBootTest.java index f686e4150..6543f63d3 100644 --- a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/subflow/endlessLoop/FlowXMLELSpringBootTest.java +++ b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/subflow/endlessLoop/FlowXMLELSpringBootTest.java @@ -16,7 +16,7 @@ import javax.annotation.Resource; * 测试 xml 文件情况下 chain 死循环逻辑 * * @author luo yi - * @since 2.11.0 + * @since 2.11.1 */ @TestPropertySource(value = "classpath:/subflow/endlessLoop/application-xml.properties") @SpringBootTest(classes = FlowXMLELSpringBootTest.class) diff --git a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/subflow/endlessLoop/FlowYmlELSpringBootTest.java b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/subflow/endlessLoop/FlowYmlELSpringBootTest.java index b0829cb26..f9a6d8f75 100644 --- a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/subflow/endlessLoop/FlowYmlELSpringBootTest.java +++ b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/subflow/endlessLoop/FlowYmlELSpringBootTest.java @@ -16,7 +16,7 @@ import javax.annotation.Resource; * 测试 yml 文件情况下 chain 死循环逻辑 * * @author luo yi - * @since 2.11.0 + * @since 2.11.1 */ @TestPropertySource(value = "classpath:/subflow/endlessLoop/application-yml.properties") @SpringBootTest(classes = FlowYmlELSpringBootTest.class) From be932d158489b8938131bbba4431eb38d4e01d30 Mon Sep 17 00:00:00 2001 From: houxinyu Date: Sat, 23 Sep 2023 17:25:46 +0800 Subject: [PATCH 17/53] =?UTF-8?q?=E4=BC=98=E5=8C=96SQL=E8=BD=AE=E8=AF=A2?= =?UTF-8?q?=E6=B5=8B=E8=AF=95=E7=94=A8=E4=BE=8B=E9=83=A8=E5=88=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../SQLWithXmlELSpringbootPollingTest.java | 18 ++++++++++++++- .../liteflow/test/sql/cmp/refresh.java | 22 +++++++++++++++++++ 2 files changed, 39 insertions(+), 1 deletion(-) create mode 100644 liteflow-testcase-el/liteflow-testcase-el-sql-springboot/src/test/java/com/yomahub/liteflow/test/sql/cmp/refresh.java diff --git a/liteflow-testcase-el/liteflow-testcase-el-sql-springboot/src/test/java/com/yomahub/liteflow/test/sql/SQLWithXmlELSpringbootPollingTest.java b/liteflow-testcase-el/liteflow-testcase-el-sql-springboot/src/test/java/com/yomahub/liteflow/test/sql/SQLWithXmlELSpringbootPollingTest.java index e358fe2e3..caf288ca7 100644 --- a/liteflow-testcase-el/liteflow-testcase-el-sql-springboot/src/test/java/com/yomahub/liteflow/test/sql/SQLWithXmlELSpringbootPollingTest.java +++ b/liteflow-testcase-el/liteflow-testcase-el-sql-springboot/src/test/java/com/yomahub/liteflow/test/sql/SQLWithXmlELSpringbootPollingTest.java @@ -90,7 +90,9 @@ public class SQLWithXmlELSpringbootPollingTest extends BaseTest { // 新増script insertScriptData(); - Thread.sleep(4000); + Thread.sleep(2500); + insertChainData(); + Thread.sleep(2500); response = flowExecutor.execute2Resp("chain6", "arg"); DefaultContext context = response.getFirstContextBean(); Assertions.assertEquals("a==>x3[x3脚本]", response.getExecuteStepStrWithoutTime()); @@ -169,6 +171,20 @@ public class SQLWithXmlELSpringbootPollingTest extends BaseTest { Statement statement = connection.createStatement(); statement.executeUpdate( "INSERT INTO SCRIPT_NODE_TABLE (APPLICATION_NAME,SCRIPT_NODE_ID,SCRIPT_NODE_NAME,SCRIPT_NODE_TYPE,SCRIPT_NODE_DATA,SCRIPT_LANGUAGE) values ('demo','x3','x3脚本','script','defaultContext.setData(\"test\",\"hello\");','groovy');"); + } + catch (SQLException e) { + throw new ELSQLException(e.getMessage()); + } + } + + private void insertChainData() { + LiteflowConfig liteflowConfig = LiteflowConfigGetter.get(); + SQLParserVO sqlParserVO = JsonUtil.parseObject(liteflowConfig.getRuleSourceExtData(), SQLParserVO.class); + Connection connection; + try { + connection = DriverManager.getConnection(sqlParserVO.getUrl(), sqlParserVO.getUsername(), + sqlParserVO.getPassword()); + Statement statement = connection.createStatement(); statement.executeUpdate( "INSERT INTO EL_TABLE (APPLICATION_NAME,CHAIN_NAME,EL_DATA) values ('demo','chain6','THEN(a, x3);');"); } diff --git a/liteflow-testcase-el/liteflow-testcase-el-sql-springboot/src/test/java/com/yomahub/liteflow/test/sql/cmp/refresh.java b/liteflow-testcase-el/liteflow-testcase-el-sql-springboot/src/test/java/com/yomahub/liteflow/test/sql/cmp/refresh.java new file mode 100644 index 000000000..70d7f7a0b --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-sql-springboot/src/test/java/com/yomahub/liteflow/test/sql/cmp/refresh.java @@ -0,0 +1,22 @@ +package com.yomahub.liteflow.test.sql.cmp; + +import com.yomahub.liteflow.core.FlowInitHook; +import com.yomahub.liteflow.flow.FlowBus; +import com.yomahub.liteflow.property.LiteflowConfigGetter; +import com.yomahub.liteflow.spi.holder.SpiFactoryCleaner; +import com.yomahub.liteflow.spring.ComponentScanner; +import com.yomahub.liteflow.thread.ExecutorHelper; +import org.junit.jupiter.api.Test; + +public class refresh { + + @Test + public void cleanScanCache() { + ComponentScanner.cleanCache(); + FlowBus.cleanCache(); + ExecutorHelper.loadInstance().clearExecutorServiceMap(); + SpiFactoryCleaner.clean(); + LiteflowConfigGetter.clean(); + FlowInitHook.cleanHook(); + } +} From 09a3b32d80f5590eaf464a13308f2360e20f515c Mon Sep 17 00:00:00 2001 From: "everywhere.z" Date: Sun, 24 Sep 2023 12:12:03 +0800 Subject: [PATCH 18/53] =?UTF-8?q?=E7=89=88=E6=9C=AC=E5=8F=B7=E6=9B=B4?= =?UTF-8?q?=E6=96=B0=E6=88=90v2.11.1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index b17900eb1..7f9815e97 100644 --- a/pom.xml +++ b/pom.xml @@ -39,7 +39,7 @@ - 2.11.0 + 2.11.1 UTF-8 UTF-8 8 From 048058641f4ebfd4981170b852cec7501a698e3a Mon Sep 17 00:00:00 2001 From: "everywhere.z" Date: Sun, 24 Sep 2023 12:12:30 +0800 Subject: [PATCH 19/53] =?UTF-8?q?=E5=AF=B9=E6=95=B0=E6=8D=AE=E5=BA=93?= =?UTF-8?q?=E8=BD=AE=E8=AF=A2=E7=9A=84=E9=BB=98=E8=AE=A4=E9=97=B4=E9=9A=94?= =?UTF-8?q?=E6=97=B6=E9=97=B4=E8=B0=83=E6=95=B4=E6=88=9060=E7=A7=92?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/yomahub/liteflow/parser/sql/vo/SQLParserVO.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/vo/SQLParserVO.java b/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/vo/SQLParserVO.java index 2e7bf0cd0..b15d68b72 100644 --- a/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/vo/SQLParserVO.java +++ b/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/vo/SQLParserVO.java @@ -94,7 +94,7 @@ public class SQLParserVO { private Boolean pollingEnabled = false; /*轮询时间间隔(s) 默认120s*/ - private Integer pollingIntervalSeconds = 120; + private Integer pollingIntervalSeconds = 60; /*规则配置后首次轮询的起始时间 默认为60s*/ private Integer pollingStartSeconds = 60; 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 20/53] =?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 175bb282f3797ca25c93351494fcc6f0072aa950 Mon Sep 17 00:00:00 2001 From: "everywhere.z" Date: Mon, 25 Sep 2023 17:31:19 +0800 Subject: [PATCH 21/53] =?UTF-8?q?=E4=BC=98=E5=8C=96=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/com/yomahub/liteflow/flow/element/Condition.java | 3 +++ 1 file changed, 3 insertions(+) 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..e9e22c4bb 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 @@ -120,10 +120,12 @@ public abstract class Condition implements Executable{ public abstract ConditionTypeEnum getConditionType(); + @Override public String getId() { return id; } + @Override public void setId(String id) { this.id = id; } @@ -133,6 +135,7 @@ public abstract class Condition implements Executable{ return tag; } + @Override public void setTag(String tag) { this.tag = tag; } From 49a677e45b549e219adb0dfb31b53f196b28c319 Mon Sep 17 00:00:00 2001 From: "everywhere.z" Date: Mon, 25 Sep 2023 17:37:09 +0800 Subject: [PATCH 22/53] =?UTF-8?q?=E4=BC=98=E5=8C=96=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/com/yomahub/liteflow/core/NodeComponent.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/core/NodeComponent.java b/liteflow-core/src/main/java/com/yomahub/liteflow/core/NodeComponent.java index 35f19f765..3df459ac6 100644 --- a/liteflow-core/src/main/java/com/yomahub/liteflow/core/NodeComponent.java +++ b/liteflow-core/src/main/java/com/yomahub/liteflow/core/NodeComponent.java @@ -87,10 +87,10 @@ public abstract class NodeComponent { Class clazz = this.getClass(); try { Method method = clazz.getDeclaredMethod("rollback"); - if(ObjectUtil.isNotNull(method)) + if(ObjectUtil.isNotNull(method)){ this.setRollback(true); - } catch (Exception e) { - } + } + } catch (Exception ignored) {} } public void execute() throws Exception { From 9108c8fa75a9c2c4bd6fac68857b3de86350931e Mon Sep 17 00:00:00 2001 From: rain <672378783@qq.com> Date: Mon, 25 Sep 2023 20:12:36 +0800 Subject: [PATCH 23/53] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E5=9B=9E=E6=BB=9A?= =?UTF-8?q?=E7=BB=84=E4=BB=B6=E6=97=A0=E6=B3=95=E8=8E=B7=E5=BE=97tag?= =?UTF-8?q?=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/yomahub/liteflow/core/FlowExecutor.java | 2 +- .../com/yomahub/liteflow/core/NodeComponent.java | 2 ++ .../com/yomahub/liteflow/flow/entity/CmpStep.java | 13 +++++++++++++ 3 files changed, 16 insertions(+), 1 deletion(-) 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 830ad1025..8c1068d1a 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 @@ -441,7 +441,7 @@ public class FlowExecutor { while(cmpStepIterator.hasNext()) { CmpStep cmpStep = cmpStepIterator.next(); if(cmpStep.getInstance().isRollback()) { - Rollbackable rollbackItem = new Node(cmpStep.getInstance()); + Rollbackable rollbackItem = cmpStep.getRefNode(); rollbackItem.rollback(slotIndex); } } diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/core/NodeComponent.java b/liteflow-core/src/main/java/com/yomahub/liteflow/core/NodeComponent.java index 3df459ac6..2ecca94ca 100644 --- a/liteflow-core/src/main/java/com/yomahub/liteflow/core/NodeComponent.java +++ b/liteflow-core/src/main/java/com/yomahub/liteflow/core/NodeComponent.java @@ -100,6 +100,7 @@ public abstract class NodeComponent { CmpStep cmpStep = new CmpStep(nodeId, name, CmpStepTypeEnum.SINGLE); cmpStep.setTag(this.getTag()); cmpStep.setInstance(this); + cmpStep.setRefNode(this.getRefNode()); slot.addStep(cmpStep); StopWatch stopWatch = new StopWatch(); @@ -158,6 +159,7 @@ public abstract class NodeComponent { CmpStep cmpStep = new CmpStep(nodeId, name, CmpStepTypeEnum.SINGLE); cmpStep.setTag(this.getTag()); + cmpStep.setInstance(this); slot.addRollbackStep(cmpStep); StopWatch stopWatch = new StopWatch(); diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/flow/entity/CmpStep.java b/liteflow-core/src/main/java/com/yomahub/liteflow/flow/entity/CmpStep.java index eacc479e9..f5eff5165 100644 --- a/liteflow-core/src/main/java/com/yomahub/liteflow/flow/entity/CmpStep.java +++ b/liteflow-core/src/main/java/com/yomahub/liteflow/flow/entity/CmpStep.java @@ -12,6 +12,7 @@ import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.StrUtil; import com.yomahub.liteflow.core.NodeComponent; import com.yomahub.liteflow.enums.CmpStepTypeEnum; +import com.yomahub.liteflow.flow.element.Node; /** * 组件步骤对象 @@ -43,6 +44,10 @@ public class CmpStep { // 回滚消耗的时间 private Long rollbackTimeSpent; + // 当前执行的node + private Node refNode; + + public CmpStep(String nodeId, String nodeName, CmpStepTypeEnum stepType) { this.nodeId = nodeId; this.nodeName = nodeName; @@ -113,6 +118,14 @@ public class CmpStep { this.rollbackTimeSpent = rollbackTimeSpent; } + public Node getRefNode() { + return refNode; + } + + public void setRefNode(Node refNode) { + this.refNode = refNode; + } + public String buildString() { if (stepType.equals(CmpStepTypeEnum.SINGLE)) { if (StrUtil.isBlank(nodeName)) { From a5592a2696e6554f31f1723373d0c223e886259f Mon Sep 17 00:00:00 2001 From: "everywhere.z" Date: Tue, 26 Sep 2023 14:56:35 +0800 Subject: [PATCH 24/53] =?UTF-8?q?=E5=AF=B9janino=E7=9A=84=E7=BC=96?= =?UTF-8?q?=E8=AF=91=E7=BA=A7=E5=88=AB=E8=BF=9B=E8=A1=8C=E8=AE=BE=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/yomahub/liteflow/script/java/JavaExecutor.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/liteflow-script-plugin/liteflow-script-java/src/main/java/com/yomahub/liteflow/script/java/JavaExecutor.java b/liteflow-script-plugin/liteflow-script-java/src/main/java/com/yomahub/liteflow/script/java/JavaExecutor.java index cdec58a2e..b0693fda4 100644 --- a/liteflow-script-plugin/liteflow-script-java/src/main/java/com/yomahub/liteflow/script/java/JavaExecutor.java +++ b/liteflow-script-plugin/liteflow-script-java/src/main/java/com/yomahub/liteflow/script/java/JavaExecutor.java @@ -16,12 +16,11 @@ public class JavaExecutor extends ScriptExecutor { private final Map compiledScriptMap = new CopyOnWriteHashMap<>(); - - @Override public void load(String nodeId, String script) { try{ IScriptEvaluator se = CompilerFactoryFactory.getDefaultCompilerFactory(this.getClass().getClassLoader()).newScriptEvaluator(); + se.setTargetVersion(8); se.setReturnType(Object.class); se.setParameters(new String[] {"_meta"}, new Class[] {ScriptExecuteWrap.class}); se.cook(convertScript(script)); @@ -40,7 +39,7 @@ public class JavaExecutor extends ScriptExecutor { throw new ScriptLoadException(errorMsg); } IScriptEvaluator se = compiledScriptMap.get(wrap.getNodeId()); - return se.evaluate(wrap); + return se.evaluate(new Object[]{wrap}); } @Override From 73ae02a84c8f1c9d4f55d0c8b3cbda389e3449f4 Mon Sep 17 00:00:00 2001 From: "everywhere.z" Date: Tue, 26 Sep 2023 14:57:09 +0800 Subject: [PATCH 25/53] =?UTF-8?q?=E5=8D=87=E7=BA=A7janino=E7=9A=84?= =?UTF-8?q?=E7=89=88=E6=9C=AC=EF=BC=8C=E5=B9=B6=E4=BF=AE=E6=94=B9janino?= =?UTF-8?q?=E7=9A=84=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 --- .../pom.xml | 5 +++++ .../src/test/resources/common/flow.xml | 11 ++++++----- pom.xml | 2 +- 3 files changed, 12 insertions(+), 6 deletions(-) diff --git a/liteflow-testcase-el/liteflow-testcase-el-script-java-springboot/pom.xml b/liteflow-testcase-el/liteflow-testcase-el-script-java-springboot/pom.xml index 2b450a298..3c50140b2 100644 --- a/liteflow-testcase-el/liteflow-testcase-el-script-java-springboot/pom.xml +++ b/liteflow-testcase-el/liteflow-testcase-el-script-java-springboot/pom.xml @@ -28,6 +28,11 @@ org.springframework.boot spring-boot-starter-test + + com.alibaba.fastjson2 + fastjson2 + 2.0.39 + \ No newline at end of file diff --git a/liteflow-testcase-el/liteflow-testcase-el-script-java-springboot/src/test/resources/common/flow.xml b/liteflow-testcase-el/liteflow-testcase-el-script-java-springboot/src/test/resources/common/flow.xml index 0bb72ea6d..a4ca812ad 100644 --- a/liteflow-testcase-el/liteflow-testcase-el-script-java-springboot/src/test/resources/common/flow.xml +++ b/liteflow-testcase-el/liteflow-testcase-el-script-java-springboot/src/test/resources/common/flow.xml @@ -4,21 +4,22 @@ 1.3.5 3.21.0 5.8.18 - 3.1.9 + 3.1.10 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 26/53] =?UTF-8?q?enhancement=20#I821F1=20=E4=BD=BF?= =?UTF-8?q?=E7=94=A8=20Jackson=20=E5=BA=8F=E5=88=97=E5=8C=96=E5=AF=B9?= =?UTF-8?q?=E8=B1=A1=E6=A3=80=E6=B5=8B=20chain=20=E6=98=AF=E5=90=A6?= =?UTF-8?q?=E5=AD=98=E5=9C=A8=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 9473efb81..616988d77 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 fea85b472..830ad1025 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 5d90e3c16..59a4674d5 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; From 5785c59b95fb4d73dee71cd083d13db2f695a8a3 Mon Sep 17 00:00:00 2001 From: luoyi <972849752@qq.com> Date: Wed, 27 Sep 2023 20:57:53 +0800 Subject: [PATCH 27/53] =?UTF-8?q?enhancement=20#I821F1=20=E8=A1=A5?= =?UTF-8?q?=E5=85=85=E6=B3=A8=E9=87=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../yomahub/liteflow/builder/el/LiteFlowChainELBuilder.java | 3 +-- .../src/main/java/com/yomahub/liteflow/flow/element/Node.java | 1 + 2 files changed, 2 insertions(+), 2 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 616988d77..cb6fd7748 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 @@ -202,9 +202,8 @@ public class LiteFlowChainELBuilder { 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())); + throw new CyclicDependencyException(StrUtil.format("There is a circular dependency in the chain[{}], please check carefully.", chain.getChainId(), e)); } else { throw new ParseException(e.getMessage()); } 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 59a4674d5..269a4dd62 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 @@ -47,6 +47,7 @@ public class Node implements Executable, Cloneable, Rollbackable{ private String language; + // 增加该注解,避免在使用 Jackson 序列化检测循环引用时出现不必要异常 @JsonIgnore private NodeComponent instance; From 8d9099dcba2f3534f6972da3465c1e6d2158bec5 Mon Sep 17 00:00:00 2001 From: luoyi <972849752@qq.com> Date: Wed, 27 Sep 2023 22:53:36 +0800 Subject: [PATCH 28/53] =?UTF-8?q?enhancement=20#I84XNE=20WHEN=20=E7=9A=84?= =?UTF-8?q?=20must=20=E8=AF=AD=E6=B3=95=E5=8F=AF=E6=8C=87=E5=AE=9A?= =?UTF-8?q?=E5=A4=9A=E4=B8=AA=E4=BB=BB=E5=8A=A1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../builder/el/operator/MustOperator.java | 13 ++++++- .../flow/element/condition/WhenCondition.java | 13 ++++--- .../strategy/SpecifyParallelExecutor.java | 37 +++++++++++++------ .../asyncNode/AsyncNodeELSpringbootTest.java | 9 +++++ .../src/test/resources/asyncNode/flow.el.xml | 4 ++ 5 files changed, 57 insertions(+), 19 deletions(-) diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/MustOperator.java b/liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/MustOperator.java index cb018c529..e859cd8bc 100644 --- a/liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/MustOperator.java +++ b/liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/MustOperator.java @@ -1,10 +1,15 @@ package com.yomahub.liteflow.builder.el.operator; +import cn.hutool.core.util.StrUtil; import com.yomahub.liteflow.builder.el.operator.base.BaseOperator; import com.yomahub.liteflow.builder.el.operator.base.OperatorHelper; import com.yomahub.liteflow.enums.ParallelStrategyEnum; import com.yomahub.liteflow.flow.element.condition.WhenCondition; +import java.util.Arrays; +import java.util.Set; +import java.util.stream.Collectors; + /** * EL 规则中的 must 的操作符 * @@ -19,8 +24,12 @@ public class MustOperator extends BaseOperator { WhenCondition whenCondition = OperatorHelper.convert(objects[0], WhenCondition.class); - String specifyId = OperatorHelper.convert(objects[1], String.class); - whenCondition.setSpecifyId(specifyId); + String specifyIds = OperatorHelper.convert(objects[1], String.class); + + // 解析指定完成的任务 ID 集合 + Set specifyIdSet = Arrays.stream(specifyIds.replace(StrUtil.SPACE, StrUtil.EMPTY).split(",")).collect(Collectors.toSet()); + + whenCondition.setSpecifyIdSet(specifyIdSet); whenCondition.setParallelStrategy(ParallelStrategyEnum.SPECIFY); return whenCondition; } diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/flow/element/condition/WhenCondition.java b/liteflow-core/src/main/java/com/yomahub/liteflow/flow/element/condition/WhenCondition.java index 7422a495e..15eb31cbd 100644 --- a/liteflow-core/src/main/java/com/yomahub/liteflow/flow/element/condition/WhenCondition.java +++ b/liteflow-core/src/main/java/com/yomahub/liteflow/flow/element/condition/WhenCondition.java @@ -17,6 +17,7 @@ import com.yomahub.liteflow.log.LFLog; import com.yomahub.liteflow.log.LFLoggerManager; import com.yomahub.liteflow.thread.ExecutorHelper; +import java.util.Set; import java.util.concurrent.TimeUnit; /** @@ -38,8 +39,8 @@ public class WhenCondition extends Condition { // 当前 When 对应并行策略,默认为 ALL private ParallelStrategyEnum parallelStrategy; - // 只有 must 条件下,才会赋值 specifyId - private String specifyId; + // 只有 must 条件下,才会赋值 specifyIdSet + private Set specifyIdSet; // when单独的线程池名称 private String threadExecutorClass; @@ -96,12 +97,12 @@ public class WhenCondition extends Condition { this.parallelStrategy = parallelStrategy; } - public String getSpecifyId() { - return specifyId; + public Set getSpecifyIdSet() { + return specifyIdSet; } - public void setSpecifyId(String specifyId) { - this.specifyId = specifyId; + public void setSpecifyIdSet(Set specifyIdSet) { + this.specifyIdSet = specifyIdSet; } public String getThreadExecutorClass() { diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/flow/parallel/strategy/SpecifyParallelExecutor.java b/liteflow-core/src/main/java/com/yomahub/liteflow/flow/parallel/strategy/SpecifyParallelExecutor.java index 9474232d4..e397608ec 100644 --- a/liteflow-core/src/main/java/com/yomahub/liteflow/flow/parallel/strategy/SpecifyParallelExecutor.java +++ b/liteflow-core/src/main/java/com/yomahub/liteflow/flow/parallel/strategy/SpecifyParallelExecutor.java @@ -1,14 +1,13 @@ package com.yomahub.liteflow.flow.parallel.strategy; -import cn.hutool.core.util.ObjUtil; +import cn.hutool.core.collection.CollUtil; import com.yomahub.liteflow.flow.element.condition.FinallyCondition; import com.yomahub.liteflow.flow.element.condition.PreCondition; import com.yomahub.liteflow.flow.element.condition.WhenCondition; import com.yomahub.liteflow.flow.parallel.WhenFutureObj; import com.yomahub.liteflow.thread.ExecutorHelper; -import java.util.ArrayList; -import java.util.List; +import java.util.*; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutorService; @@ -31,8 +30,14 @@ public class SpecifyParallelExecutor extends ParallelStrategyExecutor { // 此方法其实只会初始化一次Executor,不会每次都会初始化。Executor 是唯一的 ExecutorService parallelExecutor = ExecutorHelper.loadInstance().buildWhenExecutor(whenCondition.getThreadExecutorClass()); - // 指定任务 - final CompletableFuture[] specifyTask = { null }; + // 指定完成的任务 + CompletableFuture specifyTask; + + // 已存在的任务 ID 集合 + Set exitingTaskIdSet = new HashSet<>(); + + // 指定任务列表,可以为 0 或者多个 + List> specifyTaskList = new ArrayList<>(); // 所有任务集合 List> allTaskList = new ArrayList<>(); @@ -53,22 +58,32 @@ public class SpecifyParallelExecutor extends ParallelStrategyExecutor { // 处理 task,封装成 CompletableFuture 对象 CompletableFuture completableFutureTask = wrappedFutureObj(executable, parallelExecutor, whenCondition, currChainName, slotIndex); // 存在 must 指定 ID 的 task,且该任务只会有一个或者没有 - if (whenCondition.getSpecifyId().equals(executable.getId())) { + if (whenCondition.getSpecifyIdSet().contains(executable.getId())) { // 设置指定任务 future 对象 - specifyTask[0] = completableFutureTask; + specifyTaskList.add(completableFutureTask); + // 记录已存在的任务 ID + exitingTaskIdSet.add(executable.getId()); } // 组合所有任务 allTaskList.add(completableFutureTask); }); - if (ObjUtil.isNull(specifyTask[0])) { - LOG.warn("The specified task[{}] was not found, waiting for all tasks to complete by default.", whenCondition.getSpecifyId()); + if (CollUtil.isEmpty(specifyTaskList)) { + LOG.warn("The specified task{} was not found, waiting for all tasks to complete by default.", whenCondition.getSpecifyIdSet()); // 不存在指定任务,则需要等待所有任务都执行完成 - specifyTask[0] = CompletableFuture.allOf(allTaskList.toArray(new CompletableFuture[] {})); + specifyTask = CompletableFuture.allOf(allTaskList.toArray(new CompletableFuture[] {})); + } else { + // 判断 specifyIdSet 中有哪些任务是不存在的,给出提示 + Collection absentTaskIdSet = CollUtil.subtract(whenCondition.getSpecifyIdSet(), exitingTaskIdSet); + if (CollUtil.isNotEmpty(absentTaskIdSet)) { + LOG.warn("The specified task{} was not found, you need to define and register it.", absentTaskIdSet); + } + // 将指定要完成的任务通过 allOf 合成一个 CompletableFuture,表示需要等待 must 方法里面所有任务完成 + specifyTask = CompletableFuture.allOf(specifyTaskList.toArray(new CompletableFuture[]{})); } // 结果处理 - this.handleTaskResult(whenCondition, slotIndex, allTaskList, specifyTask[0]); + this.handleTaskResult(whenCondition, slotIndex, allTaskList, specifyTask); } diff --git a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/asyncNode/AsyncNodeELSpringbootTest.java b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/asyncNode/AsyncNodeELSpringbootTest.java index 99f9e1d97..541a2fe38 100644 --- a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/asyncNode/AsyncNodeELSpringbootTest.java +++ b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/asyncNode/AsyncNodeELSpringbootTest.java @@ -175,4 +175,13 @@ public class AsyncNodeELSpringbootTest extends BaseTest { Assertions.assertTrue(context.getData("check").toString().startsWith("akbc")); } + // 测试 must 指定多个任务, ignoreError 以及 id 关键字 + @Test + public void testAsyncFlow13() throws Exception { + LiteflowResponse response = flowExecutor.execute2Resp("chain13", "it's a base request"); + DefaultContext context = response.getFirstContextBean(); + Assertions.assertTrue(response.isSuccess()); + Assertions.assertTrue(context.getData("check").toString().startsWith("akbgc")); + } + } diff --git a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/asyncNode/flow.el.xml b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/asyncNode/flow.el.xml index e48bf988e..79523e4e5 100644 --- a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/asyncNode/flow.el.xml +++ b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/asyncNode/flow.el.xml @@ -62,4 +62,8 @@ THEN(WHEN(d, g, l, a, THEN(k, b).id("z")).ignoreError(true).must("z"), c); + + THEN(WHEN(d, g, l, a, THEN(k, b).id("z")).ignoreError(true).must("z, g, task1, task2"), c); + + \ No newline at end of file From f857c67a16e450f122478ba29ff4538fb3b1bae9 Mon Sep 17 00:00:00 2001 From: houxinyu Date: Thu, 28 Sep 2023 15:27:42 +0800 Subject: [PATCH 29/53] =?UTF-8?q?=E4=BC=98=E5=8C=96SQL=E8=84=9A=E6=9C=AC?= =?UTF-8?q?=E8=BD=AE=E8=AF=A2=E5=87=BD=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../parser/sql/util/ScriptPollingTask.java | 39 ++++++++++++------- .../SQLWithXmlELSpringbootPollingTest.java | 2 +- 2 files changed, 25 insertions(+), 16 deletions(-) diff --git a/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/util/ScriptPollingTask.java b/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/util/ScriptPollingTask.java index 5a68e6f7f..0c8c10653 100644 --- a/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/util/ScriptPollingTask.java +++ b/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/util/ScriptPollingTask.java @@ -23,13 +23,9 @@ import java.util.*; */ public class ScriptPollingTask implements Runnable { - private static final String SQL_PATTERN = "SELECT {},{} FROM {} WHERE {}=?"; + private static final String SCRIPT_PATTERN = "SELECT {},{},{},{} FROM {} WHERE {}=?"; - private static final String CONCAT_PATTERN = "CONCAT_WS(':',{},{},{}) as script_concat"; - - private static final String CONCAT_WITH_LANGUAGE_PATTERN = "CONCAT_WS(':',{},{},{},{}) as script_concat"; - - private static final String SCRIPT_KEY_FIELD = "script_concat"; + private static final String SCRIPT_PATTERN_WITH_LANGUAGE = "SELECT {},{},{},{},{} FROM {} WHERE {}=?"; private Connection conn; @@ -62,14 +58,16 @@ public class ScriptPollingTask implements Runnable { String applicationName = sqlParserVO.getApplicationName(); String scriptLanguageField = sqlParserVO.getScriptLanguageField(); - String KeyField; + String sqlCmd = null; if (StrUtil.isNotBlank(scriptLanguageField)) { - KeyField = StrUtil.format(CONCAT_WITH_LANGUAGE_PATTERN, scriptIdField, scriptTypeField, scriptNameField, scriptLanguageField); + //脚本有语言 + sqlCmd = StrUtil.format(SCRIPT_PATTERN_WITH_LANGUAGE, scriptDataField, scriptIdField, scriptTypeField, scriptNameField, + scriptLanguageField, scriptTableName, scriptApplicationNameField); } else { - KeyField = StrUtil.format(CONCAT_PATTERN, scriptIdField, scriptTypeField, scriptNameField); + sqlCmd = StrUtil.format(SCRIPT_PATTERN, scriptDataField, scriptIdField, scriptTypeField, scriptNameField, + scriptTableName, scriptApplicationNameField); } - String sqlCmd = StrUtil.format(SQL_PATTERN, KeyField, scriptDataField, scriptTableName, scriptApplicationNameField); stmt = conn.prepareStatement(sqlCmd, ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY); // 设置游标拉取数量 stmt.setFetchSize(FETCH_SIZE_MAX); @@ -79,7 +77,7 @@ public class ScriptPollingTask implements Runnable { Set newScriptSet = new HashSet<>(); while (rs.next()) { - String scriptKey = getStringFromResultSet(rs, SCRIPT_KEY_FIELD); + String scriptKey = getScriptKeyFromRS(rs, sqlParserVO); String newData = getStringFromResultSet(rs, scriptDataField); String newSHA = DigestUtil.sha1Hex(newData); newScriptSet.add(scriptKey); @@ -92,8 +90,7 @@ public class ScriptPollingTask implements Runnable { //加入到shaMap scriptSHAMap.put(scriptKey, newSHA); - } - else if (!StrUtil.equals(newSHA, scriptSHAMap.get(scriptKey))) { + } else if (!StrUtil.equals(newSHA, scriptSHAMap.get(scriptKey))) { //SHA值发生变化,表示该script的值已被修改,重新拉取变化的script NodeConvertHelper.NodeSimpleVO scriptVO = NodeConvertHelper.convert(scriptKey); //修改script @@ -106,7 +103,7 @@ public class ScriptPollingTask implements Runnable { //SHA值无变化,表示该chain未改变 } - if(scriptSHAMap.size() > newScriptSet.size()) { + if (scriptSHAMap.size() > newScriptSet.size()) { //如果遍历prepareStatement后修改过的SHAMap数量比最新script总数多, 说明有两种情况: // 1、删除了script // 2、修改了script的id/name/type:因为遍历到新的script_key时会加到SHAMap里,但没有机会删除旧的script @@ -114,7 +111,7 @@ public class ScriptPollingTask implements Runnable { //在此处遍历scriptSHAMap,把不在newScriptSet中的script删除 //这里用iterator是为避免在遍历集合时删除元素导致ConcurrentModificationException Iterator iterator = scriptSHAMap.keySet().iterator(); - while(iterator.hasNext()){ + while (iterator.hasNext()) { String scriptKey = iterator.next(); if (!newScriptSet.contains(scriptKey)) { NodeConvertHelper.NodeSimpleVO scriptVO = NodeConvertHelper.convert(scriptKey); @@ -142,4 +139,16 @@ public class ScriptPollingTask implements Runnable { } return data; } + + private String getScriptKeyFromRS(ResultSet rs, SQLParserVO sqlParserVO) throws SQLException { + String id = getStringFromResultSet(rs, sqlParserVO.getScriptIdField()); + String type = getStringFromResultSet(rs, sqlParserVO.getScriptTypeField()); + String name = getStringFromResultSet(rs, sqlParserVO.getScriptNameField()); + String scriptKey = StrUtil.join(":", id, type, name); + if (StrUtil.isNotBlank(sqlParserVO.getScriptLanguageField())) { + String language = getStringFromResultSet(rs, sqlParserVO.getScriptLanguageField()); + scriptKey = StrUtil.join(":", id, type, name, language); + } + return scriptKey; + } } diff --git a/liteflow-testcase-el/liteflow-testcase-el-sql-springboot/src/test/java/com/yomahub/liteflow/test/sql/SQLWithXmlELSpringbootPollingTest.java b/liteflow-testcase-el/liteflow-testcase-el-sql-springboot/src/test/java/com/yomahub/liteflow/test/sql/SQLWithXmlELSpringbootPollingTest.java index caf288ca7..e907cc2ab 100644 --- a/liteflow-testcase-el/liteflow-testcase-el-sql-springboot/src/test/java/com/yomahub/liteflow/test/sql/SQLWithXmlELSpringbootPollingTest.java +++ b/liteflow-testcase-el/liteflow-testcase-el-sql-springboot/src/test/java/com/yomahub/liteflow/test/sql/SQLWithXmlELSpringbootPollingTest.java @@ -148,7 +148,7 @@ public class SQLWithXmlELSpringbootPollingTest extends BaseTest { Statement statement = connection.createStatement(); //修改script data statement.executeUpdate( - "UPDATE SCRIPT_NODE_TABLE SET SCRIPT_NODE_DATA='return false;' WHERE SCRIPT_NODE_ID='x1'"); + "UPDATE SCRIPT_NODE_TABLE SET SCRIPT_NODE_DATA='return false' WHERE SCRIPT_NODE_ID='x1'"); //修改script名 statement.executeUpdate( "UPDATE SCRIPT_NODE_TABLE SET SCRIPT_NODE_NAME='x0_script' WHERE SCRIPT_NODE_ID='x0'"); From 91dc95684e8365416847484fdb256df90919d04e Mon Sep 17 00:00:00 2001 From: gaibu <1016771049@qq.com> Date: Thu, 28 Sep 2023 13:30:28 +0800 Subject: [PATCH 30/53] =?UTF-8?q?sql=20=E6=8F=92=E4=BB=B6=E9=87=8D?= =?UTF-8?q?=E6=9E=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../liteflow/parser/constant/ReadType.java | 14 + .../parser/constant/SqlReadConstant.java | 32 ++ .../liteflow/parser/sql/SQLXmlELParser.java | 4 + .../sql/polling/AbstractSqlReadPollTask.java | 98 ++++++ .../parser/sql/polling/SqlReadPollTask.java | 18 + .../sql/polling/impl/ChainReadPollTask.java | 56 +++ .../sql/polling/impl/ScriptReadPollTask.java | 50 +++ .../parser/sql/read/AbstractSqlRead.java | 98 ++++++ .../liteflow/parser/sql/read/SqlRead.java | 20 ++ .../parser/sql/read/SqlReadFactory.java | 48 +++ .../parser/sql/read/impl/ChainRead.java | 68 ++++ .../parser/sql/read/impl/ScriptRead.java | 151 ++++++++ .../parser/sql/util/ChainPollingTask.java | 126 ------- .../liteflow/parser/sql/util/JDBCHelper.java | 333 +++--------------- .../parser/sql/util/ScriptPollingTask.java | 145 -------- .../liteflow/parser/sql/vo/SQLParserVO.java | 25 +- 16 files changed, 730 insertions(+), 556 deletions(-) create mode 100644 liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/constant/ReadType.java create mode 100644 liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/constant/SqlReadConstant.java create mode 100644 liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/polling/AbstractSqlReadPollTask.java create mode 100644 liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/polling/SqlReadPollTask.java create mode 100644 liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/polling/impl/ChainReadPollTask.java create mode 100644 liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/polling/impl/ScriptReadPollTask.java create mode 100644 liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/read/AbstractSqlRead.java create mode 100644 liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/read/SqlRead.java create mode 100644 liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/read/SqlReadFactory.java create mode 100644 liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/read/impl/ChainRead.java create mode 100644 liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/read/impl/ScriptRead.java delete mode 100644 liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/util/ChainPollingTask.java delete mode 100644 liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/util/ScriptPollingTask.java diff --git a/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/constant/ReadType.java b/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/constant/ReadType.java new file mode 100644 index 000000000..a687d53d1 --- /dev/null +++ b/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/constant/ReadType.java @@ -0,0 +1,14 @@ +package com.yomahub.liteflow.parser.constant; + +/** + * Copyright (C), 2021, 北京同创永益科技发展有限公司 + * + * @author tangkc + * @version 3.0.0 + * @description + * @date 2023/9/28 11:43 + */ +public enum ReadType { + CHAIN, + SCRIPT; +} diff --git a/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/constant/SqlReadConstant.java b/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/constant/SqlReadConstant.java new file mode 100644 index 000000000..127bc0084 --- /dev/null +++ b/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/constant/SqlReadConstant.java @@ -0,0 +1,32 @@ +package com.yomahub.liteflow.parser.constant; + +/** + * Copyright (C), 2021, 北京同创永益科技发展有限公司 + * + * @author tangkc + * @version 3.0.0 + * @description + * @date 2023/9/28 11:42 + */ +public class SqlReadConstant { + + public static final String SQL_PATTERN = "SELECT {},{} FROM {} WHERE {}=?"; + + public static final String SCRIPT_SQL_CHECK_PATTERN = "SELECT 1 FROM {} "; + + public static final String SCRIPT_SQL_PATTERN = "SELECT {},{},{},{} FROM {} WHERE {}=?"; + + public static final String SCRIPT_WITH_LANGUAGE_SQL_PATTERN = "SELECT {},{},{},{},{} FROM {} WHERE {}=?"; + + public static final String CHAIN_XML_PATTERN = ""; + + public static final String NODE_XML_PATTERN = "{}"; + + public static final String NODE_ITEM_XML_PATTERN = ""; + + public static final String NODE_ITEM_WITH_LANGUAGE_XML_PATTERN = ""; + + public static final String XML_PATTERN = "{}{}"; + + public static final Integer FETCH_SIZE_MAX = 1000; +} diff --git a/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/SQLXmlELParser.java b/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/SQLXmlELParser.java index 98fa7f640..13301dbd5 100644 --- a/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/SQLXmlELParser.java +++ b/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/SQLXmlELParser.java @@ -8,6 +8,7 @@ import cn.hutool.core.util.StrUtil; import com.yomahub.liteflow.core.FlowInitHook; import com.yomahub.liteflow.parser.el.ClassXmlFlowELParser; import com.yomahub.liteflow.parser.sql.exception.ELSQLException; +import com.yomahub.liteflow.parser.sql.read.SqlReadFactory; import com.yomahub.liteflow.parser.sql.util.JDBCHelper; import com.yomahub.liteflow.parser.sql.vo.SQLParserVO; import com.yomahub.liteflow.property.LiteflowConfig; @@ -53,6 +54,9 @@ public class SQLXmlELParser extends ClassXmlFlowELParser { // 初始化 JDBCHelper JDBCHelper.init(sqlParserVO); + + // 初始化 SqlReadFactory + SqlReadFactory.registerRead(sqlParserVO); } catch (ELSQLException elsqlException) { throw elsqlException; diff --git a/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/polling/AbstractSqlReadPollTask.java b/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/polling/AbstractSqlReadPollTask.java new file mode 100644 index 000000000..1fc75902d --- /dev/null +++ b/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/polling/AbstractSqlReadPollTask.java @@ -0,0 +1,98 @@ +package com.yomahub.liteflow.parser.sql.polling; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.map.MapUtil; +import cn.hutool.core.util.StrUtil; +import cn.hutool.crypto.digest.DigestUtil; +import com.yomahub.liteflow.parser.sql.exception.ELSQLException; +import com.yomahub.liteflow.parser.sql.read.SqlRead; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; + +/** + * Copyright (C), 2021, 北京同创永益科技发展有限公司 + * + * @author tangkc + * @version 3.0.0 + * @description + * @date 2023/9/28 14:12 + */ +public abstract class AbstractSqlReadPollTask implements SqlReadPollTask { + private final Map DATA_SHA_MAP; + private final SqlRead read; + + public AbstractSqlReadPollTask(Map dataMap, SqlRead read) { + this.read = read; + this.DATA_SHA_MAP = shaMapValue(dataMap); + + if (!read.type().equals(type())) { + throw new ELSQLException("SqlReadPollTask type not match"); + } + } + + @Override + public void execute() { + Map newData = read.read(); + // 新增或者更新的元素 + Map saveElementMap = new HashMap(); + // 删除的元素 + List deleteElementIds = new ArrayList<>(); + + for (Map.Entry entry : newData.entrySet()) { + String id = entry.getKey(); + String element = entry.getValue(); + String newSHA = DigestUtil.sha1Hex(element); + + // 新增 + // 如果封装的SHAMap中不存在该chain, 表示该元素为新增 + if (!DATA_SHA_MAP.containsKey(id)) { + saveElementMap.put(id, element); + + DATA_SHA_MAP.put(id, newSHA); + } + // 修改 + // SHA值发生变化,表示该元素的值已被修改,重新拉取变化的chain + else if (!StrUtil.equals(newSHA, DATA_SHA_MAP.get(id))) { + saveElementMap.put(id, element); + + DATA_SHA_MAP.put(id, newSHA); + } + } + + Set oldIdList = DATA_SHA_MAP.keySet(); // 旧的 id 列表 + Set newIdList = newData.keySet(); // 新的 id 列表 + // 计算单差集 + // 计算集合的单差集,即只返回【newIdList】中有,但是【oldIdList】中没有的元素,例如: + // subtractToList([1,2,3,4],[2,3,4,5]) -》 [1] + deleteElementIds = CollUtil.subtractToList(newIdList, oldIdList); + + for (String id : deleteElementIds) { + DATA_SHA_MAP.remove(id); + } + + if (CollUtil.isNotEmpty(saveElementMap)) { + doSave(saveElementMap); + } + + if (CollUtil.isNotEmpty(deleteElementIds)) { + doDelete(deleteElementIds); + } + } + + public abstract void doSave(Map saveElementMap); + + public abstract void doDelete(List deleteElementId); + + private Map shaMapValue(Map dataMap) { + Map result = new HashMap<>(); + dataMap.forEach((k, v) -> { + result.put(k, DigestUtil.sha1Hex(v)); + }); + + return result; + } +} diff --git a/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/polling/SqlReadPollTask.java b/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/polling/SqlReadPollTask.java new file mode 100644 index 000000000..898dbfb21 --- /dev/null +++ b/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/polling/SqlReadPollTask.java @@ -0,0 +1,18 @@ +package com.yomahub.liteflow.parser.sql.polling; + +import com.yomahub.liteflow.parser.constant.ReadType; + +/** + * Copyright (C), 2021, 北京同创永益科技发展有限公司 + * + * @author tangkc + * @version 3.0.0 + * @description + * @date 2023/9/28 14:10 + */ +public interface SqlReadPollTask { + + void execute(); + + ReadType type(); +} diff --git a/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/polling/impl/ChainReadPollTask.java b/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/polling/impl/ChainReadPollTask.java new file mode 100644 index 000000000..1eaac11c4 --- /dev/null +++ b/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/polling/impl/ChainReadPollTask.java @@ -0,0 +1,56 @@ +package com.yomahub.liteflow.parser.sql.polling.impl; + +import com.yomahub.liteflow.builder.el.LiteFlowChainELBuilder; +import com.yomahub.liteflow.flow.FlowBus; +import com.yomahub.liteflow.parser.constant.ReadType; +import com.yomahub.liteflow.parser.helper.ParserHelper; +import com.yomahub.liteflow.parser.sql.polling.AbstractSqlReadPollTask; +import com.yomahub.liteflow.parser.sql.polling.SqlReadPollTask; +import com.yomahub.liteflow.parser.sql.read.SqlRead; +import org.dom4j.Document; +import org.dom4j.DocumentHelper; + +import java.util.List; +import java.util.Map; +import java.util.Optional; + +import static com.yomahub.liteflow.common.ChainConstant.ID; +import static com.yomahub.liteflow.common.ChainConstant.NAME; + +/** + * Copyright (C), 2021, 北京同创永益科技发展有限公司 + * + * @author tangkc + * @version 3.0.0 + * @description + * @date 2023/9/28 14:46 + */ +public class ChainReadPollTask extends AbstractSqlReadPollTask { + + public ChainReadPollTask(Map dataMap, SqlRead read) { + super(dataMap, read); + } + + @Override + public void doSave(Map saveElementMap) { + for (Map.Entry entry : saveElementMap.entrySet()) { + String chainName = entry.getKey(); + String newData = entry.getValue(); + + LiteFlowChainELBuilder.createChain().setChainId(chainName).setEL(newData).build(); + } + } + + @Override + public void doDelete(List deleteElementId) { + for (String id : deleteElementId) { + FlowBus.removeChain(id); + } + } + + @Override + public ReadType type() { + return ReadType.CHAIN; + } + +} diff --git a/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/polling/impl/ScriptReadPollTask.java b/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/polling/impl/ScriptReadPollTask.java new file mode 100644 index 000000000..41dd5b4c4 --- /dev/null +++ b/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/polling/impl/ScriptReadPollTask.java @@ -0,0 +1,50 @@ +package com.yomahub.liteflow.parser.sql.polling.impl; + +import com.yomahub.liteflow.flow.FlowBus; +import com.yomahub.liteflow.parser.constant.ReadType; +import com.yomahub.liteflow.parser.helper.NodeConvertHelper; +import com.yomahub.liteflow.parser.sql.polling.AbstractSqlReadPollTask; +import com.yomahub.liteflow.parser.sql.read.SqlRead; + +import java.util.List; +import java.util.Map; + +/** + * Copyright (C), 2021, 北京同创永益科技发展有限公司 + * + * @author tangkc + * @version 3.0.0 + * @description + * @date 2023/9/28 15:03 + */ +public class ScriptReadPollTask extends AbstractSqlReadPollTask { + public ScriptReadPollTask(Map dataMap, SqlRead read) { + super(dataMap, read); + } + + @Override + public void doSave(Map saveElementMap) { + for (Map.Entry entry : saveElementMap.entrySet()) { + String scriptKey = entry.getKey(); + String newData = entry.getValue(); + + NodeConvertHelper.NodeSimpleVO scriptVO = NodeConvertHelper.convert(scriptKey); + NodeConvertHelper.changeScriptNode(scriptVO, newData); + } + } + + @Override + public void doDelete(List deleteElementId) { + for (String id : deleteElementId) { + NodeConvertHelper.NodeSimpleVO scriptVO = NodeConvertHelper.convert(id); + + // 删除script + FlowBus.getNodeMap().remove(scriptVO.getNodeId()); + } + } + + @Override + public ReadType type() { + return ReadType.SCRIPT; + } +} diff --git a/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/read/AbstractSqlRead.java b/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/read/AbstractSqlRead.java new file mode 100644 index 000000000..e917a6161 --- /dev/null +++ b/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/read/AbstractSqlRead.java @@ -0,0 +1,98 @@ +package com.yomahub.liteflow.parser.sql.read; + +import cn.hutool.core.util.StrUtil; +import com.yomahub.liteflow.log.LFLog; +import com.yomahub.liteflow.log.LFLoggerManager; +import com.yomahub.liteflow.parser.constant.SqlReadConstant; +import com.yomahub.liteflow.parser.sql.exception.ELSQLException; +import com.yomahub.liteflow.parser.sql.read.impl.ScriptRead; +import com.yomahub.liteflow.parser.sql.util.LiteFlowJdbcUtil; +import com.yomahub.liteflow.parser.sql.vo.SQLParserVO; + +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.HashMap; +import java.util.Map; + +/** + * Copyright (C), 2021, 北京同创永益科技发展有限公司 + * + * @author tangkc + * @version 3.0.0 + * @description + * @date 2023/9/28 11:26 + */ +public abstract class AbstractSqlRead implements SqlRead { + public final SQLParserVO config; + private static LFLog LOG = LFLoggerManager.getLogger(AbstractSqlRead.class); + + public AbstractSqlRead(SQLParserVO config) { + this.config = config; + } + + @Override + public Map read() { + // 如果不需要读取直接返回 + if (!needRead()) { + return new HashMap<>(); + } + + Map result = new HashMap<>(); + String sqlCmd = buildQuerySql(); + if (config.getSqlLogEnabled()) { + LOG.info("query sql:{}", sqlCmd.replace("?", "'" + config.getApplicationName() + "'")); + } + + Connection conn = null; + PreparedStatement stmt = null; + ResultSet rs = null; + try { + conn = LiteFlowJdbcUtil.getConn(config); + stmt = conn.prepareStatement(sqlCmd, ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY); + // 设置游标拉取数量 + stmt.setFetchSize(SqlReadConstant.FETCH_SIZE_MAX); + stmt.setString(1, config.getApplicationName()); + rs = stmt.executeQuery(); + + while (rs.next()) { + String xml = buildXmlElement(rs); + String uniqueKey = buildXmlElementUniqueKey(rs); + + result.put(uniqueKey, xml); + } + } catch (Exception e) { + throw new ELSQLException(e.getMessage()); + } finally { + // 关闭连接 + LiteFlowJdbcUtil.close(conn, stmt, rs); + } + + return result; + } + + public abstract String buildQuerySql(); + + public abstract String buildXmlElement(ResultSet rs) throws SQLException; + + public abstract String buildXmlElementUniqueKey(ResultSet rs) throws SQLException; + + /** + * 是否可以读取 + * chain 默认可以读取 + * script 需要判断是否有配置 + */ + public boolean needRead() { + return true; + } + + + public String getStringFromResultSet(ResultSet rs, String field) throws SQLException { + String data = rs.getString(field); + if (StrUtil.isBlank(data)) { + throw new ELSQLException(StrUtil.format("exist {} field value is empty", field)); + } + return data; + } +} diff --git a/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/read/SqlRead.java b/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/read/SqlRead.java new file mode 100644 index 000000000..c94c54570 --- /dev/null +++ b/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/read/SqlRead.java @@ -0,0 +1,20 @@ +package com.yomahub.liteflow.parser.sql.read; + +import com.yomahub.liteflow.parser.constant.ReadType; + +import java.util.Map; + +/** + * Copyright (C), 2021, 北京同创永益科技发展有限公司 + * + * @author tangkc + * @version 3.0.0 + * @description + * @date 2023/9/28 11:25 + */ +public interface SqlRead { + + Map read(); + + ReadType type(); +} diff --git a/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/read/SqlReadFactory.java b/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/read/SqlReadFactory.java new file mode 100644 index 000000000..4f4f531e4 --- /dev/null +++ b/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/read/SqlReadFactory.java @@ -0,0 +1,48 @@ +package com.yomahub.liteflow.parser.sql.read; + +import com.yomahub.liteflow.parser.constant.ReadType; +import com.yomahub.liteflow.parser.sql.polling.SqlReadPollTask; +import com.yomahub.liteflow.parser.sql.polling.impl.ChainReadPollTask; +import com.yomahub.liteflow.parser.sql.polling.impl.ScriptReadPollTask; +import com.yomahub.liteflow.parser.sql.read.impl.ChainRead; +import com.yomahub.liteflow.parser.sql.read.impl.ScriptRead; +import com.yomahub.liteflow.parser.sql.vo.SQLParserVO; + +import java.util.HashMap; +import java.util.Map; + +/** + * Copyright (C), 2021, 北京同创永益科技发展有限公司 + * + * @author tangkc + * @version 3.0.0 + * @description + * @date 2023/9/28 15:42 + */ +public class SqlReadFactory { + private static final Map READ_MAP = new HashMap<>(); + private static final Map POLL_TASK_MAP = new HashMap<>(); + + public static void registerRead(SQLParserVO config) { + READ_MAP.put(ReadType.CHAIN, new ChainRead(config)); + READ_MAP.put(ReadType.SCRIPT, new ScriptRead(config)); + } + + public static void registerSqlReadPollTask(ReadType readType, Map dataMap) { + SqlRead sqlRead = getSqlRead(readType); + if (ReadType.CHAIN.equals(readType)) { + POLL_TASK_MAP.put(ReadType.CHAIN, new ChainReadPollTask(dataMap, sqlRead)); + } else if (ReadType.SCRIPT.equals(readType)) { + POLL_TASK_MAP.put(ReadType.SCRIPT, new ScriptReadPollTask(dataMap, sqlRead)); + } + + } + + public static SqlRead getSqlRead(ReadType readType) { + return READ_MAP.get(readType); + } + + public static SqlReadPollTask getSqlReadPollTask(ReadType readType) { + return POLL_TASK_MAP.get(readType); + } +} diff --git a/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/read/impl/ChainRead.java b/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/read/impl/ChainRead.java new file mode 100644 index 000000000..a8c776b3e --- /dev/null +++ b/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/read/impl/ChainRead.java @@ -0,0 +1,68 @@ +package com.yomahub.liteflow.parser.sql.read.impl; + +import cn.hutool.core.util.StrUtil; +import cn.hutool.core.util.XmlUtil; +import com.yomahub.liteflow.parser.constant.ReadType; +import com.yomahub.liteflow.parser.constant.SqlReadConstant; +import com.yomahub.liteflow.parser.sql.exception.ELSQLException; +import com.yomahub.liteflow.parser.sql.read.AbstractSqlRead; +import com.yomahub.liteflow.parser.sql.vo.SQLParserVO; + +import java.sql.ResultSet; +import java.sql.SQLException; + +/** + * Copyright (C), 2021, 北京同创永益科技发展有限公司 + * + * @author tangkc + * @version 3.0.0 + * @description + * @date 2023/9/28 11:44 + */ +public class ChainRead extends AbstractSqlRead { + + public ChainRead(SQLParserVO config) { + super(config); + } + + @Override + public String buildQuerySql() { + String chainTableName = super.config.getChainTableName(); + String elDataField = super.config.getElDataField(); + String chainNameField = super.config.getChainNameField(); + String chainApplicationNameField = super.config.getChainApplicationNameField(); + String applicationName = super.config.getApplicationName(); + + if (StrUtil.isBlank(chainTableName)) { + throw new ELSQLException("You did not define the chainTableName property"); + } + + if (StrUtil.isBlank(applicationName) || StrUtil.isBlank(chainApplicationNameField)) { + throw new ELSQLException("You did not define the applicationName or chainApplicationNameField property"); + } + + String sqlCmd = StrUtil.format(SqlReadConstant.SQL_PATTERN, chainNameField, elDataField, chainTableName, + chainApplicationNameField); + + return sqlCmd; + } + + @Override + public String buildXmlElement(ResultSet rs) throws SQLException { + String elDataField = super.config.getElDataField(); + + return getStringFromResultSet(rs, elDataField); + } + + @Override + public String buildXmlElementUniqueKey(ResultSet rs) throws SQLException { + String chainNameField = super.config.getChainNameField(); + + return getStringFromResultSet(rs, chainNameField); + } + + @Override + public ReadType type() { + return ReadType.CHAIN; + } +} diff --git a/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/read/impl/ScriptRead.java b/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/read/impl/ScriptRead.java new file mode 100644 index 000000000..8c04d5086 --- /dev/null +++ b/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/read/impl/ScriptRead.java @@ -0,0 +1,151 @@ +package com.yomahub.liteflow.parser.sql.read.impl; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.StrUtil; +import cn.hutool.core.util.XmlUtil; +import com.yomahub.liteflow.enums.NodeTypeEnum; +import com.yomahub.liteflow.enums.ScriptTypeEnum; +import com.yomahub.liteflow.log.LFLog; +import com.yomahub.liteflow.log.LFLoggerManager; +import com.yomahub.liteflow.parser.constant.ReadType; +import com.yomahub.liteflow.parser.constant.SqlReadConstant; +import com.yomahub.liteflow.parser.sql.exception.ELSQLException; +import com.yomahub.liteflow.parser.sql.read.AbstractSqlRead; +import com.yomahub.liteflow.parser.sql.util.LiteFlowJdbcUtil; +import com.yomahub.liteflow.parser.sql.vo.SQLParserVO; + +import java.sql.Connection; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.List; +import java.util.Objects; + +/** + * Copyright (C), 2021, 北京同创永益科技发展有限公司 + * + * @author tangkc + * @version 3.0.0 + * @description + * @date 2023/9/28 11:49 + */ +public class ScriptRead extends AbstractSqlRead { + + public ScriptRead(SQLParserVO config) { + super(config); + } + + @Override + public String buildQuerySql() { + String scriptLanguageField = super.config.getScriptLanguageField(); + String scriptTableName = super.config.getScriptTableName(); + String scriptIdField = super.config.getScriptIdField(); + String scriptDataField = super.config.getScriptDataField(); + String scriptNameField = super.config.getScriptNameField(); + String scriptTypeField = super.config.getScriptTypeField(); + String scriptApplicationNameField = super.config.getScriptApplicationNameField(); + String applicationName = super.config.getApplicationName(); + + if (StrUtil.isBlank(applicationName) || StrUtil.isBlank(scriptApplicationNameField)) { + throw new ELSQLException("You did not define the applicationName or scriptApplicationNameField property"); + } + + String sqlCmd = null; + // 脚本节点(带语言) + if (withLanguage()) { + sqlCmd = StrUtil.format( + SqlReadConstant.SCRIPT_WITH_LANGUAGE_SQL_PATTERN, + scriptIdField, + scriptDataField, + scriptNameField, + scriptTypeField, + scriptLanguageField, + scriptTableName, + scriptApplicationNameField + ); + + return sqlCmd; + } + // 脚本节点(不带语言) + else { + sqlCmd = StrUtil.format( + SqlReadConstant.SCRIPT_SQL_PATTERN, + scriptIdField, + scriptDataField, + scriptNameField, + scriptTypeField, + scriptTableName, + scriptApplicationNameField + ); + } + + + return sqlCmd; + } + + @Override + public String buildXmlElement(ResultSet rs) throws SQLException { + String scriptDataField = super.config.getScriptDataField(); + + return getStringFromResultSet(rs, scriptDataField); + + } + + @Override + public String buildXmlElementUniqueKey(ResultSet rs) throws SQLException { + String scriptIdField = super.config.getScriptIdField(); + String scriptNameField = super.config.getScriptNameField(); + String scriptTypeField = super.config.getScriptTypeField(); + String scriptLanguageField = super.config.getScriptLanguageField(); + + String id = getStringFromResultSet(rs, scriptIdField); + String name = getStringFromResultSet(rs, scriptNameField); + String type = getStringFromResultSet(rs, scriptTypeField); + String language = withLanguage() ? getStringFromResultSet(rs, scriptLanguageField) : null; + + NodeTypeEnum nodeTypeEnum = NodeTypeEnum.getEnumByCode(type); + if (Objects.isNull(nodeTypeEnum)) { + throw new ELSQLException(StrUtil.format("Invalid type value[{}]", type)); + } + + if (!nodeTypeEnum.isScript()) { + throw new ELSQLException(StrUtil.format("The type value[{}] is not a script type", type)); + } + + if (withLanguage() && !ScriptTypeEnum.checkScriptType(language)) { + throw new ELSQLException(StrUtil.format("The language value[{}] is invalid", language)); + } + List keys = CollUtil.newArrayList(id, type, name); + if (StrUtil.isNotBlank(language)) { + keys.add(language); + } + + return StrUtil.join(StrUtil.COLON, keys); + } + + @Override + public boolean needRead() { + if (StrUtil.isBlank(super.config.getScriptTableName())) { + return false; + } + + String sqlCmd = StrUtil.format( + SqlReadConstant.SCRIPT_SQL_CHECK_PATTERN, + super.config.getScriptTableName() + ); + + Connection conn = LiteFlowJdbcUtil.getConn(super.config); + return LiteFlowJdbcUtil.checkConnectionCanExecuteSql(conn, sqlCmd); + } + + @Override + public ReadType type() { + return ReadType.SCRIPT; + } + + /** + * 脚本是否带语言 + */ + private boolean withLanguage() { + return StrUtil.isNotBlank(super.config.getScriptLanguageField()); + } +} diff --git a/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/util/ChainPollingTask.java b/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/util/ChainPollingTask.java deleted file mode 100644 index ac6b9be84..000000000 --- a/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/util/ChainPollingTask.java +++ /dev/null @@ -1,126 +0,0 @@ -package com.yomahub.liteflow.parser.sql.util; - -import cn.hutool.core.util.StrUtil; -import cn.hutool.crypto.digest.DigestUtil; -import com.yomahub.liteflow.builder.el.LiteFlowChainELBuilder; -import com.yomahub.liteflow.flow.FlowBus; -import com.yomahub.liteflow.log.LFLog; -import com.yomahub.liteflow.log.LFLoggerManager; -import com.yomahub.liteflow.parser.sql.exception.ELSQLException; -import com.yomahub.liteflow.parser.sql.vo.SQLParserVO; - -import java.sql.Connection; -import java.sql.PreparedStatement; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.util.HashSet; -import java.util.Iterator; -import java.util.Map; -import java.util.Set; - -/** - * 用于轮询chain的定时任务 - * - * @author hxinyu - * @since 2.11.1 - */ -public class ChainPollingTask implements Runnable { - - private static final String SQL_PATTERN = "SELECT {},{} FROM {} WHERE {}=?"; - - private Connection conn; - - private SQLParserVO sqlParserVO; - - private Map chainSHAMap; - - private static final Integer FETCH_SIZE_MAX = 1000; - - LFLog LOG = LFLoggerManager.getLogger(ChainPollingTask.class); - - public ChainPollingTask(SQLParserVO sqlParserVO, Map chainSHAMap) { - this.sqlParserVO = sqlParserVO; - this.chainSHAMap = chainSHAMap; - } - - @Override - public void run() { - conn = LiteFlowJdbcUtil.getConn(sqlParserVO); - PreparedStatement stmt = null; - ResultSet rs = null; - try{ - String chainTableName = sqlParserVO.getChainTableName(); - String elDataField = sqlParserVO.getElDataField(); - String chainNameField = sqlParserVO.getChainNameField(); - String chainApplicationNameField = sqlParserVO.getChainApplicationNameField(); - String applicationName = sqlParserVO.getApplicationName(); - - String sqlCmd = StrUtil.format(SQL_PATTERN, chainNameField, elDataField, chainTableName, - chainApplicationNameField); - stmt = conn.prepareStatement(sqlCmd, ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY); - // 设置游标拉取数量 - stmt.setFetchSize(FETCH_SIZE_MAX); - stmt.setString(1, applicationName); - rs = stmt.executeQuery(); - - Set newChainSet = new HashSet<>(); - - while(rs.next()) { - String chainName = getStringFromResultSet(rs, chainNameField); - String newData = getStringFromResultSet(rs, elDataField); - String newSHA = DigestUtil.sha1Hex(newData); - newChainSet.add(chainName); - //如果封装的SHAMap中不存在该chain, 表示该chain为新增 - if(!chainSHAMap.containsKey(chainName)) { - //新增chain - LiteFlowChainELBuilder.createChain().setChainId(chainName).setEL(newData).build(); - LOG.info("starting reload flow config... create chain={}, new value={},", chainName, newData); - //加入到shaMap - chainSHAMap.put(chainName, newSHA); - - } - else if (!StrUtil.equals(newSHA, chainSHAMap.get(chainName))) { - //SHA值发生变化,表示该chain的值已被修改,重新拉取变化的chain - //修改chain - LiteFlowChainELBuilder.createChain().setChainId(chainName).setEL(newData).build(); - LOG.info("starting reload flow config... update chain={}, new value={},", chainName, newData); - //修改shaMap - chainSHAMap.put(chainName, newSHA); - } - //SHA值无变化,表示该chain未改变 - } - - if(chainSHAMap.size() > newChainSet.size()) { - //如果遍历prepareStatement后修改过的SHAMap数量比最新chain总数多, 说明有两种情况: - // 1、删除了chain - // 2、修改了chainName:因为遍历到新的name时会加到SHAMap里,但没有机会删除旧的chain - // 3、上述两者结合 - //在此处遍历chainSHAMap,把不在newChainSet中的chain删除 - //这里用iterator是为避免在遍历集合时删除元素导致ConcurrentModificationException - Iterator iterator = chainSHAMap.keySet().iterator(); - while(iterator.hasNext()) { - String chainName = iterator.next(); - if(!newChainSet.contains(chainName)) { - FlowBus.removeChain(chainName); - LOG.info("starting reload flow config... delete chain={}", chainName); - //修改SHAMap - iterator.remove(); - } - } - } - } catch (Exception e) { - LOG.error("[Exception during SQL chain polling] " + e.getMessage(), e); - } finally { - // 关闭连接 - LiteFlowJdbcUtil.close(conn, stmt, rs); - } - } - - private String getStringFromResultSet(ResultSet rs, String field) throws SQLException { - String data = rs.getString(field); - if (StrUtil.isBlank(data)) { - throw new ELSQLException(StrUtil.format("exist {} field value is empty", field)); - } - return data; - } -} diff --git a/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/util/JDBCHelper.java b/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/util/JDBCHelper.java index 8eb6dc4b8..aae5e44f7 100644 --- a/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/util/JDBCHelper.java +++ b/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/util/JDBCHelper.java @@ -5,22 +5,21 @@ import cn.hutool.core.thread.NamedThreadFactory; import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.StrUtil; import cn.hutool.core.util.XmlUtil; -import cn.hutool.crypto.digest.DigestUtil; -import com.yomahub.liteflow.enums.NodeTypeEnum; -import com.yomahub.liteflow.enums.ScriptTypeEnum; -import com.yomahub.liteflow.parser.sql.exception.ELSQLException; -import com.yomahub.liteflow.parser.sql.vo.SQLParserVO; +import com.yomahub.liteflow.parser.constant.ReadType; -import java.sql.Connection; -import java.sql.PreparedStatement; -import java.sql.ResultSet; -import java.sql.SQLException; +import com.yomahub.liteflow.parser.helper.NodeConvertHelper; +import com.yomahub.liteflow.parser.sql.exception.ELSQLException; +import com.yomahub.liteflow.parser.sql.read.SqlRead; +import com.yomahub.liteflow.parser.sql.read.SqlReadFactory; +import com.yomahub.liteflow.parser.sql.vo.SQLParserVO; +import org.apache.commons.lang.StringUtils; import java.util.*; import java.util.concurrent.ScheduledThreadPoolExecutor; import java.util.concurrent.ThreadFactory; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; +import static com.yomahub.liteflow.parser.constant.SqlReadConstant.*; /** * jdbc 工具类 * @@ -29,26 +28,6 @@ import java.util.concurrent.TimeUnit; */ public class JDBCHelper { - private static final String SQL_PATTERN = "SELECT {},{} FROM {} WHERE {}=?"; - - private static final String SCRIPT_SQL_CHECK_PATTERN = "SELECT 1 FROM {} WHERE {}=?"; - - private static final String SCRIPT_SQL_PATTERN = "SELECT {},{},{},{} FROM {} WHERE {}=?"; - - private static final String SCRIPT_WITH_LANGUAG_SQL_PATTERN = "SELECT {},{},{},{},{} FROM {} WHERE {}=?"; - - private static final String CHAIN_XML_PATTERN = ""; - - private static final String NODE_XML_PATTERN = "{}"; - - private static final String NODE_ITEM_XML_PATTERN = ""; - - private static final String NODE_ITEM_WITH_LANGUAGE_XML_PATTERN = ""; - - private static final String XML_PATTERN = "{}{}"; - - private static final Integer FETCH_SIZE_MAX = 1000; - private SQLParserVO sqlParserVO; private static JDBCHelper INSTANCE; @@ -59,12 +38,6 @@ public class JDBCHelper { //定时任务线程池 private static ScheduledThreadPoolExecutor pollExecutor; - //chain的SHA1加密值 用于轮询时确定chain是否变化 - private Map chainSHAMap = new HashMap<>(); - - //script的SHA1加密值 用于轮询时确定script是否变化 - private Map scriptSHAMap = new HashMap<>(); - /** * 初始化 INSTANCE */ @@ -75,13 +48,10 @@ public class JDBCHelper { Class.forName(sqlParserVO.getDriverClassName()); } INSTANCE.setSqlParserVO(sqlParserVO); - //创建定时任务线程池 + // 创建定时任务线程池 if (sqlParserVO.getPollingEnabled() && ObjectUtil.isNull(getPollExecutor())) { ThreadFactory namedThreadFactory = new NamedThreadFactory("SQL-Polling-", false); - ScheduledThreadPoolExecutor threadPoolExecutor = new ScheduledThreadPoolExecutor( - CORE_POOL_SIZE, - namedThreadFactory, - new ThreadPoolExecutor.DiscardOldestPolicy()); + ScheduledThreadPoolExecutor threadPoolExecutor = new ScheduledThreadPoolExecutor(CORE_POOL_SIZE, namedThreadFactory, new ThreadPoolExecutor.DiscardOldestPolicy()); setPollExecutor(threadPoolExecutor); } } catch (ClassNotFoundException e) { @@ -100,64 +70,38 @@ public class JDBCHelper { * 获取 ElData 数据内容 */ public String getContent() { - Connection conn = null; - PreparedStatement stmt = null; - ResultSet rs = null; + SqlRead chainRead = SqlReadFactory.getSqlRead(ReadType.CHAIN); + SqlRead scriptRead = SqlReadFactory.getSqlRead(ReadType.SCRIPT); - String chainTableName = sqlParserVO.getChainTableName(); - String elDataField = sqlParserVO.getElDataField(); - String chainNameField = sqlParserVO.getChainNameField(); - String chainApplicationNameField = sqlParserVO.getChainApplicationNameField(); - String applicationName = sqlParserVO.getApplicationName(); + // 获取 chain 数据 + Map chainMap = chainRead.read(); + List chainList = new ArrayList<>(); + chainMap.forEach((chainName, elData) -> { + chainList.add(StrUtil.format(CHAIN_XML_PATTERN, XmlUtil.escape(chainName), elData)); + }); + String chainsContent = CollUtil.join(chainList, StrUtil.EMPTY); - if (StrUtil.isBlank(chainTableName)) { - throw new ELSQLException("You did not define the chainTableName property"); - } + // 获取脚本数据 + Map scriptMap = scriptRead.read(); + List scriptList = new ArrayList<>(); + scriptMap.forEach((scriptKey, elData) -> { + NodeConvertHelper.NodeSimpleVO scriptVO = NodeConvertHelper.convert(scriptKey); + String id = scriptVO.getNodeId(); + String name = scriptVO.getName(); + String type = scriptVO.getType(); + String language = scriptVO.getLanguage(); - if (StrUtil.isBlank(applicationName) || StrUtil.isBlank(chainApplicationNameField)) { - throw new ELSQLException("You did not define the applicationName or chainApplicationNameField property"); - } - - String sqlCmd = StrUtil.format(SQL_PATTERN, chainNameField, elDataField, chainTableName, - chainApplicationNameField); - - List result = new ArrayList<>(); - try { - conn = LiteFlowJdbcUtil.getConn(sqlParserVO); - stmt = conn.prepareStatement(sqlCmd, ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY); - // 设置游标拉取数量 - stmt.setFetchSize(FETCH_SIZE_MAX); - stmt.setString(1, applicationName); - rs = stmt.executeQuery(); - - while (rs.next()) { - String elData = getStringFromResultSet(rs, elDataField); - String chainName = getStringFromResultSet(rs, chainNameField); - - result.add(StrUtil.format(CHAIN_XML_PATTERN, XmlUtil.escape(chainName), elData)); - - //如果需要轮询 计算该chainData的SHA值 - if(sqlParserVO.getPollingEnabled()){ - String chainSHA = DigestUtil.sha1Hex(elData); - chainSHAMap.put(chainName, chainSHA); - } + if (StringUtils.isNotBlank(scriptVO.getLanguage())) { + scriptList.add(StrUtil.format(NODE_ITEM_WITH_LANGUAGE_XML_PATTERN, XmlUtil.escape(id), XmlUtil.escape(name),type, language, elData)); + } else { + scriptList.add(StrUtil.format(NODE_ITEM_XML_PATTERN, XmlUtil.escape(id), XmlUtil.escape(name), type, elData)); } - } catch (Exception e) { - throw new ELSQLException(e.getMessage()); - } finally { - // 关闭连接 - LiteFlowJdbcUtil.close(conn, stmt, rs); - } - - String chainsContent = CollUtil.join(result, StrUtil.EMPTY); - - String nodesContent; - if (hasScriptData()) { - nodesContent = getScriptNodes(); - } else { - nodesContent = StrUtil.EMPTY; - } + }); + String nodesContent = StrUtil.format(NODE_XML_PATTERN, CollUtil.join(scriptList, StrUtil.EMPTY)); + // 注册 + SqlReadFactory.registerSqlReadPollTask(ReadType.CHAIN, chainMap); + SqlReadFactory.registerSqlReadPollTask(ReadType.SCRIPT, scriptMap); return StrUtil.format(XML_PATTERN, nodesContent, chainsContent); } @@ -165,197 +109,22 @@ public class JDBCHelper { * 定时轮询拉取SQL中变化的数据 */ public void listenSQL() { - //添加轮询chain的定时任务 - ChainPollingTask chainTask = new ChainPollingTask(sqlParserVO, chainSHAMap); - pollExecutor.scheduleAtFixedRate(chainTask, sqlParserVO.getPollingStartSeconds().longValue(), - sqlParserVO.getPollingIntervalSeconds().longValue(), TimeUnit.SECONDS); - if (hasScriptData()) { - //添加轮询script的定时任务 - ScriptPollingTask scriptTask = new ScriptPollingTask(sqlParserVO, scriptSHAMap); - pollExecutor.scheduleAtFixedRate(scriptTask, sqlParserVO.getPollingStartSeconds().longValue(), - sqlParserVO.getPollingIntervalSeconds().longValue(), TimeUnit.SECONDS); - } - } + // 添加轮询chain的定时任务 + pollExecutor.scheduleAtFixedRate( + () -> SqlReadFactory.getSqlReadPollTask(ReadType.CHAIN).execute(), + sqlParserVO.getPollingStartSeconds().longValue(), + sqlParserVO.getPollingIntervalSeconds().longValue(), + TimeUnit.SECONDS + ); + // 添加轮询script的定时任务 + pollExecutor.scheduleAtFixedRate( + () -> SqlReadFactory.getSqlReadPollTask(ReadType.SCRIPT).execute(), + sqlParserVO.getPollingStartSeconds().longValue(), + sqlParserVO.getPollingIntervalSeconds().longValue(), + TimeUnit.SECONDS + ); - /** - * 获取脚本节点内容 - */ - public String getScriptNodes() { - String scriptLanguageField = sqlParserVO.getScriptLanguageField(); - if (StrUtil.isNotBlank(scriptLanguageField)) { - return getScriptNodesWithLanguage(); - } - - List result = new ArrayList<>(); - Connection conn = null; - PreparedStatement stmt = null; - ResultSet rs = null; - - String scriptTableName = sqlParserVO.getScriptTableName(); - String scriptIdField = sqlParserVO.getScriptIdField(); - String scriptDataField = sqlParserVO.getScriptDataField(); - String scriptNameField = sqlParserVO.getScriptNameField(); - String scriptTypeField = sqlParserVO.getScriptTypeField(); - String scriptApplicationNameField = sqlParserVO.getScriptApplicationNameField(); - String applicationName = sqlParserVO.getApplicationName(); - - if (StrUtil.isBlank(applicationName) || StrUtil.isBlank(scriptApplicationNameField)) { - throw new ELSQLException("You did not define the applicationName or scriptApplicationNameField property"); - } - - String sqlCmd = StrUtil.format(SCRIPT_SQL_PATTERN, scriptIdField, scriptDataField, scriptNameField, - scriptTypeField, scriptTableName, scriptApplicationNameField); - try { - conn = LiteFlowJdbcUtil.getConn(sqlParserVO); - stmt = conn.prepareStatement(sqlCmd, ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY); - // 设置游标拉取数量 - stmt.setFetchSize(FETCH_SIZE_MAX); - stmt.setString(1, applicationName); - rs = stmt.executeQuery(); - - while (rs.next()) { - String id = getStringFromResultSet(rs, scriptIdField); - String data = getStringFromResultSet(rs, scriptDataField); - String name = getStringFromResultSet(rs, scriptNameField); - String type = getStringFromResultSet(rs, scriptTypeField); - - NodeTypeEnum nodeTypeEnum = NodeTypeEnum.getEnumByCode(type); - if (Objects.isNull(nodeTypeEnum)) { - throw new ELSQLException(StrUtil.format("Invalid type value[{}]", type)); - } - - if (!nodeTypeEnum.isScript()) { - throw new ELSQLException(StrUtil.format("The type value[{}] is not a script type", type)); - } - - result.add(StrUtil.format(NODE_ITEM_XML_PATTERN, XmlUtil.escape(id), XmlUtil.escape(name), type, data)); - - //如果需要轮询 计算该scriptData的SHA值 - if(sqlParserVO.getPollingEnabled()){ - String scriptKey = StrUtil.join(":", id, type, name); - String scriptSHA = DigestUtil.sha1Hex(data); - scriptSHAMap.put(scriptKey, scriptSHA); - } - } - } catch (Exception e) { - throw new ELSQLException(e.getMessage()); - } finally { - // 关闭连接 - LiteFlowJdbcUtil.close(conn, stmt, rs); - } - return StrUtil.format(NODE_XML_PATTERN, CollUtil.join(result, StrUtil.EMPTY)); - } - - /** - * 获取脚本节点(带语言) - * - * @return - */ - public String getScriptNodesWithLanguage() { - - List result = new ArrayList<>(); - Connection conn = null; - PreparedStatement stmt = null; - ResultSet rs = null; - - String scriptTableName = sqlParserVO.getScriptTableName(); - String scriptIdField = sqlParserVO.getScriptIdField(); - String scriptDataField = sqlParserVO.getScriptDataField(); - String scriptNameField = sqlParserVO.getScriptNameField(); - String scriptTypeField = sqlParserVO.getScriptTypeField(); - String scriptApplicationNameField = sqlParserVO.getScriptApplicationNameField(); - String applicationName = sqlParserVO.getApplicationName(); - String scriptLanguageField = sqlParserVO.getScriptLanguageField(); - - if (StrUtil.isBlank(applicationName) || StrUtil.isBlank(scriptApplicationNameField)) { - throw new ELSQLException("You did not define the applicationName or scriptApplicationNameField property"); - } - - String sqlCmd = StrUtil.format(SCRIPT_WITH_LANGUAG_SQL_PATTERN, scriptIdField, scriptDataField, scriptNameField, - scriptTypeField, scriptLanguageField, scriptTableName, scriptApplicationNameField); - try { - conn = LiteFlowJdbcUtil.getConn(sqlParserVO); - stmt = conn.prepareStatement(sqlCmd, ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY); - // 设置游标拉取数量 - stmt.setFetchSize(FETCH_SIZE_MAX); - stmt.setString(1, applicationName); - rs = stmt.executeQuery(); - - while (rs.next()) { - String id = getStringFromResultSet(rs, scriptIdField); - String data = getStringFromResultSet(rs, scriptDataField); - String name = getStringFromResultSet(rs, scriptNameField); - String type = getStringFromResultSet(rs, scriptTypeField); - String language = getStringFromResultSet(rs, scriptLanguageField); - - NodeTypeEnum nodeTypeEnum = NodeTypeEnum.getEnumByCode(type); - if (Objects.isNull(nodeTypeEnum)) { - throw new ELSQLException(StrUtil.format("Invalid type value[{}]", type)); - } - - if (!nodeTypeEnum.isScript()) { - throw new ELSQLException(StrUtil.format("The type value[{}] is not a script type", type)); - } - - if (!ScriptTypeEnum.checkScriptType(language)) { - throw new ELSQLException(StrUtil.format("The language value[{}] is invalid", language)); - } - - result.add(StrUtil.format(NODE_ITEM_WITH_LANGUAGE_XML_PATTERN, XmlUtil.escape(id), XmlUtil.escape(name), - type, language, data)); - - //如果需要轮询 计算该scriptData的SHA值 - if(sqlParserVO.getPollingEnabled()){ - String scriptKey = StrUtil.join(":", id, type, name, language); - String scriptSHA = DigestUtil.sha1Hex(data); - scriptSHAMap.put(scriptKey, scriptSHA); - } - } - } catch (Exception e) { - throw new ELSQLException(e.getMessage()); - } finally { - // 关闭连接 - LiteFlowJdbcUtil.close(conn, stmt, rs); - } - return StrUtil.format(NODE_XML_PATTERN, CollUtil.join(result, StrUtil.EMPTY)); - } - - private boolean hasScriptData() { - if (StrUtil.isBlank(sqlParserVO.getScriptTableName())) { - return false; - } - - Connection conn = null; - PreparedStatement stmt = null; - ResultSet rs = null; - String sqlCmd = StrUtil.format(SCRIPT_SQL_CHECK_PATTERN, sqlParserVO.getScriptTableName(), - sqlParserVO.getScriptApplicationNameField()); - try { - conn = LiteFlowJdbcUtil.getConn(sqlParserVO); - stmt = conn.prepareStatement(sqlCmd, ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY); - stmt.setFetchSize(1); - stmt.setString(1, sqlParserVO.getApplicationName()); - rs = stmt.executeQuery(); - return rs.next(); - } catch (Exception e) { - return false; - } finally { - // 关闭连接 - LiteFlowJdbcUtil.close(conn, stmt, rs); - } - } - - private String getStringFromResultSet(ResultSet rs, String field) throws SQLException { - String data = rs.getString(field); - if (StrUtil.isBlank(data)) { - throw new ELSQLException(StrUtil.format("exist {} field value is empty", field)); - } - return data; - } - - private SQLParserVO getSqlParserVO() { - return sqlParserVO; } private void setSqlParserVO(SQLParserVO sqlParserVO) { diff --git a/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/util/ScriptPollingTask.java b/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/util/ScriptPollingTask.java deleted file mode 100644 index 5a68e6f7f..000000000 --- a/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/util/ScriptPollingTask.java +++ /dev/null @@ -1,145 +0,0 @@ -package com.yomahub.liteflow.parser.sql.util; - -import cn.hutool.core.util.StrUtil; -import cn.hutool.crypto.digest.DigestUtil; -import com.yomahub.liteflow.flow.FlowBus; -import com.yomahub.liteflow.log.LFLog; -import com.yomahub.liteflow.log.LFLoggerManager; -import com.yomahub.liteflow.parser.helper.NodeConvertHelper; -import com.yomahub.liteflow.parser.sql.exception.ELSQLException; -import com.yomahub.liteflow.parser.sql.vo.SQLParserVO; - -import java.sql.Connection; -import java.sql.PreparedStatement; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.util.*; - -/** - * 用于轮询script的定时任务 - * - * @author hxinyu - * @since 2.11.1 - */ -public class ScriptPollingTask implements Runnable { - - private static final String SQL_PATTERN = "SELECT {},{} FROM {} WHERE {}=?"; - - private static final String CONCAT_PATTERN = "CONCAT_WS(':',{},{},{}) as script_concat"; - - private static final String CONCAT_WITH_LANGUAGE_PATTERN = "CONCAT_WS(':',{},{},{},{}) as script_concat"; - - private static final String SCRIPT_KEY_FIELD = "script_concat"; - - private Connection conn; - - private SQLParserVO sqlParserVO; - - private Map scriptSHAMap; - - private static final Integer FETCH_SIZE_MAX = 1000; - - LFLog LOG = LFLoggerManager.getLogger(ScriptPollingTask.class); - - public ScriptPollingTask(SQLParserVO sqlParserVO, Map scriptSHAMap) { - this.sqlParserVO = sqlParserVO; - this.scriptSHAMap = scriptSHAMap; - } - - - @Override - public void run() { - conn = LiteFlowJdbcUtil.getConn(sqlParserVO); - PreparedStatement stmt = null; - ResultSet rs = null; - try { - String scriptTableName = sqlParserVO.getScriptTableName(); - String scriptIdField = sqlParserVO.getScriptIdField(); - String scriptDataField = sqlParserVO.getScriptDataField(); - String scriptNameField = sqlParserVO.getScriptNameField(); - String scriptTypeField = sqlParserVO.getScriptTypeField(); - String scriptApplicationNameField = sqlParserVO.getScriptApplicationNameField(); - String applicationName = sqlParserVO.getApplicationName(); - String scriptLanguageField = sqlParserVO.getScriptLanguageField(); - - String KeyField; - if (StrUtil.isNotBlank(scriptLanguageField)) { - KeyField = StrUtil.format(CONCAT_WITH_LANGUAGE_PATTERN, scriptIdField, scriptTypeField, scriptNameField, scriptLanguageField); - } else { - KeyField = StrUtil.format(CONCAT_PATTERN, scriptIdField, scriptTypeField, scriptNameField); - } - - String sqlCmd = StrUtil.format(SQL_PATTERN, KeyField, scriptDataField, scriptTableName, scriptApplicationNameField); - stmt = conn.prepareStatement(sqlCmd, ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY); - // 设置游标拉取数量 - stmt.setFetchSize(FETCH_SIZE_MAX); - stmt.setString(1, applicationName); - rs = stmt.executeQuery(); - - Set newScriptSet = new HashSet<>(); - - while (rs.next()) { - String scriptKey = getStringFromResultSet(rs, SCRIPT_KEY_FIELD); - String newData = getStringFromResultSet(rs, scriptDataField); - String newSHA = DigestUtil.sha1Hex(newData); - newScriptSet.add(scriptKey); - //如果封装的SHAMap中不存在该script 表示该script为新增 - if (!scriptSHAMap.containsKey(scriptKey)) { - NodeConvertHelper.NodeSimpleVO scriptVO = NodeConvertHelper.convert(scriptKey); - //新增script - NodeConvertHelper.changeScriptNode(scriptVO, newData); - LOG.info("starting reload flow config... create script={}, new value={},", scriptKey, newData); - - //加入到shaMap - scriptSHAMap.put(scriptKey, newSHA); - } - else if (!StrUtil.equals(newSHA, scriptSHAMap.get(scriptKey))) { - //SHA值发生变化,表示该script的值已被修改,重新拉取变化的script - NodeConvertHelper.NodeSimpleVO scriptVO = NodeConvertHelper.convert(scriptKey); - //修改script - NodeConvertHelper.changeScriptNode(scriptVO, newData); - LOG.info("starting reload flow config... update scriptId={}, new value={},", scriptVO.getNodeId(), newData); - - //修改shaMap - scriptSHAMap.put(scriptKey, newSHA); - } - //SHA值无变化,表示该chain未改变 - } - - if(scriptSHAMap.size() > newScriptSet.size()) { - //如果遍历prepareStatement后修改过的SHAMap数量比最新script总数多, 说明有两种情况: - // 1、删除了script - // 2、修改了script的id/name/type:因为遍历到新的script_key时会加到SHAMap里,但没有机会删除旧的script - // 3、上述两者结合 - //在此处遍历scriptSHAMap,把不在newScriptSet中的script删除 - //这里用iterator是为避免在遍历集合时删除元素导致ConcurrentModificationException - Iterator iterator = scriptSHAMap.keySet().iterator(); - while(iterator.hasNext()){ - String scriptKey = iterator.next(); - if (!newScriptSet.contains(scriptKey)) { - NodeConvertHelper.NodeSimpleVO scriptVO = NodeConvertHelper.convert(scriptKey); - //删除script - FlowBus.getNodeMap().remove(scriptVO.getNodeId()); - LOG.info("starting reload flow config... delete script={}", scriptKey); - //修改SHAMap - iterator.remove(); - } - } - } - - } catch (Exception e) { - LOG.error("[Exception during SQL script polling] " + e.getMessage(), e); - } finally { - // 关闭连接 - LiteFlowJdbcUtil.close(conn, stmt, rs); - } - } - - private String getStringFromResultSet(ResultSet rs, String field) throws SQLException { - String data = rs.getString(field); - if (StrUtil.isBlank(data)) { - throw new ELSQLException(StrUtil.format("exist {} field value is empty", field)); - } - return data; - } -} diff --git a/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/vo/SQLParserVO.java b/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/vo/SQLParserVO.java index b15d68b72..8824328dd 100644 --- a/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/vo/SQLParserVO.java +++ b/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/vo/SQLParserVO.java @@ -90,15 +90,26 @@ public class SQLParserVO { */ private String scriptLanguageField; - /*轮询机制是否开启 默认不开启*/ + /** + * 轮询机制是否开启 默认不开启 + */ private Boolean pollingEnabled = false; - /*轮询时间间隔(s) 默认120s*/ + /** + * 轮询时间间隔(s) 默认60s + */ private Integer pollingIntervalSeconds = 60; - /*规则配置后首次轮询的起始时间 默认为60s*/ + /** + * 规则配置后首次轮询的起始时间 默认为60s + */ private Integer pollingStartSeconds = 60; + /** + * 是否开启sql日志 + */ + private Boolean sqlLogEnabled = true; + public String getUrl() { return url; } @@ -257,4 +268,12 @@ public class SQLParserVO { public void setPollingStartSeconds(Integer pollingStartSeconds) { this.pollingStartSeconds = pollingStartSeconds; } + + public Boolean getSqlLogEnabled() { + return sqlLogEnabled; + } + + public void setSqlLogEnabled(Boolean sqlLogEnabled) { + this.sqlLogEnabled = sqlLogEnabled; + } } From 50c86aa0299133c4f0375f2bcb39c6787b02de22 Mon Sep 17 00:00:00 2001 From: gaibu <1016771049@qq.com> Date: Thu, 28 Sep 2023 16:51:33 +0800 Subject: [PATCH 31/53] =?UTF-8?q?sql=20=E6=8F=92=E4=BB=B6=E4=BB=A3?= =?UTF-8?q?=E7=A0=81=E8=A7=84=E8=8C=83=E8=B0=83=E6=95=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../liteflow/parser/constant/ReadType.java | 9 ++++----- .../parser/constant/SqlReadConstant.java | 9 ++++----- .../sql/polling/AbstractSqlReadPollTask.java | 10 ++++------ .../parser/sql/polling/SqlReadPollTask.java | 15 +++++++++----- .../sql/polling/impl/ChainReadPollTask.java | 17 ++++------------ .../sql/polling/impl/ScriptReadPollTask.java | 9 ++++----- .../parser/sql/read/AbstractSqlRead.java | 10 ++++------ .../liteflow/parser/sql/read/SqlRead.java | 15 +++++++++----- .../parser/sql/read/SqlReadFactory.java | 9 ++++----- .../parser/sql/read/impl/ChainRead.java | 10 ++++------ .../parser/sql/read/impl/ScriptRead.java | 10 +++------- .../SQLWithXmlELSpringbootPollingTest.java | 20 +++++++++++++++++++ 12 files changed, 75 insertions(+), 68 deletions(-) diff --git a/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/constant/ReadType.java b/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/constant/ReadType.java index a687d53d1..812c5a5be 100644 --- a/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/constant/ReadType.java +++ b/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/constant/ReadType.java @@ -1,12 +1,11 @@ package com.yomahub.liteflow.parser.constant; /** - * Copyright (C), 2021, 北京同创永益科技发展有限公司 + * sql 类型枚举 * - * @author tangkc - * @version 3.0.0 - * @description - * @date 2023/9/28 11:43 + * @author tangkc huxinyu + * @date 2023/9/28 11:49 + * @since 2.11.1 */ public enum ReadType { CHAIN, diff --git a/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/constant/SqlReadConstant.java b/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/constant/SqlReadConstant.java index 127bc0084..80116f908 100644 --- a/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/constant/SqlReadConstant.java +++ b/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/constant/SqlReadConstant.java @@ -1,12 +1,11 @@ package com.yomahub.liteflow.parser.constant; /** - * Copyright (C), 2021, 北京同创永益科技发展有限公司 + * sql 读取常量类 * - * @author tangkc - * @version 3.0.0 - * @description - * @date 2023/9/28 11:42 + * @author tangkc huxinyu + * @date 2023/9/28 11:49 + * @since 2.11.1 */ public class SqlReadConstant { diff --git a/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/polling/AbstractSqlReadPollTask.java b/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/polling/AbstractSqlReadPollTask.java index 1fc75902d..72e9fa634 100644 --- a/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/polling/AbstractSqlReadPollTask.java +++ b/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/polling/AbstractSqlReadPollTask.java @@ -1,7 +1,6 @@ package com.yomahub.liteflow.parser.sql.polling; import cn.hutool.core.collection.CollUtil; -import cn.hutool.core.map.MapUtil; import cn.hutool.core.util.StrUtil; import cn.hutool.crypto.digest.DigestUtil; import com.yomahub.liteflow.parser.sql.exception.ELSQLException; @@ -14,12 +13,11 @@ import java.util.Map; import java.util.Set; /** - * Copyright (C), 2021, 北京同创永益科技发展有限公司 + * sql 轮询任务抽象类,维护公共方法 * - * @author tangkc - * @version 3.0.0 - * @description - * @date 2023/9/28 14:12 + * @author tangkc huxinyu + * @date 2023/9/28 11:49 + * @since 2.11.1 */ public abstract class AbstractSqlReadPollTask implements SqlReadPollTask { private final Map DATA_SHA_MAP; diff --git a/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/polling/SqlReadPollTask.java b/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/polling/SqlReadPollTask.java index 898dbfb21..bbe48aaaf 100644 --- a/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/polling/SqlReadPollTask.java +++ b/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/polling/SqlReadPollTask.java @@ -3,16 +3,21 @@ package com.yomahub.liteflow.parser.sql.polling; import com.yomahub.liteflow.parser.constant.ReadType; /** - * Copyright (C), 2021, 北京同创永益科技发展有限公司 + * sql 轮询任务接口 * - * @author tangkc - * @version 3.0.0 - * @description - * @date 2023/9/28 14:10 + * @author tangkc huxinyu + * @date 2023/9/28 11:49 + * @since 2.11.1 */ public interface SqlReadPollTask { + /** + * 执行 + */ void execute(); + /** + * 类型 + */ ReadType type(); } diff --git a/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/polling/impl/ChainReadPollTask.java b/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/polling/impl/ChainReadPollTask.java index 1eaac11c4..0e13e0fc6 100644 --- a/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/polling/impl/ChainReadPollTask.java +++ b/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/polling/impl/ChainReadPollTask.java @@ -3,27 +3,18 @@ package com.yomahub.liteflow.parser.sql.polling.impl; import com.yomahub.liteflow.builder.el.LiteFlowChainELBuilder; import com.yomahub.liteflow.flow.FlowBus; import com.yomahub.liteflow.parser.constant.ReadType; -import com.yomahub.liteflow.parser.helper.ParserHelper; import com.yomahub.liteflow.parser.sql.polling.AbstractSqlReadPollTask; -import com.yomahub.liteflow.parser.sql.polling.SqlReadPollTask; import com.yomahub.liteflow.parser.sql.read.SqlRead; -import org.dom4j.Document; -import org.dom4j.DocumentHelper; import java.util.List; import java.util.Map; -import java.util.Optional; - -import static com.yomahub.liteflow.common.ChainConstant.ID; -import static com.yomahub.liteflow.common.ChainConstant.NAME; /** - * Copyright (C), 2021, 北京同创永益科技发展有限公司 + * chain 读取任务 * - * @author tangkc - * @version 3.0.0 - * @description - * @date 2023/9/28 14:46 + * @author tangkc huxinyu + * @date 2023/9/28 11:49 + * @since 2.11.1 */ public class ChainReadPollTask extends AbstractSqlReadPollTask { diff --git a/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/polling/impl/ScriptReadPollTask.java b/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/polling/impl/ScriptReadPollTask.java index 41dd5b4c4..539b5a849 100644 --- a/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/polling/impl/ScriptReadPollTask.java +++ b/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/polling/impl/ScriptReadPollTask.java @@ -10,12 +10,11 @@ import java.util.List; import java.util.Map; /** - * Copyright (C), 2021, 北京同创永益科技发展有限公司 + * 脚本轮询任务 * - * @author tangkc - * @version 3.0.0 - * @description - * @date 2023/9/28 15:03 + * @author tangkc huxinyu + * @date 2023/9/28 11:49 + * @since 2.11.1 */ public class ScriptReadPollTask extends AbstractSqlReadPollTask { public ScriptReadPollTask(Map dataMap, SqlRead read) { diff --git a/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/read/AbstractSqlRead.java b/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/read/AbstractSqlRead.java index e917a6161..e598adbd1 100644 --- a/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/read/AbstractSqlRead.java +++ b/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/read/AbstractSqlRead.java @@ -5,7 +5,6 @@ import com.yomahub.liteflow.log.LFLog; import com.yomahub.liteflow.log.LFLoggerManager; import com.yomahub.liteflow.parser.constant.SqlReadConstant; import com.yomahub.liteflow.parser.sql.exception.ELSQLException; -import com.yomahub.liteflow.parser.sql.read.impl.ScriptRead; import com.yomahub.liteflow.parser.sql.util.LiteFlowJdbcUtil; import com.yomahub.liteflow.parser.sql.vo.SQLParserVO; @@ -17,12 +16,11 @@ import java.util.HashMap; import java.util.Map; /** - * Copyright (C), 2021, 北京同创永益科技发展有限公司 + * sql 读取抽象类,维护公共方法 * - * @author tangkc - * @version 3.0.0 - * @description - * @date 2023/9/28 11:26 + * @author tangkc huxinyu + * @date 2023/9/28 11:49 + * @since 2.11.1 */ public abstract class AbstractSqlRead implements SqlRead { public final SQLParserVO config; diff --git a/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/read/SqlRead.java b/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/read/SqlRead.java index c94c54570..8b0bdb0ee 100644 --- a/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/read/SqlRead.java +++ b/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/read/SqlRead.java @@ -5,16 +5,21 @@ import com.yomahub.liteflow.parser.constant.ReadType; import java.util.Map; /** - * Copyright (C), 2021, 北京同创永益科技发展有限公司 + * sql 读取接口 * - * @author tangkc - * @version 3.0.0 - * @description - * @date 2023/9/28 11:25 + * @author tangkc huxinyu + * @date 2023/9/28 11:49 + * @since 2.11.1 */ public interface SqlRead { + /** + * 读取 + */ Map read(); + /** + * 类型 + */ ReadType type(); } diff --git a/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/read/SqlReadFactory.java b/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/read/SqlReadFactory.java index 4f4f531e4..ad7cea54e 100644 --- a/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/read/SqlReadFactory.java +++ b/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/read/SqlReadFactory.java @@ -12,12 +12,11 @@ import java.util.HashMap; import java.util.Map; /** - * Copyright (C), 2021, 北京同创永益科技发展有限公司 + * sql 读取工厂类 * - * @author tangkc - * @version 3.0.0 - * @description - * @date 2023/9/28 15:42 + * @author tangkc huxinyu + * @date 2023/9/28 11:49 + * @since 2.11.1 */ public class SqlReadFactory { private static final Map READ_MAP = new HashMap<>(); diff --git a/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/read/impl/ChainRead.java b/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/read/impl/ChainRead.java index a8c776b3e..3eacc28c5 100644 --- a/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/read/impl/ChainRead.java +++ b/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/read/impl/ChainRead.java @@ -1,7 +1,6 @@ package com.yomahub.liteflow.parser.sql.read.impl; import cn.hutool.core.util.StrUtil; -import cn.hutool.core.util.XmlUtil; import com.yomahub.liteflow.parser.constant.ReadType; import com.yomahub.liteflow.parser.constant.SqlReadConstant; import com.yomahub.liteflow.parser.sql.exception.ELSQLException; @@ -12,12 +11,11 @@ import java.sql.ResultSet; import java.sql.SQLException; /** - * Copyright (C), 2021, 北京同创永益科技发展有限公司 + * chain 读取 * - * @author tangkc - * @version 3.0.0 - * @description - * @date 2023/9/28 11:44 + * @author tangkc huxinyu + * @date 2023/9/28 11:49 + * @since 2.11.1 */ public class ChainRead extends AbstractSqlRead { diff --git a/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/read/impl/ScriptRead.java b/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/read/impl/ScriptRead.java index 8c04d5086..5fae2d029 100644 --- a/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/read/impl/ScriptRead.java +++ b/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/read/impl/ScriptRead.java @@ -2,11 +2,8 @@ package com.yomahub.liteflow.parser.sql.read.impl; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.util.StrUtil; -import cn.hutool.core.util.XmlUtil; import com.yomahub.liteflow.enums.NodeTypeEnum; import com.yomahub.liteflow.enums.ScriptTypeEnum; -import com.yomahub.liteflow.log.LFLog; -import com.yomahub.liteflow.log.LFLoggerManager; import com.yomahub.liteflow.parser.constant.ReadType; import com.yomahub.liteflow.parser.constant.SqlReadConstant; import com.yomahub.liteflow.parser.sql.exception.ELSQLException; @@ -21,12 +18,11 @@ import java.util.List; import java.util.Objects; /** - * Copyright (C), 2021, 北京同创永益科技发展有限公司 + * 脚本读取 * - * @author tangkc - * @version 3.0.0 - * @description + * @author tangkc huxinyu * @date 2023/9/28 11:49 + * @since 2.11.1 */ public class ScriptRead extends AbstractSqlRead { diff --git a/liteflow-testcase-el/liteflow-testcase-el-sql-springboot/src/test/java/com/yomahub/liteflow/test/sql/SQLWithXmlELSpringbootPollingTest.java b/liteflow-testcase-el/liteflow-testcase-el-sql-springboot/src/test/java/com/yomahub/liteflow/test/sql/SQLWithXmlELSpringbootPollingTest.java index e907cc2ab..4a37741bf 100644 --- a/liteflow-testcase-el/liteflow-testcase-el-sql-springboot/src/test/java/com/yomahub/liteflow/test/sql/SQLWithXmlELSpringbootPollingTest.java +++ b/liteflow-testcase-el/liteflow-testcase-el-sql-springboot/src/test/java/com/yomahub/liteflow/test/sql/SQLWithXmlELSpringbootPollingTest.java @@ -74,6 +74,8 @@ public class SQLWithXmlELSpringbootPollingTest extends BaseTest { insertData(); Thread.sleep(4000); Assertions.assertEquals("a==>b", flowExecutor.execute2Resp("chain5", "arg").getExecuteStepStr()); + + } @@ -99,6 +101,24 @@ public class SQLWithXmlELSpringbootPollingTest extends BaseTest { Assertions.assertEquals("hello", context.getData("test")); } + /** + * 删除chain数据 + */ + private void deleteData(){ + LiteflowConfig liteflowConfig = LiteflowConfigGetter.get(); + SQLParserVO sqlParserVO = JsonUtil.parseObject(liteflowConfig.getRuleSourceExtData(), SQLParserVO.class); + Connection connection; + try { + connection = DriverManager.getConnection(sqlParserVO.getUrl(), sqlParserVO.getUsername(), + sqlParserVO.getPassword()); + Statement statement = connection.createStatement(); + statement.executeUpdate("DELETE FROM EL_TABLE WHERE chain_name='chain1'"); + } + catch (SQLException e) { + throw new ELSQLException(e.getMessage()); + } + } + /** * 修改chain数据 */ From 3921430631a5f1020de9cfa038acd2bed7d1f2b6 Mon Sep 17 00:00:00 2001 From: luoyi <972849752@qq.com> Date: Thu, 28 Sep 2023 20:25:54 +0800 Subject: [PATCH 32/53] =?UTF-8?q?enhancement=20#I84XNE=20=E8=B0=83?= =?UTF-8?q?=E6=95=B4=20must=20=E5=85=A5=E5=8F=82=E7=B1=BB=E5=9E=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../builder/el/operator/MustOperator.java | 20 ++++++++++++------- .../src/test/resources/asyncNode/flow.el.xml | 2 +- 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/MustOperator.java b/liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/MustOperator.java index e859cd8bc..9c819d3be 100644 --- a/liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/MustOperator.java +++ b/liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/MustOperator.java @@ -1,14 +1,13 @@ package com.yomahub.liteflow.builder.el.operator; -import cn.hutool.core.util.StrUtil; import com.yomahub.liteflow.builder.el.operator.base.BaseOperator; import com.yomahub.liteflow.builder.el.operator.base.OperatorHelper; import com.yomahub.liteflow.enums.ParallelStrategyEnum; +import com.yomahub.liteflow.flow.element.Executable; import com.yomahub.liteflow.flow.element.condition.WhenCondition; -import java.util.Arrays; +import java.util.HashSet; import java.util.Set; -import java.util.stream.Collectors; /** * EL 规则中的 must 的操作符 @@ -20,14 +19,21 @@ public class MustOperator extends BaseOperator { @Override public WhenCondition build(Object[] objects) throws Exception { - OperatorHelper.checkObjectSizeEqTwo(objects); + OperatorHelper.checkObjectSizeGtTwo(objects); WhenCondition whenCondition = OperatorHelper.convert(objects[0], WhenCondition.class); - String specifyIds = OperatorHelper.convert(objects[1], String.class); - // 解析指定完成的任务 ID 集合 - Set specifyIdSet = Arrays.stream(specifyIds.replace(StrUtil.SPACE, StrUtil.EMPTY).split(",")).collect(Collectors.toSet()); + Set specifyIdSet = new HashSet<>(); + + for (int i = 1; i < objects.length; i++) { + Object task = objects[i]; + if (task instanceof String) { + specifyIdSet.add(OperatorHelper.convert(task, String.class)); + } else if (task instanceof Executable) { + specifyIdSet.add(OperatorHelper.convert(task, Executable.class).getId()); + } + } whenCondition.setSpecifyIdSet(specifyIdSet); whenCondition.setParallelStrategy(ParallelStrategyEnum.SPECIFY); diff --git a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/asyncNode/flow.el.xml b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/asyncNode/flow.el.xml index 79523e4e5..b02c48cf8 100644 --- a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/asyncNode/flow.el.xml +++ b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/asyncNode/flow.el.xml @@ -63,7 +63,7 @@ - THEN(WHEN(d, g, l, a, THEN(k, b).id("z")).ignoreError(true).must("z, g, task1, task2"), c); + THEN(WHEN(d, g, l, a, THEN(k, b).id("z")).ignoreError(true).must("z", g, "task1", "task2"), c); \ No newline at end of file From 75566e98f081a2761a49aa0b9c27b08b62541a16 Mon Sep 17 00:00:00 2001 From: gaibu <1016771049@qq.com> Date: Fri, 29 Sep 2023 10:04:27 +0800 Subject: [PATCH 33/53] =?UTF-8?q?sql=20=E6=8F=92=E4=BB=B6=E8=A1=A5?= =?UTF-8?q?=E5=85=85=E5=8D=95=E5=85=83=E6=B5=8B=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../sql/polling/AbstractSqlReadPollTask.java | 4 +-- .../SQLWithXmlELSpringbootPollingTest.java | 34 +++++++++++++++++-- 2 files changed, 34 insertions(+), 4 deletions(-) diff --git a/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/polling/AbstractSqlReadPollTask.java b/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/polling/AbstractSqlReadPollTask.java index 72e9fa634..a2c951925 100644 --- a/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/polling/AbstractSqlReadPollTask.java +++ b/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/polling/AbstractSqlReadPollTask.java @@ -64,9 +64,9 @@ public abstract class AbstractSqlReadPollTask implements SqlReadPollTask { Set oldIdList = DATA_SHA_MAP.keySet(); // 旧的 id 列表 Set newIdList = newData.keySet(); // 新的 id 列表 // 计算单差集 - // 计算集合的单差集,即只返回【newIdList】中有,但是【oldIdList】中没有的元素,例如: + // 计算集合的单差集,即只返回【oldIdList】中有,但是【newIdList】中没有的元素,例如: // subtractToList([1,2,3,4],[2,3,4,5]) -》 [1] - deleteElementIds = CollUtil.subtractToList(newIdList, oldIdList); + deleteElementIds = CollUtil.subtractToList(oldIdList, newIdList); for (String id : deleteElementIds) { DATA_SHA_MAP.remove(id); diff --git a/liteflow-testcase-el/liteflow-testcase-el-sql-springboot/src/test/java/com/yomahub/liteflow/test/sql/SQLWithXmlELSpringbootPollingTest.java b/liteflow-testcase-el/liteflow-testcase-el-sql-springboot/src/test/java/com/yomahub/liteflow/test/sql/SQLWithXmlELSpringbootPollingTest.java index 4a37741bf..f3ca22197 100644 --- a/liteflow-testcase-el/liteflow-testcase-el-sql-springboot/src/test/java/com/yomahub/liteflow/test/sql/SQLWithXmlELSpringbootPollingTest.java +++ b/liteflow-testcase-el/liteflow-testcase-el-sql-springboot/src/test/java/com/yomahub/liteflow/test/sql/SQLWithXmlELSpringbootPollingTest.java @@ -1,6 +1,7 @@ package com.yomahub.liteflow.test.sql; import com.yomahub.liteflow.core.FlowExecutor; +import com.yomahub.liteflow.exception.ChainNotFoundException; import com.yomahub.liteflow.flow.LiteflowResponse; import com.yomahub.liteflow.log.LFLog; import com.yomahub.liteflow.log.LFLoggerManager; @@ -21,6 +22,7 @@ import org.springframework.boot.test.context.SpringBootTest; import org.springframework.context.annotation.ComponentScan; import org.springframework.test.context.TestPropertySource; import org.springframework.test.context.junit.jupiter.SpringExtension; +import org.springframework.util.Assert; import javax.annotation.Resource; import java.lang.reflect.Field; @@ -75,7 +77,11 @@ public class SQLWithXmlELSpringbootPollingTest extends BaseTest { Thread.sleep(4000); Assertions.assertEquals("a==>b", flowExecutor.execute2Resp("chain5", "arg").getExecuteStepStr()); - + // 删除 chain + deleteData(); + Thread.sleep(4000); + Exception cause = flowExecutor.execute2Resp("chain5", "arg").getCause(); + Assertions.assertTrue(cause instanceof ChainNotFoundException,"删除 chain 测试失败"); } @@ -99,6 +105,11 @@ public class SQLWithXmlELSpringbootPollingTest extends BaseTest { DefaultContext context = response.getFirstContextBean(); Assertions.assertEquals("a==>x3[x3脚本]", response.getExecuteStepStrWithoutTime()); Assertions.assertEquals("hello", context.getData("test")); + + // TODO 删除脚本 + deleteScriptData(); + Thread.sleep(4000); + flowExecutor.execute2Resp("chain6", "arg"); } /** @@ -112,7 +123,7 @@ public class SQLWithXmlELSpringbootPollingTest extends BaseTest { connection = DriverManager.getConnection(sqlParserVO.getUrl(), sqlParserVO.getUsername(), sqlParserVO.getPassword()); Statement statement = connection.createStatement(); - statement.executeUpdate("DELETE FROM EL_TABLE WHERE chain_name='chain1'"); + statement.executeUpdate("DELETE FROM EL_TABLE WHERE chain_name='chain5'"); } catch (SQLException e) { throw new ELSQLException(e.getMessage()); @@ -197,6 +208,25 @@ public class SQLWithXmlELSpringbootPollingTest extends BaseTest { } } + /** + * 删除脚本 + */ + private void deleteScriptData() { + LiteflowConfig liteflowConfig = LiteflowConfigGetter.get(); + SQLParserVO sqlParserVO = JsonUtil.parseObject(liteflowConfig.getRuleSourceExtData(), SQLParserVO.class); + Connection connection; + try { + connection = DriverManager.getConnection(sqlParserVO.getUrl(), sqlParserVO.getUsername(), + sqlParserVO.getPassword()); + Statement statement = connection.createStatement(); + statement.executeUpdate( + "DELETE FROM SCRIPT_NODE_TABLE WHERE SCRIPT_NODE_ID = 'x3'"); + } + catch (SQLException e) { + throw new ELSQLException(e.getMessage()); + } + } + private void insertChainData() { LiteflowConfig liteflowConfig = LiteflowConfigGetter.get(); SQLParserVO sqlParserVO = JsonUtil.parseObject(liteflowConfig.getRuleSourceExtData(), SQLParserVO.class); From 1454236ef3199b981eff4a1b49af1c7aed94e570 Mon Sep 17 00:00:00 2001 From: gaibu <1016771049@qq.com> Date: Fri, 29 Sep 2023 10:11:38 +0800 Subject: [PATCH 34/53] =?UTF-8?q?sql=20=E6=8F=92=E4=BB=B6=E8=A1=A5?= =?UTF-8?q?=E5=85=85=E5=8D=95=E5=85=83=E6=B5=8B=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../liteflow/test/sql/SQLWithXmlELSpringbootPollingTest.java | 4 ---- 1 file changed, 4 deletions(-) diff --git a/liteflow-testcase-el/liteflow-testcase-el-sql-springboot/src/test/java/com/yomahub/liteflow/test/sql/SQLWithXmlELSpringbootPollingTest.java b/liteflow-testcase-el/liteflow-testcase-el-sql-springboot/src/test/java/com/yomahub/liteflow/test/sql/SQLWithXmlELSpringbootPollingTest.java index f3ca22197..5993a2faa 100644 --- a/liteflow-testcase-el/liteflow-testcase-el-sql-springboot/src/test/java/com/yomahub/liteflow/test/sql/SQLWithXmlELSpringbootPollingTest.java +++ b/liteflow-testcase-el/liteflow-testcase-el-sql-springboot/src/test/java/com/yomahub/liteflow/test/sql/SQLWithXmlELSpringbootPollingTest.java @@ -106,10 +106,6 @@ public class SQLWithXmlELSpringbootPollingTest extends BaseTest { Assertions.assertEquals("a==>x3[x3脚本]", response.getExecuteStepStrWithoutTime()); Assertions.assertEquals("hello", context.getData("test")); - // TODO 删除脚本 - deleteScriptData(); - Thread.sleep(4000); - flowExecutor.execute2Resp("chain6", "arg"); } /** From e7de64ced06bcdb50c58dffe03f4e926308b612b Mon Sep 17 00:00:00 2001 From: gaibu <1016771049@qq.com> Date: Fri, 29 Sep 2023 10:17:43 +0800 Subject: [PATCH 35/53] =?UTF-8?q?sql=20=E6=8F=92=E4=BB=B6=E8=BD=AE?= =?UTF-8?q?=E8=AF=A2=E5=A2=9E=E5=8A=A0=E5=BC=82=E5=B8=B8=E6=8D=95=E8=8E=B7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../liteflow/parser/sql/util/JDBCHelper.java | 33 ++++++++++++++++--- 1 file changed, 28 insertions(+), 5 deletions(-) diff --git a/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/util/JDBCHelper.java b/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/util/JDBCHelper.java index aae5e44f7..a181ccd79 100644 --- a/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/util/JDBCHelper.java +++ b/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/util/JDBCHelper.java @@ -5,14 +5,18 @@ import cn.hutool.core.thread.NamedThreadFactory; import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.StrUtil; import cn.hutool.core.util.XmlUtil; +import com.yomahub.liteflow.log.LFLog; +import com.yomahub.liteflow.log.LFLoggerManager; import com.yomahub.liteflow.parser.constant.ReadType; import com.yomahub.liteflow.parser.helper.NodeConvertHelper; import com.yomahub.liteflow.parser.sql.exception.ELSQLException; +import com.yomahub.liteflow.parser.sql.read.AbstractSqlRead; import com.yomahub.liteflow.parser.sql.read.SqlRead; import com.yomahub.liteflow.parser.sql.read.SqlReadFactory; import com.yomahub.liteflow.parser.sql.vo.SQLParserVO; import org.apache.commons.lang.StringUtils; + import java.util.*; import java.util.concurrent.ScheduledThreadPoolExecutor; import java.util.concurrent.ThreadFactory; @@ -20,6 +24,7 @@ import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; import static com.yomahub.liteflow.parser.constant.SqlReadConstant.*; + /** * jdbc 工具类 * @@ -32,12 +37,18 @@ public class JDBCHelper { private static JDBCHelper INSTANCE; - //定时任务线程池核心线程数 + /** + * 定时任务线程池核心线程数 + */ private static final int CORE_POOL_SIZE = 2; - //定时任务线程池 + /** + * 定时任务线程池 + */ private static ScheduledThreadPoolExecutor pollExecutor; + private static LFLog LOG = LFLoggerManager.getLogger(JDBCHelper.class); + /** * 初始化 INSTANCE */ @@ -92,7 +103,7 @@ public class JDBCHelper { String language = scriptVO.getLanguage(); if (StringUtils.isNotBlank(scriptVO.getLanguage())) { - scriptList.add(StrUtil.format(NODE_ITEM_WITH_LANGUAGE_XML_PATTERN, XmlUtil.escape(id), XmlUtil.escape(name),type, language, elData)); + scriptList.add(StrUtil.format(NODE_ITEM_WITH_LANGUAGE_XML_PATTERN, XmlUtil.escape(id), XmlUtil.escape(name), type, language, elData)); } else { scriptList.add(StrUtil.format(NODE_ITEM_XML_PATTERN, XmlUtil.escape(id), XmlUtil.escape(name), type, elData)); } @@ -111,7 +122,13 @@ public class JDBCHelper { public void listenSQL() { // 添加轮询chain的定时任务 pollExecutor.scheduleAtFixedRate( - () -> SqlReadFactory.getSqlReadPollTask(ReadType.CHAIN).execute(), + () -> { + try { + SqlReadFactory.getSqlReadPollTask(ReadType.CHAIN).execute(); + } catch (Exception ex) { + LOG.info("poll chain fail", ex); + } + }, sqlParserVO.getPollingStartSeconds().longValue(), sqlParserVO.getPollingIntervalSeconds().longValue(), TimeUnit.SECONDS @@ -119,7 +136,13 @@ public class JDBCHelper { // 添加轮询script的定时任务 pollExecutor.scheduleAtFixedRate( - () -> SqlReadFactory.getSqlReadPollTask(ReadType.SCRIPT).execute(), + () -> { + try { + SqlReadFactory.getSqlReadPollTask(ReadType.SCRIPT).execute(); + } catch (Exception ex) { + LOG.info("poll script fail", ex); + } + }, sqlParserVO.getPollingStartSeconds().longValue(), sqlParserVO.getPollingIntervalSeconds().longValue(), TimeUnit.SECONDS From 94d458f62828e4e99d815fd16b11217890c665c8 Mon Sep 17 00:00:00 2001 From: gaibu <1016771049@qq.com> Date: Fri, 29 Sep 2023 21:34:07 +0800 Subject: [PATCH 36/53] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E6=97=A5=E5=BF=97?= =?UTF-8?q?=E7=BA=A7=E5=88=AB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../liteflow/parser/sql/polling/AbstractSqlReadPollTask.java | 2 +- .../java/com/yomahub/liteflow/parser/sql/util/JDBCHelper.java | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/polling/AbstractSqlReadPollTask.java b/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/polling/AbstractSqlReadPollTask.java index a2c951925..2f3873865 100644 --- a/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/polling/AbstractSqlReadPollTask.java +++ b/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/polling/AbstractSqlReadPollTask.java @@ -36,7 +36,7 @@ public abstract class AbstractSqlReadPollTask implements SqlReadPollTask { public void execute() { Map newData = read.read(); // 新增或者更新的元素 - Map saveElementMap = new HashMap(); + Map saveElementMap = new HashMap<>(); // 删除的元素 List deleteElementIds = new ArrayList<>(); diff --git a/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/util/JDBCHelper.java b/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/util/JDBCHelper.java index a181ccd79..0c3c4db2d 100644 --- a/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/util/JDBCHelper.java +++ b/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/util/JDBCHelper.java @@ -126,7 +126,7 @@ public class JDBCHelper { try { SqlReadFactory.getSqlReadPollTask(ReadType.CHAIN).execute(); } catch (Exception ex) { - LOG.info("poll chain fail", ex); + LOG.error("poll chain fail", ex); } }, sqlParserVO.getPollingStartSeconds().longValue(), @@ -140,7 +140,7 @@ public class JDBCHelper { try { SqlReadFactory.getSqlReadPollTask(ReadType.SCRIPT).execute(); } catch (Exception ex) { - LOG.info("poll script fail", ex); + LOG.error("poll script fail", ex); } }, sqlParserVO.getPollingStartSeconds().longValue(), 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 37/53] =?UTF-8?q?feature=20#I7YYLE=20=E6=B7=BB=E5=8A=A0=20?= =?UTF-8?q?Spring=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 d627276672188904f4421240a19fad194fab8aea Mon Sep 17 00:00:00 2001 From: gaibu <1016771049@qq.com> Date: Sun, 1 Oct 2023 15:39:37 +0800 Subject: [PATCH 38/53] =?UTF-8?q?sql=20=E6=8F=92=E4=BB=B6=20code=20review?= =?UTF-8?q?=20=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../liteflow/parser/constant/ReadType.java | 4 +- .../parser/constant/SqlReadConstant.java | 4 +- .../liteflow/parser/sql/SQLXmlELParser.java | 144 +++++++++--------- .../sql/polling/AbstractSqlReadPollTask.java | 14 +- .../parser/sql/polling/SqlReadPollTask.java | 15 +- .../sql/polling/impl/ChainReadPollTask.java | 8 +- .../sql/polling/impl/ScriptReadPollTask.java | 8 +- .../parser/sql/read/AbstractSqlRead.java | 5 +- .../liteflow/parser/sql/read/SqlRead.java | 8 +- .../parser/sql/read/SqlReadFactory.java | 11 +- .../parser/sql/read/impl/ChainRead.java | 4 +- .../parser/sql/read/impl/ScriptRead.java | 4 +- .../liteflow/parser/sql/util/JDBCHelper.java | 10 +- 13 files changed, 132 insertions(+), 107 deletions(-) diff --git a/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/constant/ReadType.java b/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/constant/ReadType.java index 812c5a5be..68cb72c98 100644 --- a/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/constant/ReadType.java +++ b/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/constant/ReadType.java @@ -3,8 +3,8 @@ package com.yomahub.liteflow.parser.constant; /** * sql 类型枚举 * - * @author tangkc huxinyu - * @date 2023/9/28 11:49 + * @author tangkc + * @author houxinyu * @since 2.11.1 */ public enum ReadType { diff --git a/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/constant/SqlReadConstant.java b/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/constant/SqlReadConstant.java index 80116f908..68d8e5ee8 100644 --- a/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/constant/SqlReadConstant.java +++ b/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/constant/SqlReadConstant.java @@ -3,8 +3,8 @@ package com.yomahub.liteflow.parser.constant; /** * sql 读取常量类 * - * @author tangkc huxinyu - * @date 2023/9/28 11:49 + * @author tangkc + * @author houxinyu * @since 2.11.1 */ public class SqlReadConstant { diff --git a/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/SQLXmlELParser.java b/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/SQLXmlELParser.java index 13301dbd5..4a08df95c 100644 --- a/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/SQLXmlELParser.java +++ b/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/SQLXmlELParser.java @@ -6,6 +6,7 @@ import cn.hutool.core.map.MapUtil; import cn.hutool.core.text.StrFormatter; import cn.hutool.core.util.StrUtil; import com.yomahub.liteflow.core.FlowInitHook; +import com.yomahub.liteflow.parser.constant.ReadType; import com.yomahub.liteflow.parser.el.ClassXmlFlowELParser; import com.yomahub.liteflow.parser.sql.exception.ELSQLException; import com.yomahub.liteflow.parser.sql.read.SqlReadFactory; @@ -25,86 +26,87 @@ import java.util.Objects; */ public class SQLXmlELParser extends ClassXmlFlowELParser { - private static SQLParserVO sqlParserVO; + private static SQLParserVO sqlParserVO; - private static final String ERROR_MSG_PATTERN = "rule-source-ext-data {} is blank"; + private static final String ERROR_MSG_PATTERN = "rule-source-ext-data {} is blank"; - private static final String ERROR_COMMON_MSG = "rule-source-ext-data is empty"; + private static final String ERROR_COMMON_MSG = "rule-source-ext-data is empty"; - /** - * 构造函数 - */ - public SQLXmlELParser() { - LiteflowConfig liteflowConfig = LiteflowConfigGetter.get(); + /** + * 构造函数 + */ + public SQLXmlELParser() { + LiteflowConfig liteflowConfig = LiteflowConfigGetter.get(); - try { - if (MapUtil.isNotEmpty((liteflowConfig.getRuleSourceExtDataMap()))) { - sqlParserVO = BeanUtil.toBean(liteflowConfig.getRuleSourceExtDataMap(), SQLParserVO.class, - CopyOptions.create()); - } - else if (StrUtil.isNotBlank(liteflowConfig.getRuleSourceExtData())) { - sqlParserVO = JsonUtil.parseObject(liteflowConfig.getRuleSourceExtData(), SQLParserVO.class); - } - if (Objects.isNull(sqlParserVO)) { - throw new ELSQLException(ERROR_COMMON_MSG); - } + try { + if (MapUtil.isNotEmpty((liteflowConfig.getRuleSourceExtDataMap()))) { + sqlParserVO = BeanUtil.toBean(liteflowConfig.getRuleSourceExtDataMap(), SQLParserVO.class, + CopyOptions.create()); + } else if (StrUtil.isNotBlank(liteflowConfig.getRuleSourceExtData())) { + sqlParserVO = JsonUtil.parseObject(liteflowConfig.getRuleSourceExtData(), SQLParserVO.class); + } + if (Objects.isNull(sqlParserVO)) { + throw new ELSQLException(ERROR_COMMON_MSG); + } - // 检查配置文件 - checkParserVO(sqlParserVO); + // 检查配置文件 + checkParserVO(sqlParserVO); - // 初始化 JDBCHelper - JDBCHelper.init(sqlParserVO); + // 初始化 JDBCHelper + JDBCHelper.init(sqlParserVO); - // 初始化 SqlReadFactory - SqlReadFactory.registerRead(sqlParserVO); - } - catch (ELSQLException elsqlException) { - throw elsqlException; - } - catch (Exception ex) { - throw new ELSQLException(ex.getMessage()); - } + // 初始化 SqlReadFactory + SqlReadFactory.registerRead(sqlParserVO); - } + // 注册轮询任务 + SqlReadFactory.registerSqlReadPollTask(ReadType.CHAIN); + SqlReadFactory.registerSqlReadPollTask(ReadType.SCRIPT); + } catch (ELSQLException elsqlException) { + throw elsqlException; + } catch (Exception ex) { + throw new ELSQLException(ex.getMessage()); + } - @Override - public String parseCustom() { - try{ - JDBCHelper jdbcHelper = JDBCHelper.getInstance(); - String content = jdbcHelper.getContent(); - if(sqlParserVO.getPollingEnabled()) { - FlowInitHook.addHook(() -> { - jdbcHelper.listenSQL(); - return true; - }); - } - return content; - } - catch (Exception ex) { - throw new ELSQLException(ex.getMessage()); - } - } + } - /** - * 检查配置文件并设置默认值 - * @param sqlParserVO sqlParserVO - */ - private void checkParserVO(SQLParserVO sqlParserVO) { - if (sqlParserVO.isDefaultDataSource()) { - return; - } - if (StrUtil.isEmpty(sqlParserVO.getUrl())) { - throw new ELSQLException(StrFormatter.format(ERROR_MSG_PATTERN, "url")); - } - if (StrUtil.isEmpty(sqlParserVO.getDriverClassName())) { - throw new ELSQLException(StrFormatter.format(ERROR_MSG_PATTERN, "driverClassName")); - } - if (Objects.isNull(sqlParserVO.getUsername())) { - throw new ELSQLException(StrFormatter.format(ERROR_MSG_PATTERN, "username")); - } - if (Objects.isNull(sqlParserVO.getPassword())) { - throw new ELSQLException(StrFormatter.format(ERROR_MSG_PATTERN, "password")); - } - } + @Override + public String parseCustom() { + try { + JDBCHelper jdbcHelper = JDBCHelper.getInstance(); + String content = jdbcHelper.getContent(); + if (sqlParserVO.getPollingEnabled()) { + FlowInitHook.addHook(() -> { + jdbcHelper.listenSQL(); + return true; + }); + } + return content; + } catch (Exception ex) { + throw new ELSQLException(ex.getMessage()); + } + } + + /** + * 检查配置文件并设置默认值 + * + * @param sqlParserVO sqlParserVO + */ + private void checkParserVO(SQLParserVO sqlParserVO) { + if (sqlParserVO.isDefaultDataSource()) { + return; + } + if (StrUtil.isEmpty(sqlParserVO.getUrl())) { + throw new ELSQLException(StrFormatter.format(ERROR_MSG_PATTERN, "url")); + } + if (StrUtil.isEmpty(sqlParserVO.getDriverClassName())) { + throw new ELSQLException(StrFormatter.format(ERROR_MSG_PATTERN, "driverClassName")); + } + if (Objects.isNull(sqlParserVO.getUsername())) { + throw new ELSQLException(StrFormatter.format(ERROR_MSG_PATTERN, "username")); + } + if (Objects.isNull(sqlParserVO.getPassword())) { + throw new ELSQLException(StrFormatter.format(ERROR_MSG_PATTERN, "password")); + } + } } diff --git a/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/polling/AbstractSqlReadPollTask.java b/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/polling/AbstractSqlReadPollTask.java index 2f3873865..d4049a4ca 100644 --- a/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/polling/AbstractSqlReadPollTask.java +++ b/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/polling/AbstractSqlReadPollTask.java @@ -15,17 +15,16 @@ import java.util.Set; /** * sql 轮询任务抽象类,维护公共方法 * - * @author tangkc huxinyu - * @date 2023/9/28 11:49 + * @author tangkc + * @author houxinyu * @since 2.11.1 */ public abstract class AbstractSqlReadPollTask implements SqlReadPollTask { - private final Map DATA_SHA_MAP; + private final Map DATA_SHA_MAP = new HashMap<>(); private final SqlRead read; - public AbstractSqlReadPollTask(Map dataMap, SqlRead read) { + public AbstractSqlReadPollTask(SqlRead read) { this.read = read; - this.DATA_SHA_MAP = shaMapValue(dataMap); if (!read.type().equals(type())) { throw new ELSQLException("SqlReadPollTask type not match"); @@ -81,6 +80,11 @@ public abstract class AbstractSqlReadPollTask implements SqlReadPollTask { } } + @Override + public void initData(Map dataMap) { + DATA_SHA_MAP.putAll(shaMapValue(dataMap)); + } + public abstract void doSave(Map saveElementMap); public abstract void doDelete(List deleteElementId); diff --git a/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/polling/SqlReadPollTask.java b/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/polling/SqlReadPollTask.java index bbe48aaaf..8c491e9ad 100644 --- a/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/polling/SqlReadPollTask.java +++ b/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/polling/SqlReadPollTask.java @@ -2,11 +2,13 @@ package com.yomahub.liteflow.parser.sql.polling; import com.yomahub.liteflow.parser.constant.ReadType; +import java.util.Map; + /** * sql 轮询任务接口 * - * @author tangkc huxinyu - * @date 2023/9/28 11:49 + * @author tangkc + * @author houxinyu * @since 2.11.1 */ public interface SqlReadPollTask { @@ -16,8 +18,17 @@ public interface SqlReadPollTask { */ void execute(); + /** + * 初始化数据 + * + * @param dataMap 数据 + */ + void initData(Map dataMap); + /** * 类型 + * + * @return 类型 */ ReadType type(); } diff --git a/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/polling/impl/ChainReadPollTask.java b/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/polling/impl/ChainReadPollTask.java index 0e13e0fc6..717ebc106 100644 --- a/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/polling/impl/ChainReadPollTask.java +++ b/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/polling/impl/ChainReadPollTask.java @@ -12,14 +12,14 @@ import java.util.Map; /** * chain 读取任务 * - * @author tangkc huxinyu - * @date 2023/9/28 11:49 + * @author tangkc + * @author houxinyu * @since 2.11.1 */ public class ChainReadPollTask extends AbstractSqlReadPollTask { - public ChainReadPollTask(Map dataMap, SqlRead read) { - super(dataMap, read); + public ChainReadPollTask(SqlRead read) { + super(read); } @Override diff --git a/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/polling/impl/ScriptReadPollTask.java b/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/polling/impl/ScriptReadPollTask.java index 539b5a849..77c6ce74d 100644 --- a/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/polling/impl/ScriptReadPollTask.java +++ b/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/polling/impl/ScriptReadPollTask.java @@ -12,13 +12,13 @@ import java.util.Map; /** * 脚本轮询任务 * - * @author tangkc huxinyu - * @date 2023/9/28 11:49 + * @author tangkc + * @author houxinyu * @since 2.11.1 */ public class ScriptReadPollTask extends AbstractSqlReadPollTask { - public ScriptReadPollTask(Map dataMap, SqlRead read) { - super(dataMap, read); + public ScriptReadPollTask(SqlRead read) { + super(read); } @Override diff --git a/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/read/AbstractSqlRead.java b/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/read/AbstractSqlRead.java index e598adbd1..4c144aef6 100644 --- a/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/read/AbstractSqlRead.java +++ b/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/read/AbstractSqlRead.java @@ -18,8 +18,8 @@ import java.util.Map; /** * sql 读取抽象类,维护公共方法 * - * @author tangkc huxinyu - * @date 2023/9/28 11:49 + * @author tangkc + * @author houxinyu * @since 2.11.1 */ public abstract class AbstractSqlRead implements SqlRead { @@ -80,6 +80,7 @@ public abstract class AbstractSqlRead implements SqlRead { * 是否可以读取 * chain 默认可以读取 * script 需要判断是否有配置 + * @return 布尔值 */ public boolean needRead() { return true; diff --git a/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/read/SqlRead.java b/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/read/SqlRead.java index 8b0bdb0ee..af003f8ea 100644 --- a/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/read/SqlRead.java +++ b/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/read/SqlRead.java @@ -7,19 +7,23 @@ import java.util.Map; /** * sql 读取接口 * - * @author tangkc huxinyu - * @date 2023/9/28 11:49 + * @author tangkc + * @author houxinyu * @since 2.11.1 */ public interface SqlRead { /** * 读取 + * + * @return 返回读取到的数据 */ Map read(); /** * 类型 + * + * @return 返回类型 */ ReadType type(); } diff --git a/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/read/SqlReadFactory.java b/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/read/SqlReadFactory.java index ad7cea54e..b08de78a9 100644 --- a/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/read/SqlReadFactory.java +++ b/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/read/SqlReadFactory.java @@ -14,8 +14,8 @@ import java.util.Map; /** * sql 读取工厂类 * - * @author tangkc huxinyu - * @date 2023/9/28 11:49 + * @author tangkc + * @author houxinyu * @since 2.11.1 */ public class SqlReadFactory { @@ -27,14 +27,13 @@ public class SqlReadFactory { READ_MAP.put(ReadType.SCRIPT, new ScriptRead(config)); } - public static void registerSqlReadPollTask(ReadType readType, Map dataMap) { + public static void registerSqlReadPollTask(ReadType readType) { SqlRead sqlRead = getSqlRead(readType); if (ReadType.CHAIN.equals(readType)) { - POLL_TASK_MAP.put(ReadType.CHAIN, new ChainReadPollTask(dataMap, sqlRead)); + POLL_TASK_MAP.put(ReadType.CHAIN, new ChainReadPollTask(sqlRead)); } else if (ReadType.SCRIPT.equals(readType)) { - POLL_TASK_MAP.put(ReadType.SCRIPT, new ScriptReadPollTask(dataMap, sqlRead)); + POLL_TASK_MAP.put(ReadType.SCRIPT, new ScriptReadPollTask(sqlRead)); } - } public static SqlRead getSqlRead(ReadType readType) { diff --git a/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/read/impl/ChainRead.java b/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/read/impl/ChainRead.java index 3eacc28c5..69eadd692 100644 --- a/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/read/impl/ChainRead.java +++ b/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/read/impl/ChainRead.java @@ -13,8 +13,8 @@ import java.sql.SQLException; /** * chain 读取 * - * @author tangkc huxinyu - * @date 2023/9/28 11:49 + * @author tangkc + * @author houxinyu * @since 2.11.1 */ public class ChainRead extends AbstractSqlRead { diff --git a/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/read/impl/ScriptRead.java b/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/read/impl/ScriptRead.java index 5fae2d029..a0b054b0d 100644 --- a/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/read/impl/ScriptRead.java +++ b/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/read/impl/ScriptRead.java @@ -20,8 +20,8 @@ import java.util.Objects; /** * 脚本读取 * - * @author tangkc huxinyu - * @date 2023/9/28 11:49 + * @author tangkc + * @author houxinyu * @since 2.11.1 */ public class ScriptRead extends AbstractSqlRead { diff --git a/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/util/JDBCHelper.java b/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/util/JDBCHelper.java index 0c3c4db2d..7b9b0efda 100644 --- a/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/util/JDBCHelper.java +++ b/liteflow-rule-plugin/liteflow-rule-sql/src/main/java/com/yomahub/liteflow/parser/sql/util/JDBCHelper.java @@ -72,6 +72,8 @@ public class JDBCHelper { /** * 获取 INSTANCE + * + * @return 实例 */ public static JDBCHelper getInstance() { return INSTANCE; @@ -79,6 +81,8 @@ public class JDBCHelper { /** * 获取 ElData 数据内容 + * + * @return 数据内容 */ public String getContent() { SqlRead chainRead = SqlReadFactory.getSqlRead(ReadType.CHAIN); @@ -110,9 +114,9 @@ public class JDBCHelper { }); String nodesContent = StrUtil.format(NODE_XML_PATTERN, CollUtil.join(scriptList, StrUtil.EMPTY)); - // 注册 - SqlReadFactory.registerSqlReadPollTask(ReadType.CHAIN, chainMap); - SqlReadFactory.registerSqlReadPollTask(ReadType.SCRIPT, scriptMap); + // 初始化轮询任务 + SqlReadFactory.getSqlReadPollTask(ReadType.CHAIN).initData(chainMap); + SqlReadFactory.getSqlReadPollTask(ReadType.SCRIPT).initData(scriptMap); return StrUtil.format(XML_PATTERN, nodesContent, chainsContent); } 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 39/53] =?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 40/53] =?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 a7ffee862e0056de9f1c00b91eccbd637eeaf97e Mon Sep 17 00:00:00 2001 From: luoyi <972849752@qq.com> Date: Mon, 2 Oct 2023 17:20:24 +0800 Subject: [PATCH 41/53] =?UTF-8?q?enhancement=20#I821F1=20=E8=B0=83?= =?UTF-8?q?=E6=95=B4=20Chain=20=E5=BE=AA=E7=8E=AF=E4=BE=9D=E8=B5=96?= =?UTF-8?q?=E6=B5=8B=E8=AF=95=E6=A1=88=E4=BE=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../FlowInDifferentConfigTest.java | 4 +- .../FlowJsonTest.java | 4 +- .../FlowXMLTest.java | 4 +- .../FlowYMLTest.java | 4 +- .../liteflow/test/endlessLoop/cmp/ACmp.java | 12 ++++ .../liteflow/test/endlessLoop/cmp/BCmp.java | 12 ++++ .../liteflow/test/endlessLoop/cmp/CCmp.java | 12 ++++ .../liteflow/test/endlessLoop/cmp/DCmp.java | 12 ++++ .../liteflow/test/endlessLoop/cmp/ECmp.java | 12 ++++ .../resources/endlessLoop/flow-main.el.xml | 13 +++++ .../endlessLoop/flow-sub1.el.xml | 0 .../test/resources/endlessLoop/flow.el.json | 42 ++++++++++++++ .../test/resources/endlessLoop/flow.el.xml | 21 +++++++ .../test/resources/endlessLoop/flow.el.yml | 20 +++++++ .../subflow/endlessLoop/flow-main.el.xml | 17 ------ .../subflow/endlessLoop/flow.el.json | 58 ------------------- .../resources/subflow/endlessLoop/flow.el.xml | 25 -------- .../resources/subflow/endlessLoop/flow.el.yml | 28 --------- ...FlowInDifferentConfigELSpringbootTest.java | 18 +++--- .../endlessLoop/FlowJsonELSpringBootTest.java | 17 +++--- .../endlessLoop/FlowXMLELSpringBootTest.java | 17 +++--- .../endlessLoop/FlowYmlELSpringBootTest.java | 17 +++--- .../liteflow/test/endlessLoop/cmp/ACmp.java | 14 +++++ .../liteflow/test/endlessLoop/cmp/BCmp.java | 14 +++++ .../liteflow/test/endlessLoop/cmp/CCmp.java | 14 +++++ .../liteflow/test/endlessLoop/cmp/DCmp.java | 14 +++++ .../liteflow/test/endlessLoop/cmp/ECmp.java | 14 +++++ .../endlessLoop/flow-sub1.el.xml | 0 .../endlessLoop/flow-sub2.el.yml | 0 .../{subflow => }/endlessLoop/flow.el.json | 0 .../{subflow => }/endlessLoop/flow.el.xml | 0 .../{subflow => }/endlessLoop/flow.el.yml | 0 .../endlessLoop/application-json.properties | 1 - ...plication-subInDifferentConfig1.properties | 2 - .../endlessLoop/application-xml.properties | 1 - .../endlessLoop/application-yml.properties | 1 - 36 files changed, 275 insertions(+), 169 deletions(-) rename liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/java/com/yomahub/liteflow/test/{subflow/endlessLopp => endlessLoop}/FlowInDifferentConfigTest.java (82%) rename liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/java/com/yomahub/liteflow/test/{subflow/endlessLopp => endlessLoop}/FlowJsonTest.java (86%) rename liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/java/com/yomahub/liteflow/test/{subflow/endlessLopp => endlessLoop}/FlowXMLTest.java (86%) rename liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/java/com/yomahub/liteflow/test/{subflow/endlessLopp => endlessLoop}/FlowYMLTest.java (86%) create mode 100644 liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/java/com/yomahub/liteflow/test/endlessLoop/cmp/ACmp.java create mode 100644 liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/java/com/yomahub/liteflow/test/endlessLoop/cmp/BCmp.java create mode 100644 liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/java/com/yomahub/liteflow/test/endlessLoop/cmp/CCmp.java create mode 100644 liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/java/com/yomahub/liteflow/test/endlessLoop/cmp/DCmp.java create mode 100644 liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/java/com/yomahub/liteflow/test/endlessLoop/cmp/ECmp.java create mode 100644 liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/resources/endlessLoop/flow-main.el.xml rename liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/resources/{subflow => }/endlessLoop/flow-sub1.el.xml (100%) create mode 100644 liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/resources/endlessLoop/flow.el.json create mode 100644 liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/resources/endlessLoop/flow.el.xml create mode 100644 liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/resources/endlessLoop/flow.el.yml delete mode 100644 liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/resources/subflow/endlessLoop/flow-main.el.xml delete mode 100644 liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/resources/subflow/endlessLoop/flow.el.json delete mode 100644 liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/resources/subflow/endlessLoop/flow.el.xml delete mode 100644 liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/resources/subflow/endlessLoop/flow.el.yml rename liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/{subflow => }/endlessLoop/FlowInDifferentConfigELSpringbootTest.java (57%) rename liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/{subflow => }/endlessLoop/FlowJsonELSpringBootTest.java (60%) rename liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/{subflow => }/endlessLoop/FlowXMLELSpringBootTest.java (60%) rename liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/{subflow => }/endlessLoop/FlowYmlELSpringBootTest.java (60%) create mode 100644 liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/endlessLoop/cmp/ACmp.java create mode 100644 liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/endlessLoop/cmp/BCmp.java create mode 100644 liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/endlessLoop/cmp/CCmp.java create mode 100644 liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/endlessLoop/cmp/DCmp.java create mode 100644 liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/endlessLoop/cmp/ECmp.java rename liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/{subflow => }/endlessLoop/flow-sub1.el.xml (100%) rename liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/{subflow => }/endlessLoop/flow-sub2.el.yml (100%) rename liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/{subflow => }/endlessLoop/flow.el.json (100%) rename liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/{subflow => }/endlessLoop/flow.el.xml (100%) rename liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/{subflow => }/endlessLoop/flow.el.yml (100%) delete mode 100644 liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/subflow/endlessLoop/application-json.properties delete mode 100644 liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/subflow/endlessLoop/application-subInDifferentConfig1.properties delete mode 100644 liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/subflow/endlessLoop/application-xml.properties delete mode 100644 liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/subflow/endlessLoop/application-yml.properties diff --git a/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/java/com/yomahub/liteflow/test/subflow/endlessLopp/FlowInDifferentConfigTest.java b/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/java/com/yomahub/liteflow/test/endlessLoop/FlowInDifferentConfigTest.java similarity index 82% rename from liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/java/com/yomahub/liteflow/test/subflow/endlessLopp/FlowInDifferentConfigTest.java rename to liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/java/com/yomahub/liteflow/test/endlessLoop/FlowInDifferentConfigTest.java index 24d21cc48..3017205c4 100644 --- a/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/java/com/yomahub/liteflow/test/subflow/endlessLopp/FlowInDifferentConfigTest.java +++ b/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/java/com/yomahub/liteflow/test/endlessLoop/FlowInDifferentConfigTest.java @@ -1,5 +1,5 @@ -package com.yomahub.liteflow.test.subflow.endlessLopp; +package com.yomahub.liteflow.test.endlessLoop; import com.yomahub.liteflow.core.FlowExecutorHolder; import com.yomahub.liteflow.exception.CyclicDependencyException; @@ -23,7 +23,7 @@ public class FlowInDifferentConfigTest extends BaseTest { public void testChainEndlessLoop() { Assertions.assertThrows(CyclicDependencyException.class, () -> { LiteflowConfig config = LiteflowConfigGetter.get(); - config.setRuleSource("subflow/endlessLoop/flow-main.el.xml,subflow/endlessLoop/flow-sub1.el.xml"); + config.setRuleSource("endlessLoop/flow-main.el.xml,endlessLoop/flow-sub1.el.xml"); FlowExecutorHolder.loadInstance(config); }); } diff --git a/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/java/com/yomahub/liteflow/test/subflow/endlessLopp/FlowJsonTest.java b/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/java/com/yomahub/liteflow/test/endlessLoop/FlowJsonTest.java similarity index 86% rename from liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/java/com/yomahub/liteflow/test/subflow/endlessLopp/FlowJsonTest.java rename to liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/java/com/yomahub/liteflow/test/endlessLoop/FlowJsonTest.java index 12b6f8c42..5f36f22aa 100644 --- a/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/java/com/yomahub/liteflow/test/subflow/endlessLopp/FlowJsonTest.java +++ b/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/java/com/yomahub/liteflow/test/endlessLoop/FlowJsonTest.java @@ -1,4 +1,4 @@ -package com.yomahub.liteflow.test.subflow.endlessLopp; +package com.yomahub.liteflow.test.endlessLoop; import com.yomahub.liteflow.core.FlowExecutorHolder; import com.yomahub.liteflow.exception.CyclicDependencyException; @@ -21,7 +21,7 @@ public class FlowJsonTest extends BaseTest { public void testChainEndlessLoop() { Assertions.assertThrows(CyclicDependencyException.class, () -> { LiteflowConfig config = LiteflowConfigGetter.get(); - config.setRuleSource("subflow/endlessLoop/flow.el.json"); + config.setRuleSource("endlessLoop/flow.el.json"); FlowExecutorHolder.loadInstance(config); }); } diff --git a/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/java/com/yomahub/liteflow/test/subflow/endlessLopp/FlowXMLTest.java b/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/java/com/yomahub/liteflow/test/endlessLoop/FlowXMLTest.java similarity index 86% rename from liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/java/com/yomahub/liteflow/test/subflow/endlessLopp/FlowXMLTest.java rename to liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/java/com/yomahub/liteflow/test/endlessLoop/FlowXMLTest.java index 465c4b4f2..3091e60a9 100644 --- a/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/java/com/yomahub/liteflow/test/subflow/endlessLopp/FlowXMLTest.java +++ b/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/java/com/yomahub/liteflow/test/endlessLoop/FlowXMLTest.java @@ -1,4 +1,4 @@ -package com.yomahub.liteflow.test.subflow.endlessLopp; +package com.yomahub.liteflow.test.endlessLoop; import com.yomahub.liteflow.core.FlowExecutorHolder; import com.yomahub.liteflow.exception.CyclicDependencyException; @@ -21,7 +21,7 @@ public class FlowXMLTest extends BaseTest { public void testChainEndlessLoop() { Assertions.assertThrows(CyclicDependencyException.class, () -> { LiteflowConfig config = LiteflowConfigGetter.get(); - config.setRuleSource("subflow/endlessLoop/flow.el.xml"); + config.setRuleSource("endlessLoop/flow.el.xml"); FlowExecutorHolder.loadInstance(config); }); } diff --git a/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/java/com/yomahub/liteflow/test/subflow/endlessLopp/FlowYMLTest.java b/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/java/com/yomahub/liteflow/test/endlessLoop/FlowYMLTest.java similarity index 86% rename from liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/java/com/yomahub/liteflow/test/subflow/endlessLopp/FlowYMLTest.java rename to liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/java/com/yomahub/liteflow/test/endlessLoop/FlowYMLTest.java index e586b7d8e..654cf63db 100644 --- a/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/java/com/yomahub/liteflow/test/subflow/endlessLopp/FlowYMLTest.java +++ b/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/java/com/yomahub/liteflow/test/endlessLoop/FlowYMLTest.java @@ -1,4 +1,4 @@ -package com.yomahub.liteflow.test.subflow.endlessLopp; +package com.yomahub.liteflow.test.endlessLoop; import com.yomahub.liteflow.core.FlowExecutorHolder; import com.yomahub.liteflow.exception.CyclicDependencyException; @@ -21,7 +21,7 @@ public class FlowYMLTest extends BaseTest { public void testChainEndlessLoop() { Assertions.assertThrows(CyclicDependencyException.class, () -> { LiteflowConfig config = LiteflowConfigGetter.get(); - config.setRuleSource("subflow/endlessLoop/flow.el.yml"); + config.setRuleSource("endlessLoop/flow.el.yml"); FlowExecutorHolder.loadInstance(config); }); } diff --git a/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/java/com/yomahub/liteflow/test/endlessLoop/cmp/ACmp.java b/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/java/com/yomahub/liteflow/test/endlessLoop/cmp/ACmp.java new file mode 100644 index 000000000..a98b541c2 --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/java/com/yomahub/liteflow/test/endlessLoop/cmp/ACmp.java @@ -0,0 +1,12 @@ +package com.yomahub.liteflow.test.endlessLoop.cmp; + +import com.yomahub.liteflow.core.NodeComponent; + +public class ACmp extends NodeComponent { + + @Override + public void process() { + System.out.println("Acomp executed!"); + } + +} diff --git a/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/java/com/yomahub/liteflow/test/endlessLoop/cmp/BCmp.java b/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/java/com/yomahub/liteflow/test/endlessLoop/cmp/BCmp.java new file mode 100644 index 000000000..f3699371e --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/java/com/yomahub/liteflow/test/endlessLoop/cmp/BCmp.java @@ -0,0 +1,12 @@ +package com.yomahub.liteflow.test.endlessLoop.cmp; + +import com.yomahub.liteflow.core.NodeComponent; + +public class BCmp extends NodeComponent { + + @Override + public void process() { + System.out.println("Bcomp executed!"); + } + +} diff --git a/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/java/com/yomahub/liteflow/test/endlessLoop/cmp/CCmp.java b/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/java/com/yomahub/liteflow/test/endlessLoop/cmp/CCmp.java new file mode 100644 index 000000000..d9abde6be --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/java/com/yomahub/liteflow/test/endlessLoop/cmp/CCmp.java @@ -0,0 +1,12 @@ +package com.yomahub.liteflow.test.endlessLoop.cmp; + +import com.yomahub.liteflow.core.NodeComponent; + +public class CCmp extends NodeComponent { + + @Override + public void process() throws Exception { + System.out.println("Ccomp executed!"); + } + +} diff --git a/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/java/com/yomahub/liteflow/test/endlessLoop/cmp/DCmp.java b/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/java/com/yomahub/liteflow/test/endlessLoop/cmp/DCmp.java new file mode 100644 index 000000000..b5ffafe78 --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/java/com/yomahub/liteflow/test/endlessLoop/cmp/DCmp.java @@ -0,0 +1,12 @@ +package com.yomahub.liteflow.test.endlessLoop.cmp; + +import com.yomahub.liteflow.core.NodeComponent; + +public class DCmp extends NodeComponent { + + @Override + public void process() throws Exception { + System.out.println("Dcomp executed!"); + } + +} diff --git a/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/java/com/yomahub/liteflow/test/endlessLoop/cmp/ECmp.java b/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/java/com/yomahub/liteflow/test/endlessLoop/cmp/ECmp.java new file mode 100644 index 000000000..fce4af378 --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/java/com/yomahub/liteflow/test/endlessLoop/cmp/ECmp.java @@ -0,0 +1,12 @@ +package com.yomahub.liteflow.test.endlessLoop.cmp; + +import com.yomahub.liteflow.core.NodeComponent; + +public class ECmp extends NodeComponent { + + @Override + public void process() throws Exception { + System.out.println("Ecomp executed!"); + } + +} diff --git a/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/resources/endlessLoop/flow-main.el.xml b/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/resources/endlessLoop/flow-main.el.xml new file mode 100644 index 000000000..2100fc65f --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/resources/endlessLoop/flow-main.el.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + THEN(a, b, chain2); + + \ No newline at end of file diff --git a/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/resources/subflow/endlessLoop/flow-sub1.el.xml b/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/resources/endlessLoop/flow-sub1.el.xml similarity index 100% rename from liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/resources/subflow/endlessLoop/flow-sub1.el.xml rename to liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/resources/endlessLoop/flow-sub1.el.xml diff --git a/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/resources/endlessLoop/flow.el.json b/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/resources/endlessLoop/flow.el.json new file mode 100644 index 000000000..b63faed4d --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/resources/endlessLoop/flow.el.json @@ -0,0 +1,42 @@ +{ + "flow": { + "nodes": { + "node": [ + { + "id": "a", + "class": "com.yomahub.liteflow.test.endlessLoop.cmp.ACmp" + }, + { + "id": "b", + "class": "com.yomahub.liteflow.test.endlessLoop.cmp.BCmp" + }, + { + "id": "c", + "class": "com.yomahub.liteflow.test.endlessLoop.cmp.CCmp" + }, + { + "id": "d", + "class": "com.yomahub.liteflow.test.endlessLoop.cmp.DCmp" + }, + { + "id": "e", + "class": "com.yomahub.liteflow.test.endlessLoop.cmp.ECmp" + } + ] + }, + "chain": [ + { + "name": "chain7", + "value": "THEN(a, chain8);" + }, + { + "name": "chain8", + "value": "THEN(b, chain9);" + }, + { + "name": "chain9", + "value": "WHEN(c, chain7);" + } + ] + } +} \ No newline at end of file diff --git a/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/resources/endlessLoop/flow.el.xml b/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/resources/endlessLoop/flow.el.xml new file mode 100644 index 000000000..fdd72433d --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/resources/endlessLoop/flow.el.xml @@ -0,0 +1,21 @@ + + + + + + + + + + + THEN(a, chain2); + + + + THEN(b, chain3); + + + + THEN(c, chain1); + + \ No newline at end of file diff --git a/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/resources/endlessLoop/flow.el.yml b/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/resources/endlessLoop/flow.el.yml new file mode 100644 index 000000000..c82163e7c --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/resources/endlessLoop/flow.el.yml @@ -0,0 +1,20 @@ +flow: + nodes: + node: + - id: a + class: com.yomahub.liteflow.test.endlessLoop.cmp.ACmp + - id: b + class: com.yomahub.liteflow.test.endlessLoop.cmp.BCmp + - id: c + class: com.yomahub.liteflow.test.endlessLoop.cmp.CCmp + - id: d + class: com.yomahub.liteflow.test.endlessLoop.cmp.DCmp + - id: e + class: com.yomahub.liteflow.test.endlessLoop.cmp.ECmp + chain: + - name: chain4 + value: "THEN(a, chain5);" + - name: chain5 + value: "THEN(b, chain6);" + - name: chain6 + value: "THEN(c, chain5);" \ No newline at end of file diff --git a/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/resources/subflow/endlessLoop/flow-main.el.xml b/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/resources/subflow/endlessLoop/flow-main.el.xml deleted file mode 100644 index 4f479f6e5..000000000 --- a/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/resources/subflow/endlessLoop/flow-main.el.xml +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - - - - - - - - - THEN(a, b, chain2); - - \ No newline at end of file diff --git a/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/resources/subflow/endlessLoop/flow.el.json b/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/resources/subflow/endlessLoop/flow.el.json deleted file mode 100644 index e1012cc73..000000000 --- a/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/resources/subflow/endlessLoop/flow.el.json +++ /dev/null @@ -1,58 +0,0 @@ -{ - "flow": { - "nodes": { - "node": [ - { - "id": "a", - "class": "com.yomahub.liteflow.test.subflow.cmp1.ACmp" - }, - { - "id": "b", - "class": "com.yomahub.liteflow.test.subflow.cmp1.BCmp" - }, - { - "id": "c", - "class": "com.yomahub.liteflow.test.subflow.cmp1.CCmp" - }, - { - "id": "d", - "class": "com.yomahub.liteflow.test.subflow.cmp1.DCmp" - }, - { - "id": "e", - "class": "com.yomahub.liteflow.test.subflow.cmp1.ECmp" - }, - { - "id": "f", - "class": "com.yomahub.liteflow.test.subflow.cmp2.FCmp" - }, - { - "id": "g", - "class": "com.yomahub.liteflow.test.subflow.cmp2.GCmp" - }, - { - "id": "h", - "class": "com.yomahub.liteflow.test.subflow.cmp2.HCmp" - }, - { - "id": "M", - "class": "com.yomahub.liteflow.test.subflow.cmp2.MCmp" - } - ] - }, - "chain": [ - { - "name": "chain7", - "value": "THEN(a, chain8);" - }, - { - "name": "chain8", - "value": "THEN(b, chain9);" - }, - { - "name": "chain9", - "value": "WHEN(c, chain7);" - } - ] - } -} \ No newline at end of file diff --git a/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/resources/subflow/endlessLoop/flow.el.xml b/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/resources/subflow/endlessLoop/flow.el.xml deleted file mode 100644 index 38120c94f..000000000 --- a/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/resources/subflow/endlessLoop/flow.el.xml +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - - - - - - - - THEN(a, chain2); - - - - THEN(b, chain3); - - - - THEN(c, chain1); - - \ No newline at end of file diff --git a/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/resources/subflow/endlessLoop/flow.el.yml b/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/resources/subflow/endlessLoop/flow.el.yml deleted file mode 100644 index efdf7b431..000000000 --- a/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/resources/subflow/endlessLoop/flow.el.yml +++ /dev/null @@ -1,28 +0,0 @@ -flow: - nodes: - node: - - id: a - class: com.yomahub.liteflow.test.subflow.cmp1.ACmp - - id: b - class: com.yomahub.liteflow.test.subflow.cmp1.BCmp - - id: c - class: com.yomahub.liteflow.test.subflow.cmp1.CCmp - - id: d - class: com.yomahub.liteflow.test.subflow.cmp1.DCmp - - id: e - class: com.yomahub.liteflow.test.subflow.cmp1.ECmp - - id: f - class: com.yomahub.liteflow.test.subflow.cmp2.FCmp - - id: g - class: com.yomahub.liteflow.test.subflow.cmp2.GCmp - - id: h - class: com.yomahub.liteflow.test.subflow.cmp2.HCmp - - id: h - class: com.yomahub.liteflow.test.subflow.cmp2.MCmp - chain: - - name: chain4 - value: "THEN(a, chain5);" - - name: chain5 - value: "THEN(b, chain6);" - - name: chain6 - value: "THEN(c, chain5);" \ No newline at end of file diff --git a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/subflow/endlessLoop/FlowInDifferentConfigELSpringbootTest.java b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/endlessLoop/FlowInDifferentConfigELSpringbootTest.java similarity index 57% rename from liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/subflow/endlessLoop/FlowInDifferentConfigELSpringbootTest.java rename to liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/endlessLoop/FlowInDifferentConfigELSpringbootTest.java index ca5ea0fed..90efa473c 100644 --- a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/subflow/endlessLoop/FlowInDifferentConfigELSpringbootTest.java +++ b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/endlessLoop/FlowInDifferentConfigELSpringbootTest.java @@ -1,14 +1,15 @@ -package com.yomahub.liteflow.test.subflow.endlessLoop; +package com.yomahub.liteflow.test.endlessLoop; import com.yomahub.liteflow.core.FlowExecutor; -import com.yomahub.liteflow.flow.LiteflowResponse; +import com.yomahub.liteflow.exception.CyclicDependencyException; +import com.yomahub.liteflow.property.LiteflowConfig; +import com.yomahub.liteflow.property.LiteflowConfigGetter; 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; @@ -18,10 +19,9 @@ import javax.annotation.Resource; * @author luo yi * @since 2.11.1 */ -@TestPropertySource(value = "classpath:/subflow/endlessLoop/application-subInDifferentConfig1.properties") @SpringBootTest(classes = FlowInDifferentConfigELSpringbootTest.class) @EnableAutoConfiguration -@ComponentScan({ "com.yomahub.liteflow.test.subflow.cmp1", "com.yomahub.liteflow.test.subflow.cmp2" }) +@ComponentScan({ "com.yomahub.liteflow.test.endlessLoop.cmp"}) public class FlowInDifferentConfigELSpringbootTest extends BaseTest { @Resource @@ -30,8 +30,12 @@ public class FlowInDifferentConfigELSpringbootTest extends BaseTest { // 测试 chain 死循环 @Test public void testChainEndlessLoop() { - LiteflowResponse response = flowExecutor.execute2Resp("chain1", "it's a request"); - Assertions.assertFalse(response.isSuccess()); + Assertions.assertThrows(CyclicDependencyException.class, () -> { + LiteflowConfig config = LiteflowConfigGetter.get(); + config.setRuleSource("endlessLoop/flow-sub1.el.xml,endlessLoop/flow-sub2.el.yml"); + config.setSupportMultipleType(true); + flowExecutor.reloadRule(); + }); } } diff --git a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/subflow/endlessLoop/FlowJsonELSpringBootTest.java b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/endlessLoop/FlowJsonELSpringBootTest.java similarity index 60% rename from liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/subflow/endlessLoop/FlowJsonELSpringBootTest.java rename to liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/endlessLoop/FlowJsonELSpringBootTest.java index b0d97aa1b..8bcb71cbf 100644 --- a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/subflow/endlessLoop/FlowJsonELSpringBootTest.java +++ b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/endlessLoop/FlowJsonELSpringBootTest.java @@ -1,14 +1,15 @@ -package com.yomahub.liteflow.test.subflow.endlessLoop; +package com.yomahub.liteflow.test.endlessLoop; import com.yomahub.liteflow.core.FlowExecutor; -import com.yomahub.liteflow.flow.LiteflowResponse; +import com.yomahub.liteflow.exception.CyclicDependencyException; +import com.yomahub.liteflow.property.LiteflowConfig; +import com.yomahub.liteflow.property.LiteflowConfigGetter; 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; @@ -18,10 +19,9 @@ import javax.annotation.Resource; * @author luo yi * @since 2.11.1 */ -@TestPropertySource(value = "classpath:/subflow/endlessLoop/application-json.properties") @SpringBootTest(classes = FlowJsonELSpringBootTest.class) @EnableAutoConfiguration -@ComponentScan({ "com.yomahub.liteflow.test.subflow.cmp1" }) +@ComponentScan({ "com.yomahub.liteflow.test.endlessLoop.cmp" }) public class FlowJsonELSpringBootTest extends BaseTest { @Resource @@ -30,8 +30,11 @@ public class FlowJsonELSpringBootTest extends BaseTest { // 测试 chain 死循环 @Test public void testChainEndlessLoop() { - LiteflowResponse response = flowExecutor.execute2Resp("chain7", "it's a request"); - Assertions.assertFalse(response.isSuccess()); + Assertions.assertThrows(CyclicDependencyException.class, () -> { + LiteflowConfig config = LiteflowConfigGetter.get(); + config.setRuleSource("endlessLoop/flow.el.json"); + flowExecutor.reloadRule(); + }); } } diff --git a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/subflow/endlessLoop/FlowXMLELSpringBootTest.java b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/endlessLoop/FlowXMLELSpringBootTest.java similarity index 60% rename from liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/subflow/endlessLoop/FlowXMLELSpringBootTest.java rename to liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/endlessLoop/FlowXMLELSpringBootTest.java index 6543f63d3..585cb02eb 100644 --- a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/subflow/endlessLoop/FlowXMLELSpringBootTest.java +++ b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/endlessLoop/FlowXMLELSpringBootTest.java @@ -1,14 +1,15 @@ -package com.yomahub.liteflow.test.subflow.endlessLoop; +package com.yomahub.liteflow.test.endlessLoop; import com.yomahub.liteflow.core.FlowExecutor; -import com.yomahub.liteflow.flow.LiteflowResponse; +import com.yomahub.liteflow.exception.CyclicDependencyException; +import com.yomahub.liteflow.property.LiteflowConfig; +import com.yomahub.liteflow.property.LiteflowConfigGetter; 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; @@ -18,10 +19,9 @@ import javax.annotation.Resource; * @author luo yi * @since 2.11.1 */ -@TestPropertySource(value = "classpath:/subflow/endlessLoop/application-xml.properties") @SpringBootTest(classes = FlowXMLELSpringBootTest.class) @EnableAutoConfiguration -@ComponentScan({ "com.yomahub.liteflow.test.subflow.cmp1" }) +@ComponentScan({ "com.yomahub.liteflow.test.endlessLoop.cmp" }) public class FlowXMLELSpringBootTest extends BaseTest { @Resource @@ -30,8 +30,11 @@ public class FlowXMLELSpringBootTest extends BaseTest { // 测试 chain 死循环 @Test public void testChainEndlessLoop() { - LiteflowResponse response = flowExecutor.execute2Resp("chain1", "it's a request"); - Assertions.assertFalse(response.isSuccess()); + Assertions.assertThrows(CyclicDependencyException.class, () -> { + LiteflowConfig config = LiteflowConfigGetter.get(); + config.setRuleSource("endlessLoop/flow.el.xml"); + flowExecutor.reloadRule(); + }); } } diff --git a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/subflow/endlessLoop/FlowYmlELSpringBootTest.java b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/endlessLoop/FlowYmlELSpringBootTest.java similarity index 60% rename from liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/subflow/endlessLoop/FlowYmlELSpringBootTest.java rename to liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/endlessLoop/FlowYmlELSpringBootTest.java index f9a6d8f75..4df3d56db 100644 --- a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/subflow/endlessLoop/FlowYmlELSpringBootTest.java +++ b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/endlessLoop/FlowYmlELSpringBootTest.java @@ -1,14 +1,15 @@ -package com.yomahub.liteflow.test.subflow.endlessLoop; +package com.yomahub.liteflow.test.endlessLoop; import com.yomahub.liteflow.core.FlowExecutor; -import com.yomahub.liteflow.flow.LiteflowResponse; +import com.yomahub.liteflow.exception.CyclicDependencyException; +import com.yomahub.liteflow.property.LiteflowConfig; +import com.yomahub.liteflow.property.LiteflowConfigGetter; 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; @@ -18,10 +19,9 @@ import javax.annotation.Resource; * @author luo yi * @since 2.11.1 */ -@TestPropertySource(value = "classpath:/subflow/endlessLoop/application-yml.properties") @SpringBootTest(classes = FlowYmlELSpringBootTest.class) @EnableAutoConfiguration -@ComponentScan({ "com.yomahub.liteflow.test.subflow.cmp1" }) +@ComponentScan({ "com.yomahub.liteflow.test.endlessLoop.cmp" }) public class FlowYmlELSpringBootTest extends BaseTest { @Resource @@ -30,8 +30,11 @@ public class FlowYmlELSpringBootTest extends BaseTest { // 测试 chain 死循环 @Test public void testChainEndlessLoop() { - LiteflowResponse response = flowExecutor.execute2Resp("chain5", "it's a request"); - Assertions.assertFalse(response.isSuccess()); + Assertions.assertThrows(CyclicDependencyException.class, () -> { + LiteflowConfig config = LiteflowConfigGetter.get(); + config.setRuleSource("endlessLoop/flow.el.yml"); + flowExecutor.reloadRule(); + }); } } diff --git a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/endlessLoop/cmp/ACmp.java b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/endlessLoop/cmp/ACmp.java new file mode 100644 index 000000000..17c75c038 --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/endlessLoop/cmp/ACmp.java @@ -0,0 +1,14 @@ +package com.yomahub.liteflow.test.endlessLoop.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("Acomp executed!"); + } + +} diff --git a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/endlessLoop/cmp/BCmp.java b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/endlessLoop/cmp/BCmp.java new file mode 100644 index 000000000..cdaa88716 --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/endlessLoop/cmp/BCmp.java @@ -0,0 +1,14 @@ +package com.yomahub.liteflow.test.endlessLoop.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("Bcomp executed!"); + } + +} diff --git a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/endlessLoop/cmp/CCmp.java b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/endlessLoop/cmp/CCmp.java new file mode 100644 index 000000000..7d9ec1ab6 --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/endlessLoop/cmp/CCmp.java @@ -0,0 +1,14 @@ +package com.yomahub.liteflow.test.endlessLoop.cmp; + +import com.yomahub.liteflow.core.NodeComponent; +import org.springframework.stereotype.Component; + +@Component("c") +public class CCmp extends NodeComponent { + + @Override + public void process() throws Exception { + System.out.println("Ccomp executed!"); + } + +} diff --git a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/endlessLoop/cmp/DCmp.java b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/endlessLoop/cmp/DCmp.java new file mode 100644 index 000000000..bf2f50f39 --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/endlessLoop/cmp/DCmp.java @@ -0,0 +1,14 @@ +package com.yomahub.liteflow.test.endlessLoop.cmp; + +import com.yomahub.liteflow.core.NodeComponent; +import org.springframework.stereotype.Component; + +@Component("d") +public class DCmp extends NodeComponent { + + @Override + public void process() throws Exception { + System.out.println("Dcomp executed!"); + } + +} diff --git a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/endlessLoop/cmp/ECmp.java b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/endlessLoop/cmp/ECmp.java new file mode 100644 index 000000000..5a010ea22 --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/endlessLoop/cmp/ECmp.java @@ -0,0 +1,14 @@ +package com.yomahub.liteflow.test.endlessLoop.cmp; + +import com.yomahub.liteflow.core.NodeComponent; +import org.springframework.stereotype.Component; + +@Component("e") +public class ECmp extends NodeComponent { + + @Override + public void process() throws Exception { + System.out.println("Ecomp executed!"); + } + +} diff --git a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/subflow/endlessLoop/flow-sub1.el.xml b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/endlessLoop/flow-sub1.el.xml similarity index 100% rename from liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/subflow/endlessLoop/flow-sub1.el.xml rename to liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/endlessLoop/flow-sub1.el.xml diff --git a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/subflow/endlessLoop/flow-sub2.el.yml b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/endlessLoop/flow-sub2.el.yml similarity index 100% rename from liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/subflow/endlessLoop/flow-sub2.el.yml rename to liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/endlessLoop/flow-sub2.el.yml diff --git a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/subflow/endlessLoop/flow.el.json b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/endlessLoop/flow.el.json similarity index 100% rename from liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/subflow/endlessLoop/flow.el.json rename to liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/endlessLoop/flow.el.json diff --git a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/subflow/endlessLoop/flow.el.xml b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/endlessLoop/flow.el.xml similarity index 100% rename from liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/subflow/endlessLoop/flow.el.xml rename to liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/endlessLoop/flow.el.xml diff --git a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/subflow/endlessLoop/flow.el.yml b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/endlessLoop/flow.el.yml similarity index 100% rename from liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/subflow/endlessLoop/flow.el.yml rename to liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/endlessLoop/flow.el.yml diff --git a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/subflow/endlessLoop/application-json.properties b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/subflow/endlessLoop/application-json.properties deleted file mode 100644 index f19fd93f5..000000000 --- a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/subflow/endlessLoop/application-json.properties +++ /dev/null @@ -1 +0,0 @@ -liteflow.rule-source=subflow/endlessLoop/flow.el.json \ No newline at end of file diff --git a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/subflow/endlessLoop/application-subInDifferentConfig1.properties b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/subflow/endlessLoop/application-subInDifferentConfig1.properties deleted file mode 100644 index 418d38274..000000000 --- a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/subflow/endlessLoop/application-subInDifferentConfig1.properties +++ /dev/null @@ -1,2 +0,0 @@ -liteflow.rule-source=subflow/endlessLoop/flow-sub1.el.xml,subflow/endlessLoop/flow-sub2.el.yml -liteflow.support-multiple-type=true \ No newline at end of file diff --git a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/subflow/endlessLoop/application-xml.properties b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/subflow/endlessLoop/application-xml.properties deleted file mode 100644 index d2261bca5..000000000 --- a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/subflow/endlessLoop/application-xml.properties +++ /dev/null @@ -1 +0,0 @@ -liteflow.rule-source=subflow/endlessLoop/flow.el.xml \ No newline at end of file diff --git a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/subflow/endlessLoop/application-yml.properties b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/subflow/endlessLoop/application-yml.properties deleted file mode 100644 index a9088ce2e..000000000 --- a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/subflow/endlessLoop/application-yml.properties +++ /dev/null @@ -1 +0,0 @@ -liteflow.rule-source=subflow/endlessLoop/flow.el.yml \ 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 42/53] =?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 43/53] =?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 baff77a82cdfad601db8eb4f91630c45d52eb18a Mon Sep 17 00:00:00 2001 From: rain <672378783@qq.com> Date: Wed, 4 Oct 2023 14:52:23 +0800 Subject: [PATCH 44/53] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E5=9B=9E=E6=BB=9A?= =?UTF-8?q?=E7=BB=84=E4=BB=B6=E6=97=A0=E6=B3=95=E8=8E=B7=E5=BE=97tag?= =?UTF-8?q?=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../rollback/RollbackELDeclMultiSpringbootTest.java | 10 ++++++++++ .../liteflow/test/rollback/cmp/CmpConfig.java | 12 ++++++++++++ .../src/test/resources/rollback/flow.el.xml | 4 ++++ .../test/rollback/RollbackELDeclSpringbootTest.java | 10 ++++++++++ .../com/yomahub/liteflow/test/rollback/cmp/ACmp.java | 12 ++++++++++++ .../src/test/resources/rollback/flow.el.xml | 4 ++++ .../yomahub/liteflow/test/rollback/RollbackTest.java | 10 ++++++++++ .../com/yomahub/liteflow/test/rollback/cmp/ACmp.java | 12 ++++++++++++ .../src/test/resources/rollback/flow.el.xml | 4 ++++ .../test/rollback/RollbackSpringbootTest.java | 10 ++++++++++ .../com/yomahub/liteflow/test/rollback/cmp/ACmp.java | 12 ++++++++++++ .../src/test/resources/rollback/flow.el.xml | 4 ++++ .../test/rollback/RollbackSpringbootTest.java | 10 ++++++++++ .../com/yomahub/liteflow/test/rollback/cmp/ACmp.java | 12 ++++++++++++ .../src/test/resources/rollback/flow.el.xml | 4 ++++ .../liteflow/test/rollback/RollbackSpringTest.java | 10 ++++++++++ .../com/yomahub/liteflow/test/rollback/cmp/ACmp.java | 12 ++++++++++++ .../src/test/resources/rollback/flow.el.xml | 4 ++++ 18 files changed, 156 insertions(+) diff --git a/liteflow-testcase-el/liteflow-testcase-el-declare-multi-springboot/src/test/java/com/yomahub/liteflow/test/rollback/RollbackELDeclMultiSpringbootTest.java b/liteflow-testcase-el/liteflow-testcase-el-declare-multi-springboot/src/test/java/com/yomahub/liteflow/test/rollback/RollbackELDeclMultiSpringbootTest.java index a012753ac..022dc9aec 100644 --- a/liteflow-testcase-el/liteflow-testcase-el-declare-multi-springboot/src/test/java/com/yomahub/liteflow/test/rollback/RollbackELDeclMultiSpringbootTest.java +++ b/liteflow-testcase-el/liteflow-testcase-el-declare-multi-springboot/src/test/java/com/yomahub/liteflow/test/rollback/RollbackELDeclMultiSpringbootTest.java @@ -2,6 +2,7 @@ package com.yomahub.liteflow.test.rollback; import com.yomahub.liteflow.core.FlowExecutor; import com.yomahub.liteflow.flow.LiteflowResponse; +import com.yomahub.liteflow.slot.DefaultContext; import com.yomahub.liteflow.test.BaseTest; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; @@ -90,4 +91,13 @@ public class RollbackELDeclMultiSpringbootTest extends BaseTest { Assertions.assertEquals("", response.getRollbackStepStr()); } + @Test + // 对获取数据的测试 + public void testData() throws Exception { + LiteflowResponse response = flowExecutor.execute2Resp("chain9", "arg"); + DefaultContext context = response.getFirstContextBean(); + Assertions.assertFalse(response.isSuccess()); + Assertions.assertEquals("321", context.getData("test")); + } + } diff --git a/liteflow-testcase-el/liteflow-testcase-el-declare-multi-springboot/src/test/java/com/yomahub/liteflow/test/rollback/cmp/CmpConfig.java b/liteflow-testcase-el/liteflow-testcase-el-declare-multi-springboot/src/test/java/com/yomahub/liteflow/test/rollback/cmp/CmpConfig.java index fb61212f6..1c1e43ad8 100644 --- a/liteflow-testcase-el/liteflow-testcase-el-declare-multi-springboot/src/test/java/com/yomahub/liteflow/test/rollback/cmp/CmpConfig.java +++ b/liteflow-testcase-el/liteflow-testcase-el-declare-multi-springboot/src/test/java/com/yomahub/liteflow/test/rollback/cmp/CmpConfig.java @@ -6,6 +6,7 @@ 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 com.yomahub.liteflow.slot.DefaultContext; import java.util.Iterator; import java.util.List; @@ -20,6 +21,17 @@ public class CmpConfig { @LiteflowMethod(value = LiteFlowMethodEnum.ROLLBACK, nodeId = "a") public void rollbackA(NodeComponent bindCmp) throws Exception { + String testKey = "test"; + + DefaultContext context = bindCmp.getFirstContextBean(); + if (context.getData(testKey) == null) { + context.setData(testKey, bindCmp.getTag()); + } + else { + String s = context.getData(testKey); + s += bindCmp.getTag(); + context.setData(testKey, s); + } System.out.println("ACmp rollback!"); } diff --git a/liteflow-testcase-el/liteflow-testcase-el-declare-multi-springboot/src/test/resources/rollback/flow.el.xml b/liteflow-testcase-el/liteflow-testcase-el-declare-multi-springboot/src/test/resources/rollback/flow.el.xml index 1857166a3..887403167 100644 --- a/liteflow-testcase-el/liteflow-testcase-el-declare-multi-springboot/src/test/resources/rollback/flow.el.xml +++ b/liteflow-testcase-el/liteflow-testcase-el-declare-multi-springboot/src/test/resources/rollback/flow.el.xml @@ -31,4 +31,8 @@ CATCH( THEN(b, c, d) ).DO(a); + + + THEN(a.tag("1"), a.tag("2"), a.tag("3"), d); + \ No newline at end of file diff --git a/liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/java/com/yomahub/liteflow/test/rollback/RollbackELDeclSpringbootTest.java b/liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/java/com/yomahub/liteflow/test/rollback/RollbackELDeclSpringbootTest.java index c6dc23465..c89f3c72c 100644 --- a/liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/java/com/yomahub/liteflow/test/rollback/RollbackELDeclSpringbootTest.java +++ b/liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/java/com/yomahub/liteflow/test/rollback/RollbackELDeclSpringbootTest.java @@ -2,6 +2,7 @@ package com.yomahub.liteflow.test.rollback; import com.yomahub.liteflow.core.FlowExecutor; import com.yomahub.liteflow.flow.LiteflowResponse; +import com.yomahub.liteflow.slot.DefaultContext; import com.yomahub.liteflow.test.BaseTest; import com.yomahub.liteflow.test.whenTimeOut.WhenTimeOutELDeclSpringbootTest1; import org.junit.jupiter.api.Assertions; @@ -92,4 +93,13 @@ public class RollbackELDeclSpringbootTest extends BaseTest { Assertions.assertEquals("", response.getRollbackStepStr()); } + @Test + // 对获取数据的测试 + public void testData() throws Exception { + LiteflowResponse response = flowExecutor.execute2Resp("chain9", "arg"); + DefaultContext context = response.getFirstContextBean(); + Assertions.assertFalse(response.isSuccess()); + Assertions.assertEquals("321", context.getData("test")); + } + } diff --git a/liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/java/com/yomahub/liteflow/test/rollback/cmp/ACmp.java b/liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/java/com/yomahub/liteflow/test/rollback/cmp/ACmp.java index cb52a08b3..a29efd0db 100644 --- a/liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/java/com/yomahub/liteflow/test/rollback/cmp/ACmp.java +++ b/liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/java/com/yomahub/liteflow/test/rollback/cmp/ACmp.java @@ -8,6 +8,7 @@ package com.yomahub.liteflow.test.rollback.cmp; import com.yomahub.liteflow.core.NodeComponent; +import com.yomahub.liteflow.slot.DefaultContext; import org.springframework.stereotype.Component; @Component("a") @@ -20,6 +21,17 @@ public class ACmp extends NodeComponent { @Override public void rollback() throws Exception { + String testKey = "test"; + + DefaultContext context = this.getFirstContextBean(); + if (context.getData(testKey) == null) { + context.setData(testKey, this.getTag()); + } + else { + String s = context.getData(testKey); + s += this.getTag(); + context.setData(testKey, s); + } System.out.println("ACmp rollback!"); } } diff --git a/liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/resources/rollback/flow.el.xml b/liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/resources/rollback/flow.el.xml index b0cb7fcd9..2e46ba7af 100644 --- a/liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/resources/rollback/flow.el.xml +++ b/liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/resources/rollback/flow.el.xml @@ -31,4 +31,8 @@ CATCH( THEN(b, c, d) ).DO(a); + + + THEN(a.tag("1"), a.tag("2"), a.tag("3"), d); + \ No newline at end of file diff --git a/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/java/com/yomahub/liteflow/test/rollback/RollbackTest.java b/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/java/com/yomahub/liteflow/test/rollback/RollbackTest.java index 4a3239e46..f8d58918e 100644 --- a/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/java/com/yomahub/liteflow/test/rollback/RollbackTest.java +++ b/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/java/com/yomahub/liteflow/test/rollback/RollbackTest.java @@ -3,7 +3,9 @@ package com.yomahub.liteflow.test.rollback; import com.yomahub.liteflow.core.FlowExecutor; import com.yomahub.liteflow.core.FlowExecutorHolder; import com.yomahub.liteflow.flow.LiteflowResponse; +import com.yomahub.liteflow.flow.entity.CmpStep; import com.yomahub.liteflow.property.LiteflowConfig; +import com.yomahub.liteflow.slot.DefaultContext; import com.yomahub.liteflow.test.BaseTest; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeAll; @@ -88,5 +90,13 @@ public class RollbackTest extends BaseTest { Assertions.assertEquals("", response.getRollbackStepStr()); } + @Test + // 对获取数据的测试 + public void testData() throws Exception { + LiteflowResponse response = flowExecutor.execute2Resp("chain9", "arg"); + DefaultContext context = response.getFirstContextBean(); + Assertions.assertFalse(response.isSuccess()); + Assertions.assertEquals("321", context.getData("test")); + } } diff --git a/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/java/com/yomahub/liteflow/test/rollback/cmp/ACmp.java b/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/java/com/yomahub/liteflow/test/rollback/cmp/ACmp.java index 269b3ba9a..f1a43cfb1 100644 --- a/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/java/com/yomahub/liteflow/test/rollback/cmp/ACmp.java +++ b/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/java/com/yomahub/liteflow/test/rollback/cmp/ACmp.java @@ -8,6 +8,7 @@ package com.yomahub.liteflow.test.rollback.cmp; import com.yomahub.liteflow.core.NodeComponent; +import com.yomahub.liteflow.slot.DefaultContext; public class ACmp extends NodeComponent { @@ -18,6 +19,17 @@ public class ACmp extends NodeComponent { @Override public void rollback() throws Exception { + String testKey = "test"; + + DefaultContext context = this.getFirstContextBean(); + if (context.getData(testKey) == null) { + context.setData(testKey, this.getTag()); + } + else { + String s = context.getData(testKey); + s += this.getTag(); + context.setData(testKey, s); + } System.out.println("ACmp rollback!"); } } diff --git a/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/resources/rollback/flow.el.xml b/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/resources/rollback/flow.el.xml index d67b21e92..7072cf2b9 100644 --- a/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/resources/rollback/flow.el.xml +++ b/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/resources/rollback/flow.el.xml @@ -44,4 +44,8 @@ CATCH( THEN(b, c, d) ).DO(a); + + + THEN(a.tag("1"), a.tag("2"), a.tag("3"), d); + \ No newline at end of file diff --git a/liteflow-testcase-el/liteflow-testcase-el-solon/src/test/java/com/yomahub/liteflow/test/rollback/RollbackSpringbootTest.java b/liteflow-testcase-el/liteflow-testcase-el-solon/src/test/java/com/yomahub/liteflow/test/rollback/RollbackSpringbootTest.java index 9d1e93a2e..07d7486f6 100644 --- a/liteflow-testcase-el/liteflow-testcase-el-solon/src/test/java/com/yomahub/liteflow/test/rollback/RollbackSpringbootTest.java +++ b/liteflow-testcase-el/liteflow-testcase-el-solon/src/test/java/com/yomahub/liteflow/test/rollback/RollbackSpringbootTest.java @@ -2,6 +2,7 @@ package com.yomahub.liteflow.test.rollback; import com.yomahub.liteflow.core.FlowExecutor; import com.yomahub.liteflow.flow.LiteflowResponse; +import com.yomahub.liteflow.slot.DefaultContext; import com.yomahub.liteflow.test.BaseTest; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; @@ -84,4 +85,13 @@ public class RollbackSpringbootTest extends BaseTest { Assertions.assertEquals("", response.getRollbackStepStr()); } + @Test + // 对获取数据的测试 + public void testData() throws Exception { + LiteflowResponse response = flowExecutor.execute2Resp("chain9", "arg"); + DefaultContext context = response.getFirstContextBean(); + Assertions.assertFalse(response.isSuccess()); + Assertions.assertEquals("321", context.getData("test")); + } + } diff --git a/liteflow-testcase-el/liteflow-testcase-el-solon/src/test/java/com/yomahub/liteflow/test/rollback/cmp/ACmp.java b/liteflow-testcase-el/liteflow-testcase-el-solon/src/test/java/com/yomahub/liteflow/test/rollback/cmp/ACmp.java index bb44d8522..d953f86fa 100644 --- a/liteflow-testcase-el/liteflow-testcase-el-solon/src/test/java/com/yomahub/liteflow/test/rollback/cmp/ACmp.java +++ b/liteflow-testcase-el/liteflow-testcase-el-solon/src/test/java/com/yomahub/liteflow/test/rollback/cmp/ACmp.java @@ -8,6 +8,7 @@ package com.yomahub.liteflow.test.rollback.cmp; import com.yomahub.liteflow.core.NodeComponent; +import com.yomahub.liteflow.slot.DefaultContext; import org.noear.solon.annotation.Component; @@ -21,6 +22,17 @@ public class ACmp extends NodeComponent { @Override public void rollback() throws Exception { + String testKey = "test"; + + DefaultContext context = this.getFirstContextBean(); + if (context.getData(testKey) == null) { + context.setData(testKey, this.getTag()); + } + else { + String s = context.getData(testKey); + s += this.getTag(); + context.setData(testKey, s); + } System.out.println("ACmp rollback!"); } } diff --git a/liteflow-testcase-el/liteflow-testcase-el-solon/src/test/resources/rollback/flow.el.xml b/liteflow-testcase-el/liteflow-testcase-el-solon/src/test/resources/rollback/flow.el.xml index b0cb7fcd9..2e46ba7af 100644 --- a/liteflow-testcase-el/liteflow-testcase-el-solon/src/test/resources/rollback/flow.el.xml +++ b/liteflow-testcase-el/liteflow-testcase-el-solon/src/test/resources/rollback/flow.el.xml @@ -31,4 +31,8 @@ CATCH( THEN(b, c, d) ).DO(a); + + + THEN(a.tag("1"), a.tag("2"), a.tag("3"), d); + \ No newline at end of file diff --git a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/rollback/RollbackSpringbootTest.java b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/rollback/RollbackSpringbootTest.java index 7984bb192..8e230f7fa 100644 --- a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/rollback/RollbackSpringbootTest.java +++ b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/rollback/RollbackSpringbootTest.java @@ -2,6 +2,7 @@ package com.yomahub.liteflow.test.rollback; import com.yomahub.liteflow.core.FlowExecutor; import com.yomahub.liteflow.flow.LiteflowResponse; +import com.yomahub.liteflow.slot.DefaultContext; import com.yomahub.liteflow.test.BaseTest; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; @@ -87,4 +88,13 @@ public class RollbackSpringbootTest extends BaseTest { Assertions.assertNull(response.getCause()); Assertions.assertEquals("", response.getRollbackStepStr()); } + + @Test + // 对获取数据的测试 + public void testData() throws Exception { + LiteflowResponse response = flowExecutor.execute2Resp("chain9", "arg"); + DefaultContext context = response.getFirstContextBean(); + Assertions.assertFalse(response.isSuccess()); + Assertions.assertEquals("321", context.getData("test")); + } } diff --git a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/rollback/cmp/ACmp.java b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/rollback/cmp/ACmp.java index cb52a08b3..a29efd0db 100644 --- a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/rollback/cmp/ACmp.java +++ b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/rollback/cmp/ACmp.java @@ -8,6 +8,7 @@ package com.yomahub.liteflow.test.rollback.cmp; import com.yomahub.liteflow.core.NodeComponent; +import com.yomahub.liteflow.slot.DefaultContext; import org.springframework.stereotype.Component; @Component("a") @@ -20,6 +21,17 @@ public class ACmp extends NodeComponent { @Override public void rollback() throws Exception { + String testKey = "test"; + + DefaultContext context = this.getFirstContextBean(); + if (context.getData(testKey) == null) { + context.setData(testKey, this.getTag()); + } + else { + String s = context.getData(testKey); + s += this.getTag(); + context.setData(testKey, s); + } System.out.println("ACmp rollback!"); } } diff --git a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/rollback/flow.el.xml b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/rollback/flow.el.xml index b0cb7fcd9..2e46ba7af 100644 --- a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/rollback/flow.el.xml +++ b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/rollback/flow.el.xml @@ -31,4 +31,8 @@ CATCH( THEN(b, c, d) ).DO(a); + + + THEN(a.tag("1"), a.tag("2"), a.tag("3"), d); + \ No newline at end of file diff --git a/liteflow-testcase-el/liteflow-testcase-el-springnative/src/test/java/com/yomahub/liteflow/test/rollback/RollbackSpringTest.java b/liteflow-testcase-el/liteflow-testcase-el-springnative/src/test/java/com/yomahub/liteflow/test/rollback/RollbackSpringTest.java index 28429f0dd..e4b08ccc9 100644 --- a/liteflow-testcase-el/liteflow-testcase-el-springnative/src/test/java/com/yomahub/liteflow/test/rollback/RollbackSpringTest.java +++ b/liteflow-testcase-el/liteflow-testcase-el-springnative/src/test/java/com/yomahub/liteflow/test/rollback/RollbackSpringTest.java @@ -2,6 +2,7 @@ package com.yomahub.liteflow.test.rollback; import com.yomahub.liteflow.core.FlowExecutor; import com.yomahub.liteflow.flow.LiteflowResponse; +import com.yomahub.liteflow.slot.DefaultContext; import com.yomahub.liteflow.test.BaseTest; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; @@ -85,5 +86,14 @@ public class RollbackSpringTest extends BaseTest { Assertions.assertEquals("", response.getRollbackStepStr()); } + @Test + // 对获取数据的测试 + public void testData() throws Exception { + LiteflowResponse response = flowExecutor.execute2Resp("chain9", "arg"); + DefaultContext context = response.getFirstContextBean(); + Assertions.assertFalse(response.isSuccess()); + Assertions.assertEquals("321", context.getData("test")); + } + } diff --git a/liteflow-testcase-el/liteflow-testcase-el-springnative/src/test/java/com/yomahub/liteflow/test/rollback/cmp/ACmp.java b/liteflow-testcase-el/liteflow-testcase-el-springnative/src/test/java/com/yomahub/liteflow/test/rollback/cmp/ACmp.java index cb52a08b3..a29efd0db 100644 --- a/liteflow-testcase-el/liteflow-testcase-el-springnative/src/test/java/com/yomahub/liteflow/test/rollback/cmp/ACmp.java +++ b/liteflow-testcase-el/liteflow-testcase-el-springnative/src/test/java/com/yomahub/liteflow/test/rollback/cmp/ACmp.java @@ -8,6 +8,7 @@ package com.yomahub.liteflow.test.rollback.cmp; import com.yomahub.liteflow.core.NodeComponent; +import com.yomahub.liteflow.slot.DefaultContext; import org.springframework.stereotype.Component; @Component("a") @@ -20,6 +21,17 @@ public class ACmp extends NodeComponent { @Override public void rollback() throws Exception { + String testKey = "test"; + + DefaultContext context = this.getFirstContextBean(); + if (context.getData(testKey) == null) { + context.setData(testKey, this.getTag()); + } + else { + String s = context.getData(testKey); + s += this.getTag(); + context.setData(testKey, s); + } System.out.println("ACmp rollback!"); } } diff --git a/liteflow-testcase-el/liteflow-testcase-el-springnative/src/test/resources/rollback/flow.el.xml b/liteflow-testcase-el/liteflow-testcase-el-springnative/src/test/resources/rollback/flow.el.xml index b0cb7fcd9..2e46ba7af 100644 --- a/liteflow-testcase-el/liteflow-testcase-el-springnative/src/test/resources/rollback/flow.el.xml +++ b/liteflow-testcase-el/liteflow-testcase-el-springnative/src/test/resources/rollback/flow.el.xml @@ -31,4 +31,8 @@ CATCH( THEN(b, c, d) ).DO(a); + + + THEN(a.tag("1"), a.tag("2"), a.tag("3"), d); + \ No newline at end of file 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 45/53] =?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 70954b4ae2ad2cc8ec24658bee6e5e591baf0860 Mon Sep 17 00:00:00 2001 From: rain <672378783@qq.com> Date: Fri, 6 Oct 2023 15:38:39 +0800 Subject: [PATCH 46/53] =?UTF-8?q?=E6=94=AF=E6=8C=81=E7=BB=9D=E5=AF=B9?= =?UTF-8?q?=E8=B7=AF=E5=BE=84=E7=9A=84=E6=A8=A1=E7=B3=8A=E5=8C=B9=E9=85=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../spi/local/LocalPathContentParser.java | 8 +- .../yomahub/liteflow/util/PathMatchUtil.java | 73 +++++++++++++++ .../liteflow/solon/config/PathsUtils.java | 93 ++++++++++--------- .../spi/spring/SpringPathContentParser.java | 7 +- .../absoluteConfigPath/application.properties | 3 +- .../resources/absoluteConfigPath/flow.el.xml | 2 +- .../absoluteConfigPath/application.properties | 3 +- .../resources/absoluteConfigPath/flow.el.xml | 2 +- .../AbsoluteConfigPathTest.java | 1 + .../resources/absoluteConfigPath/flow.el.xml | 8 +- .../absoluteConfigPath/application.properties | 3 +- .../resources/absoluteConfigPath/flow.el.xml | 2 +- .../MonitorFileELSpringbootTest.java | 16 ++++ .../absoluteConfigPath/application.properties | 3 +- .../resources/absoluteConfigPath/flow.el.xml | 2 +- .../monitorFile/application.properties | 1 + .../absoluteConfigPath/application.xml | 4 + .../resources/absoluteConfigPath/flow.el.xml | 2 +- 18 files changed, 175 insertions(+), 58 deletions(-) create mode 100644 liteflow-core/src/main/java/com/yomahub/liteflow/util/PathMatchUtil.java diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/spi/local/LocalPathContentParser.java b/liteflow-core/src/main/java/com/yomahub/liteflow/spi/local/LocalPathContentParser.java index e750468db..64a397f7d 100644 --- a/liteflow-core/src/main/java/com/yomahub/liteflow/spi/local/LocalPathContentParser.java +++ b/liteflow-core/src/main/java/com/yomahub/liteflow/spi/local/LocalPathContentParser.java @@ -9,6 +9,7 @@ import cn.hutool.core.util.ClassLoaderUtil; import cn.hutool.core.util.StrUtil; import com.yomahub.liteflow.exception.ConfigErrorException; import com.yomahub.liteflow.spi.PathContentParser; +import com.yomahub.liteflow.util.PathMatchUtil; import java.util.ArrayList; import java.util.List; @@ -24,10 +25,11 @@ public class LocalPathContentParser implements PathContentParser { if (CollectionUtil.isEmpty(pathList)) { throw new ConfigErrorException("rule source must not be null"); } + List absolutePathList = PathMatchUtil.searchAbsolutePath(pathList); List contentList = new ArrayList<>(); - for (String path : pathList) { + for (String path : absolutePathList) { if (FileUtil.isAbsolutePath(path) && FileUtil.isFile(path)) { path = FILE_URL_PREFIX + path; } @@ -50,10 +52,10 @@ public class LocalPathContentParser implements PathContentParser { if (CollectionUtil.isEmpty(pathList)) { throw new ConfigErrorException("rule source must not be null"); } - + List absolutePathList = PathMatchUtil.searchAbsolutePath(pathList); List result = new ArrayList<>(); - for (String path : pathList) { + for (String path : absolutePathList) { if (FileUtil.isAbsolutePath(path) && FileUtil.isFile(path)) { path = FILE_URL_PREFIX + path; result.add(new FileResource(path).getFile().getAbsolutePath()); diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/util/PathMatchUtil.java b/liteflow-core/src/main/java/com/yomahub/liteflow/util/PathMatchUtil.java new file mode 100644 index 000000000..31e9fbb36 --- /dev/null +++ b/liteflow-core/src/main/java/com/yomahub/liteflow/util/PathMatchUtil.java @@ -0,0 +1,73 @@ +package com.yomahub.liteflow.util; + +import cn.hutool.core.io.FileUtil; +import cn.hutool.core.text.AntPathMatcher; + +import java.io.File; +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + +/** + * 用于获取模糊匹配的路径 + * + * @author Rain + * @since 2.11.1 + */ +public class PathMatchUtil { + + public static List searchAbsolutePath(List pathList) { + + List absolutePathList = new ArrayList<>(); + + for (String path : pathList) { + // 只对绝对路径进行处理 + if(FileUtil.isAbsolutePath(path)) { + if(!path.contains("*")) { + absolutePathList.add(path); + } + else { + String[] pathSegments = path.split("/"); + StringBuilder baseDir = new StringBuilder(); + + // 找到最大基础路径 + for(int i = 0; i < pathSegments.length; i ++) { + if(!pathSegments[i].contains("*")) { + baseDir.append(pathSegments[i]).append(File.separator); + } else { + baseDir.deleteCharAt(baseDir.length() - 1); + searchAbsolutePath(baseDir.toString(), path, absolutePathList); + break; + } + } + } + } else { + absolutePathList.add(path); + } + } + // 路径去重 + List newAbsolutePathList = absolutePathList.stream() + .distinct() + .collect(Collectors.toList()); + return newAbsolutePathList; + } + + private static void searchAbsolutePath(String baseDir, String path, List absolutePathList) { + AntPathMatcher pathMatcher = new AntPathMatcher(); + File dir = new File(baseDir); + File[] files = dir.listFiles(); + + if (files != null) { + for (File file : files) { + if (file.isDirectory()) { + searchAbsolutePath(file.getAbsolutePath(), path, absolutePathList); + } else { + String absolutePath = file.getAbsolutePath().replace("\\", "/"); + if (pathMatcher.match(path, absolutePath)) { + absolutePathList.add(absolutePath); + } + } + } + } + } +} diff --git a/liteflow-solon-plugin/src/main/java/com/yomahub/liteflow/solon/config/PathsUtils.java b/liteflow-solon-plugin/src/main/java/com/yomahub/liteflow/solon/config/PathsUtils.java index 08e9d9fb4..879328004 100644 --- a/liteflow-solon-plugin/src/main/java/com/yomahub/liteflow/solon/config/PathsUtils.java +++ b/liteflow-solon-plugin/src/main/java/com/yomahub/liteflow/solon/config/PathsUtils.java @@ -1,8 +1,11 @@ package com.yomahub.liteflow.solon.config; +import cn.hutool.core.io.FileUtil; +import com.yomahub.liteflow.util.PathMatchUtil; import org.noear.solon.core.util.ScanUtil; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collection; import java.util.List; import java.util.regex.Pattern; @@ -17,51 +20,55 @@ public class PathsUtils { public static Collection resolvePaths(String pathExpr) { List paths = new ArrayList<>(); + if(!FileUtil.isAbsolutePath(pathExpr)) { + if (pathExpr.contains("/*") == false) { // 说明没有*符 + paths.add(pathExpr); + return paths; + } - if (pathExpr.contains("/*") == false) { // 说明没有*符 - paths.add(pathExpr); - return paths; + // 确定目录 + int dirIdx = pathExpr.indexOf("/*"); + String dir = pathExpr.substring(0, dirIdx); + + // 确定后缀 + int sufIdx = pathExpr.lastIndexOf("."); + String suf = null; + if (sufIdx > 0) { + suf = pathExpr.substring(sufIdx); + if (suf.contains("*")) { + sufIdx = -1; + suf = null; + } + } + + int sufIdx2 = sufIdx; + String suf2 = suf; + + // 匹配表达式 + String expr = pathExpr.replaceAll("/\\*\\.", "/[^\\.]*\\."); + expr = expr.replaceAll("/\\*\\*/", "(/[^/]*)*/"); + + Pattern pattern = Pattern.compile(expr); + + List finalPaths = paths; + ScanUtil.scan(dir, n -> { + // 进行后缀过滤,相对比较快 + if (sufIdx2 > 0) { + return n.endsWith(suf2); + } + else { + return true; + } + }).forEach(uri -> { + // 再进行表达式过滤 + if (pattern.matcher(uri).find()) { + finalPaths.add(uri); + } + }); + } else { + String[] pathExprs = pathExpr.split(","); + paths = PathMatchUtil.searchAbsolutePath(Arrays.asList(pathExprs)); } - - // 确定目录 - int dirIdx = pathExpr.indexOf("/*"); - String dir = pathExpr.substring(0, dirIdx); - - // 确定后缀 - int sufIdx = pathExpr.lastIndexOf("."); - String suf = null; - if (sufIdx > 0) { - suf = pathExpr.substring(sufIdx); - if (suf.contains("*")) { - sufIdx = -1; - suf = null; - } - } - - int sufIdx2 = sufIdx; - String suf2 = suf; - - // 匹配表达式 - String expr = pathExpr.replaceAll("/\\*\\.", "/[^\\.]*\\."); - expr = expr.replaceAll("/\\*\\*/", "(/[^/]*)*/"); - - Pattern pattern = Pattern.compile(expr); - - ScanUtil.scan(dir, n -> { - // 进行后缀过滤,相对比较快 - if (sufIdx2 > 0) { - return n.endsWith(suf2); - } - else { - return true; - } - }).forEach(uri -> { - // 再进行表达式过滤 - if (pattern.matcher(uri).find()) { - paths.add(uri); - } - }); - return paths; } diff --git a/liteflow-spring/src/main/java/com/yomahub/liteflow/spi/spring/SpringPathContentParser.java b/liteflow-spring/src/main/java/com/yomahub/liteflow/spi/spring/SpringPathContentParser.java index a3f6fc0b4..137208541 100644 --- a/liteflow-spring/src/main/java/com/yomahub/liteflow/spi/spring/SpringPathContentParser.java +++ b/liteflow-spring/src/main/java/com/yomahub/liteflow/spi/spring/SpringPathContentParser.java @@ -10,6 +10,7 @@ import cn.hutool.core.util.CharsetUtil; import cn.hutool.core.util.StrUtil; import com.yomahub.liteflow.exception.ConfigErrorException; import com.yomahub.liteflow.spi.PathContentParser; +import com.yomahub.liteflow.util.PathMatchUtil; import org.springframework.core.io.Resource; import org.springframework.core.io.support.PathMatchingResourcePatternResolver; import org.springframework.core.io.support.ResourcePatternResolver; @@ -26,7 +27,8 @@ public class SpringPathContentParser implements PathContentParser { @Override public List parseContent(List pathList) throws Exception { - List allResource = getResources(pathList); + List absolutePathList = PathMatchUtil.searchAbsolutePath(pathList); + List allResource = getResources(absolutePathList); // 转换成内容List List contentList = new ArrayList<>(); @@ -42,7 +44,8 @@ public class SpringPathContentParser implements PathContentParser { @Override public List getFileAbsolutePath(List pathList) throws Exception { - List allResource = getResources(pathList); + List absolutePathList = PathMatchUtil.searchAbsolutePath(pathList); + List allResource = getResources(absolutePathList); return StreamUtil.of(allResource) // 过滤非 file 类型 Resource diff --git a/liteflow-testcase-el/liteflow-testcase-el-declare-multi-springboot/src/test/resources/absoluteConfigPath/application.properties b/liteflow-testcase-el/liteflow-testcase-el-declare-multi-springboot/src/test/resources/absoluteConfigPath/application.properties index 348a63af9..cfd4db495 100644 --- a/liteflow-testcase-el/liteflow-testcase-el-declare-multi-springboot/src/test/resources/absoluteConfigPath/application.properties +++ b/liteflow-testcase-el/liteflow-testcase-el-declare-multi-springboot/src/test/resources/absoluteConfigPath/application.properties @@ -1 +1,2 @@ -liteflow.rule-source=/usr/local/flow.el.xml \ No newline at end of file +liteflow.rule-source=/usr/local/flow.el.xml +#liteflow.rule-source=/usr/**/*.xml \ No newline at end of file diff --git a/liteflow-testcase-el/liteflow-testcase-el-declare-multi-springboot/src/test/resources/absoluteConfigPath/flow.el.xml b/liteflow-testcase-el/liteflow-testcase-el-declare-multi-springboot/src/test/resources/absoluteConfigPath/flow.el.xml index 0d670c770..2fda05e60 100644 --- a/liteflow-testcase-el/liteflow-testcase-el-declare-multi-springboot/src/test/resources/absoluteConfigPath/flow.el.xml +++ b/liteflow-testcase-el/liteflow-testcase-el-declare-multi-springboot/src/test/resources/absoluteConfigPath/flow.el.xml @@ -1,5 +1,5 @@ - + WHEN(a,b,c); diff --git a/liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/resources/absoluteConfigPath/application.properties b/liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/resources/absoluteConfigPath/application.properties index 348a63af9..cfd4db495 100644 --- a/liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/resources/absoluteConfigPath/application.properties +++ b/liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/resources/absoluteConfigPath/application.properties @@ -1 +1,2 @@ -liteflow.rule-source=/usr/local/flow.el.xml \ No newline at end of file +liteflow.rule-source=/usr/local/flow.el.xml +#liteflow.rule-source=/usr/**/*.xml \ No newline at end of file diff --git a/liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/resources/absoluteConfigPath/flow.el.xml b/liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/resources/absoluteConfigPath/flow.el.xml index 0d670c770..2fda05e60 100644 --- a/liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/resources/absoluteConfigPath/flow.el.xml +++ b/liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/resources/absoluteConfigPath/flow.el.xml @@ -1,5 +1,5 @@ - + WHEN(a,b,c); diff --git a/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/java/com/yomahub/liteflow/test/absoluteConfigPath/AbsoluteConfigPathTest.java b/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/java/com/yomahub/liteflow/test/absoluteConfigPath/AbsoluteConfigPathTest.java index 120c3984a..3d0ffef59 100644 --- a/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/java/com/yomahub/liteflow/test/absoluteConfigPath/AbsoluteConfigPathTest.java +++ b/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/java/com/yomahub/liteflow/test/absoluteConfigPath/AbsoluteConfigPathTest.java @@ -23,6 +23,7 @@ public class AbsoluteConfigPathTest extends BaseTest { public static void init() { LiteflowConfig config = new LiteflowConfig(); config.setRuleSource("/usr/local/flow2.xml"); +// config.setRuleSource("/usr/**/*.xml"); flowExecutor = FlowExecutorHolder.loadInstance(config); } diff --git a/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/resources/absoluteConfigPath/flow.el.xml b/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/resources/absoluteConfigPath/flow.el.xml index 0d670c770..9920ec543 100644 --- a/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/resources/absoluteConfigPath/flow.el.xml +++ b/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/resources/absoluteConfigPath/flow.el.xml @@ -1,6 +1,12 @@ - + + + + + + + WHEN(a,b,c); diff --git a/liteflow-testcase-el/liteflow-testcase-el-solon/src/test/resources/absoluteConfigPath/application.properties b/liteflow-testcase-el/liteflow-testcase-el-solon/src/test/resources/absoluteConfigPath/application.properties index 348a63af9..cfd4db495 100644 --- a/liteflow-testcase-el/liteflow-testcase-el-solon/src/test/resources/absoluteConfigPath/application.properties +++ b/liteflow-testcase-el/liteflow-testcase-el-solon/src/test/resources/absoluteConfigPath/application.properties @@ -1 +1,2 @@ -liteflow.rule-source=/usr/local/flow.el.xml \ No newline at end of file +liteflow.rule-source=/usr/local/flow.el.xml +#liteflow.rule-source=/usr/**/*.xml \ No newline at end of file diff --git a/liteflow-testcase-el/liteflow-testcase-el-solon/src/test/resources/absoluteConfigPath/flow.el.xml b/liteflow-testcase-el/liteflow-testcase-el-solon/src/test/resources/absoluteConfigPath/flow.el.xml index 0d670c770..2fda05e60 100644 --- a/liteflow-testcase-el/liteflow-testcase-el-solon/src/test/resources/absoluteConfigPath/flow.el.xml +++ b/liteflow-testcase-el/liteflow-testcase-el-solon/src/test/resources/absoluteConfigPath/flow.el.xml @@ -1,5 +1,5 @@ - + WHEN(a,b,c); diff --git a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/monitorFile/MonitorFileELSpringbootTest.java b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/monitorFile/MonitorFileELSpringbootTest.java index ecc1f9e91..3b7194f9e 100644 --- a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/monitorFile/MonitorFileELSpringbootTest.java +++ b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/monitorFile/MonitorFileELSpringbootTest.java @@ -38,6 +38,22 @@ public class MonitorFileELSpringbootTest extends BaseTest { Assertions.assertEquals("a==>c==>b", response.getExecuteStepStr()); } + /** + * 对绝对路径模糊匹配功能的测试 + */ + @Test + public void testMonitorAbsolutePath() throws Exception { + String absolutePath = "/your/path/dir"; + FileUtil.writeString("THEN(a, b, c);", new File(absolutePath), CharsetUtil.CHARSET_UTF_8); + String content = FileUtil.readUtf8String(absolutePath); + String newContent = content.replace("THEN(a, b, c);", "THEN(a, c, b);"); + Thread.sleep(1000); + FileUtil.writeString(newContent, new File(absolutePath), CharsetUtil.CHARSET_UTF_8); + Thread.sleep(3000); + LiteflowResponse response = flowExecutor.execute2Resp("chain1", "arg"); + Assertions.assertEquals("a==>c==>b", response.getExecuteStepStr()); + } + /** * 测试文件变更,但是 EL 规则错误情况 * 输出 ERROR 日志异常信息,但是不会停止监听线程,当下一次变更正确后替换为新规则 diff --git a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/absoluteConfigPath/application.properties b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/absoluteConfigPath/application.properties index 348a63af9..cfd4db495 100644 --- a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/absoluteConfigPath/application.properties +++ b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/absoluteConfigPath/application.properties @@ -1 +1,2 @@ -liteflow.rule-source=/usr/local/flow.el.xml \ No newline at end of file +liteflow.rule-source=/usr/local/flow.el.xml +#liteflow.rule-source=/usr/**/*.xml \ No newline at end of file diff --git a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/absoluteConfigPath/flow.el.xml b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/absoluteConfigPath/flow.el.xml index 0d670c770..2fda05e60 100644 --- a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/absoluteConfigPath/flow.el.xml +++ b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/absoluteConfigPath/flow.el.xml @@ -1,5 +1,5 @@ - + WHEN(a,b,c); diff --git a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/monitorFile/application.properties b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/monitorFile/application.properties index 361f7e90e..a292d3445 100644 --- a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/monitorFile/application.properties +++ b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/monitorFile/application.properties @@ -1,2 +1,3 @@ liteflow.rule-source=monitorFile/flow.el.xml +#liteflow.rule-source=/usr/**/*.xml liteflow.enable-monitor-file=true \ No newline at end of file diff --git a/liteflow-testcase-el/liteflow-testcase-el-springnative/src/test/resources/absoluteConfigPath/application.xml b/liteflow-testcase-el/liteflow-testcase-el-springnative/src/test/resources/absoluteConfigPath/application.xml index 3a5cc59d9..c3e5fe362 100644 --- a/liteflow-testcase-el/liteflow-testcase-el-springnative/src/test/resources/absoluteConfigPath/application.xml +++ b/liteflow-testcase-el/liteflow-testcase-el-springnative/src/test/resources/absoluteConfigPath/application.xml @@ -17,6 +17,10 @@ + + + + diff --git a/liteflow-testcase-el/liteflow-testcase-el-springnative/src/test/resources/absoluteConfigPath/flow.el.xml b/liteflow-testcase-el/liteflow-testcase-el-springnative/src/test/resources/absoluteConfigPath/flow.el.xml index fd7d34c72..507e19d62 100644 --- a/liteflow-testcase-el/liteflow-testcase-el-springnative/src/test/resources/absoluteConfigPath/flow.el.xml +++ b/liteflow-testcase-el/liteflow-testcase-el-springnative/src/test/resources/absoluteConfigPath/flow.el.xml @@ -1,5 +1,5 @@ - + WHEN(a,b,c); 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 47/53] =?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 From 4742ffea2827274277f99e9ef7b7cdd71d02df93 Mon Sep 17 00:00:00 2001 From: rain <672378783@qq.com> Date: Mon, 9 Oct 2023 16:11:29 +0800 Subject: [PATCH 48/53] =?UTF-8?q?=E6=94=AF=E6=8C=81=E7=BB=9D=E5=AF=B9?= =?UTF-8?q?=E8=B7=AF=E5=BE=84=E7=9A=84=E6=A8=A1=E7=B3=8A=E5=8C=B9=E9=85=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...teConfigPathELDeclMultiSpringbootTest.java | 40 ++++++++++++-- .../absoluteConfigPath/application.properties | 3 +- .../resources/absoluteConfigPath/flow.el.xml | 2 +- ...bsoluteConfigPathELDeclSpringbootTest.java | 40 ++++++++++++-- .../absoluteConfigPath/application.properties | 3 +- .../resources/absoluteConfigPath/flow.el.xml | 2 +- .../AbsoluteConfigPathTest.java | 55 ++++++++++++++++--- .../resources/absoluteConfigPath/flow.el.xml | 2 +- .../AbsoluteConfigPathELSpringbootTest.java | 39 +++++++++++-- .../absoluteConfigPath/application.properties | 3 +- .../resources/absoluteConfigPath/flow.el.xml | 2 +- .../AbsoluteConfigPathELSpringbootTest.java | 39 +++++++++++-- .../absoluteConfigPath/application.properties | 3 +- .../resources/absoluteConfigPath/flow.el.xml | 2 +- .../AbsoluteConfigPathELSpringTest.java | 39 ++++++++++++- .../absoluteConfigPath/application.xml | 6 +- .../resources/absoluteConfigPath/flow.el.xml | 2 +- 17 files changed, 233 insertions(+), 49 deletions(-) diff --git a/liteflow-testcase-el/liteflow-testcase-el-declare-multi-springboot/src/test/java/com/yomahub/liteflow/test/absoluteConfigPath/AbsoluteConfigPathELDeclMultiSpringbootTest.java b/liteflow-testcase-el/liteflow-testcase-el-declare-multi-springboot/src/test/java/com/yomahub/liteflow/test/absoluteConfigPath/AbsoluteConfigPathELDeclMultiSpringbootTest.java index 293b56d83..e04dbc456 100644 --- a/liteflow-testcase-el/liteflow-testcase-el-declare-multi-springboot/src/test/java/com/yomahub/liteflow/test/absoluteConfigPath/AbsoluteConfigPathELDeclMultiSpringbootTest.java +++ b/liteflow-testcase-el/liteflow-testcase-el-declare-multi-springboot/src/test/java/com/yomahub/liteflow/test/absoluteConfigPath/AbsoluteConfigPathELDeclMultiSpringbootTest.java @@ -1,9 +1,15 @@ package com.yomahub.liteflow.test.absoluteConfigPath; +import cn.hutool.core.io.FileUtil; +import cn.hutool.core.util.CharsetUtil; import com.yomahub.liteflow.core.FlowExecutor; import com.yomahub.liteflow.flow.LiteflowResponse; +import com.yomahub.liteflow.property.LiteflowConfig; +import com.yomahub.liteflow.property.LiteflowConfigGetter; import com.yomahub.liteflow.test.BaseTest; +import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.test.context.junit.jupiter.SpringExtension; @@ -24,21 +30,45 @@ import javax.annotation.Resource; * @since 2.6.4 */ @ExtendWith(SpringExtension.class) -@TestPropertySource(value = "classpath:/absoluteConfigPath/application.properties") @SpringBootTest(classes = AbsoluteConfigPathELDeclMultiSpringbootTest.class) @EnableAutoConfiguration @ComponentScan({ "com.yomahub.liteflow.test.absoluteConfigPath.cmp" }) public class AbsoluteConfigPathELDeclMultiSpringbootTest extends BaseTest { - private final Logger log = LoggerFactory.getLogger(this.getClass()); - @Resource private FlowExecutor flowExecutor; @Test public void testAbsoluteConfig() throws Exception { - LiteflowResponse response = flowExecutor.execute2Resp("chain1", "arg"); - Assertions.assertTrue(response.isSuccess()); + Assertions.assertTrue(() -> { + LiteflowConfig config = LiteflowConfigGetter.get(); + config.setRuleSource("C:/LiteFlow/Test/a/b/c/flow.el.xml"); + flowExecutor.reloadRule(); + return flowExecutor.execute2Resp("chain1", "arg").isSuccess(); + }); + } + + @Test + public void testAbsolutePathMatch() throws Exception { + Assertions.assertTrue(() -> { + LiteflowConfig config = LiteflowConfigGetter.get(); + config.setRuleSource("C:/LiteFlow/Tes*/**/c/*.el.xml"); + flowExecutor.reloadRule(); + return flowExecutor.execute2Resp("chain1", "arg").isSuccess(); + }); + } + + @BeforeAll + public static void createFiles() { + String filePath = "C:/LiteFlow/Test/a/b/c"; + String content = "WHEN(a, b, c);"; + FileUtil.mkdir(filePath); + FileUtil.writeString(content, filePath + "/flow.el.xml", CharsetUtil.CHARSET_UTF_8); + } + + @AfterAll + public static void removeFiles() { + FileUtil.del("C:/LiteFlow"); } } diff --git a/liteflow-testcase-el/liteflow-testcase-el-declare-multi-springboot/src/test/resources/absoluteConfigPath/application.properties b/liteflow-testcase-el/liteflow-testcase-el-declare-multi-springboot/src/test/resources/absoluteConfigPath/application.properties index cfd4db495..93a30df79 100644 --- a/liteflow-testcase-el/liteflow-testcase-el-declare-multi-springboot/src/test/resources/absoluteConfigPath/application.properties +++ b/liteflow-testcase-el/liteflow-testcase-el-declare-multi-springboot/src/test/resources/absoluteConfigPath/application.properties @@ -1,2 +1 @@ -liteflow.rule-source=/usr/local/flow.el.xml -#liteflow.rule-source=/usr/**/*.xml \ No newline at end of file +liteflow.rule-source=C:/LiteFlow/Test/a/b/c/flow.el.xml \ No newline at end of file diff --git a/liteflow-testcase-el/liteflow-testcase-el-declare-multi-springboot/src/test/resources/absoluteConfigPath/flow.el.xml b/liteflow-testcase-el/liteflow-testcase-el-declare-multi-springboot/src/test/resources/absoluteConfigPath/flow.el.xml index 2fda05e60..4871fa66c 100644 --- a/liteflow-testcase-el/liteflow-testcase-el-declare-multi-springboot/src/test/resources/absoluteConfigPath/flow.el.xml +++ b/liteflow-testcase-el/liteflow-testcase-el-declare-multi-springboot/src/test/resources/absoluteConfigPath/flow.el.xml @@ -1,5 +1,5 @@ - + WHEN(a,b,c); diff --git a/liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/java/com/yomahub/liteflow/test/absoluteConfigPath/AbsoluteConfigPathELDeclSpringbootTest.java b/liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/java/com/yomahub/liteflow/test/absoluteConfigPath/AbsoluteConfigPathELDeclSpringbootTest.java index 55c900075..c59dbe1a5 100644 --- a/liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/java/com/yomahub/liteflow/test/absoluteConfigPath/AbsoluteConfigPathELDeclSpringbootTest.java +++ b/liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/java/com/yomahub/liteflow/test/absoluteConfigPath/AbsoluteConfigPathELDeclSpringbootTest.java @@ -1,9 +1,15 @@ package com.yomahub.liteflow.test.absoluteConfigPath; +import cn.hutool.core.io.FileUtil; +import cn.hutool.core.util.CharsetUtil; import com.yomahub.liteflow.core.FlowExecutor; import com.yomahub.liteflow.flow.LiteflowResponse; +import com.yomahub.liteflow.property.LiteflowConfig; +import com.yomahub.liteflow.property.LiteflowConfigGetter; import com.yomahub.liteflow.test.BaseTest; +import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.test.context.junit.jupiter.SpringExtension; @@ -24,21 +30,45 @@ import javax.annotation.Resource; * @since 2.6.4 */ @ExtendWith(SpringExtension.class) -@TestPropertySource(value = "classpath:/absoluteConfigPath/application.properties") @SpringBootTest(classes = AbsoluteConfigPathELDeclSpringbootTest.class) @EnableAutoConfiguration @ComponentScan({ "com.yomahub.liteflow.test.absoluteConfigPath.cmp" }) public class AbsoluteConfigPathELDeclSpringbootTest extends BaseTest { - private final Logger log = LoggerFactory.getLogger(this.getClass()); - @Resource private FlowExecutor flowExecutor; @Test public void testAbsoluteConfig() throws Exception { - LiteflowResponse response = flowExecutor.execute2Resp("chain1", "arg"); - Assertions.assertTrue(response.isSuccess()); + Assertions.assertTrue(() -> { + LiteflowConfig config = LiteflowConfigGetter.get(); + config.setRuleSource("C:/LiteFlow/Test/a/b/c/flow.el.xml"); + flowExecutor.reloadRule(); + return flowExecutor.execute2Resp("chain1", "arg").isSuccess(); + }); + } + + @Test + public void testAbsolutePathMatch() throws Exception { + Assertions.assertTrue(() -> { + LiteflowConfig config = LiteflowConfigGetter.get(); + config.setRuleSource("C:/LiteFlow/Tes*/**/c/*.el.xml"); + flowExecutor.reloadRule(); + return flowExecutor.execute2Resp("chain1", "arg").isSuccess(); + }); + } + + @BeforeAll + public static void createFiles() { + String filePath = "C:/LiteFlow/Test/a/b/c"; + String content = "WHEN(a, b, c);"; + FileUtil.mkdir(filePath); + FileUtil.writeString(content, filePath + "/flow.el.xml", CharsetUtil.CHARSET_UTF_8); + } + + @AfterAll + public static void removeFiles() { + FileUtil.del("C:/LiteFlow"); } } diff --git a/liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/resources/absoluteConfigPath/application.properties b/liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/resources/absoluteConfigPath/application.properties index cfd4db495..93a30df79 100644 --- a/liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/resources/absoluteConfigPath/application.properties +++ b/liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/resources/absoluteConfigPath/application.properties @@ -1,2 +1 @@ -liteflow.rule-source=/usr/local/flow.el.xml -#liteflow.rule-source=/usr/**/*.xml \ No newline at end of file +liteflow.rule-source=C:/LiteFlow/Test/a/b/c/flow.el.xml \ No newline at end of file diff --git a/liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/resources/absoluteConfigPath/flow.el.xml b/liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/resources/absoluteConfigPath/flow.el.xml index 2fda05e60..4871fa66c 100644 --- a/liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/resources/absoluteConfigPath/flow.el.xml +++ b/liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/resources/absoluteConfigPath/flow.el.xml @@ -1,5 +1,5 @@ - + WHEN(a,b,c); diff --git a/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/java/com/yomahub/liteflow/test/absoluteConfigPath/AbsoluteConfigPathTest.java b/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/java/com/yomahub/liteflow/test/absoluteConfigPath/AbsoluteConfigPathTest.java index 3d0ffef59..f9c1c3139 100644 --- a/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/java/com/yomahub/liteflow/test/absoluteConfigPath/AbsoluteConfigPathTest.java +++ b/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/java/com/yomahub/liteflow/test/absoluteConfigPath/AbsoluteConfigPathTest.java @@ -1,10 +1,14 @@ package com.yomahub.liteflow.test.absoluteConfigPath; +import cn.hutool.core.io.FileUtil; +import cn.hutool.core.util.CharsetUtil; 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.property.LiteflowConfigGetter; import com.yomahub.liteflow.test.BaseTest; +import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; @@ -19,18 +23,51 @@ public class AbsoluteConfigPathTest extends BaseTest { private static FlowExecutor flowExecutor; - @BeforeAll - public static void init() { - LiteflowConfig config = new LiteflowConfig(); - config.setRuleSource("/usr/local/flow2.xml"); -// config.setRuleSource("/usr/**/*.xml"); - flowExecutor = FlowExecutorHolder.loadInstance(config); - } @Test public void testAbsoluteConfig() throws Exception { - LiteflowResponse response = flowExecutor.execute2Resp("chain1", "arg"); - Assertions.assertTrue(response.isSuccess()); + Assertions.assertTrue(() -> { + LiteflowConfig config = LiteflowConfigGetter.get(); + config.setRuleSource("C:/LiteFlow/Test/a/b/c/flow.el.xml"); + flowExecutor.reloadRule(); + return flowExecutor.execute2Resp("chain1", "arg").isSuccess(); + }); } + @Test + public void testAbsolutePathMatch() throws Exception { + Assertions.assertTrue(() -> { + LiteflowConfig config = LiteflowConfigGetter.get(); + config.setRuleSource("C:/LiteFlow/Tes*/**/c/*.el.xml"); + flowExecutor.reloadRule(); + return flowExecutor.execute2Resp("chain1", "arg").isSuccess(); + }); + } + + @BeforeAll + public static void createFiles() { + String filePath = "C:/LiteFlow/Test/a/b/c"; + String content = "\n" + + "\n" + + "\n" + + " \n" + + " \n" + + " \n" + + "\n" + + "\n" + + "\n" + + " WHEN(a,b,c);\n" + + "\n" + + ""; + FileUtil.mkdir(filePath); + FileUtil.writeString(content, filePath + "/flow.el.xml", CharsetUtil.CHARSET_UTF_8); + LiteflowConfig config = new LiteflowConfig(); + config.setRuleSource("absoluteConfigPath/flow.el.xml"); + flowExecutor = FlowExecutorHolder.loadInstance(config); + } + + @AfterAll + public static void removeFiles() { + FileUtil.del("C:/LiteFlow"); + } } diff --git a/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/resources/absoluteConfigPath/flow.el.xml b/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/resources/absoluteConfigPath/flow.el.xml index 9920ec543..59b01c85c 100644 --- a/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/resources/absoluteConfigPath/flow.el.xml +++ b/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/resources/absoluteConfigPath/flow.el.xml @@ -1,5 +1,5 @@ - + diff --git a/liteflow-testcase-el/liteflow-testcase-el-solon/src/test/java/com/yomahub/liteflow/test/absoluteConfigPath/AbsoluteConfigPathELSpringbootTest.java b/liteflow-testcase-el/liteflow-testcase-el-solon/src/test/java/com/yomahub/liteflow/test/absoluteConfigPath/AbsoluteConfigPathELSpringbootTest.java index 8e8897b85..0ae3c55b0 100644 --- a/liteflow-testcase-el/liteflow-testcase-el-solon/src/test/java/com/yomahub/liteflow/test/absoluteConfigPath/AbsoluteConfigPathELSpringbootTest.java +++ b/liteflow-testcase-el/liteflow-testcase-el-solon/src/test/java/com/yomahub/liteflow/test/absoluteConfigPath/AbsoluteConfigPathELSpringbootTest.java @@ -1,9 +1,15 @@ package com.yomahub.liteflow.test.absoluteConfigPath; +import cn.hutool.core.io.FileUtil; +import cn.hutool.core.util.CharsetUtil; import com.yomahub.liteflow.core.FlowExecutor; import com.yomahub.liteflow.flow.LiteflowResponse; +import com.yomahub.liteflow.property.LiteflowConfig; +import com.yomahub.liteflow.property.LiteflowConfigGetter; import com.yomahub.liteflow.test.BaseTest; +import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.noear.solon.annotation.Inject; @@ -19,18 +25,43 @@ import org.slf4j.LoggerFactory; * @since 2.6.4 */ @ExtendWith(SolonJUnit5Extension.class) -@TestPropertySource("classpath:/absoluteConfigPath/application.properties") public class AbsoluteConfigPathELSpringbootTest extends BaseTest { - private final Logger log = LoggerFactory.getLogger(this.getClass()); @Inject private FlowExecutor flowExecutor; @Test public void testAbsoluteConfig() throws Exception { - LiteflowResponse response = flowExecutor.execute2Resp("chain1", "arg"); - Assertions.assertTrue(response.isSuccess()); + Assertions.assertTrue(() -> { + LiteflowConfig config = LiteflowConfigGetter.get(); + config.setRuleSource("C:/LiteFlow/Test/a/b/c/flow.el.xml"); + flowExecutor.reloadRule(); + return flowExecutor.execute2Resp("chain1", "arg").isSuccess(); + }); + } + + @Test + public void testAbsolutePathMatch() throws Exception { + Assertions.assertTrue(() -> { + LiteflowConfig config = LiteflowConfigGetter.get(); + config.setRuleSource("C:/LiteFlow/Tes*/**/c/*.el.xml"); + flowExecutor.reloadRule(); + return flowExecutor.execute2Resp("chain1", "arg").isSuccess(); + }); + } + + @BeforeAll + public static void createFiles() { + String filePath = "C:/LiteFlow/Test/a/b/c"; + String content = "WHEN(a, b, c);"; + FileUtil.mkdir(filePath); + FileUtil.writeString(content, filePath + "/flow.el.xml", CharsetUtil.CHARSET_UTF_8); + } + + @AfterAll + public static void removeFiles() { + FileUtil.del("C:/LiteFlow"); } } diff --git a/liteflow-testcase-el/liteflow-testcase-el-solon/src/test/resources/absoluteConfigPath/application.properties b/liteflow-testcase-el/liteflow-testcase-el-solon/src/test/resources/absoluteConfigPath/application.properties index cfd4db495..93a30df79 100644 --- a/liteflow-testcase-el/liteflow-testcase-el-solon/src/test/resources/absoluteConfigPath/application.properties +++ b/liteflow-testcase-el/liteflow-testcase-el-solon/src/test/resources/absoluteConfigPath/application.properties @@ -1,2 +1 @@ -liteflow.rule-source=/usr/local/flow.el.xml -#liteflow.rule-source=/usr/**/*.xml \ No newline at end of file +liteflow.rule-source=C:/LiteFlow/Test/a/b/c/flow.el.xml \ No newline at end of file diff --git a/liteflow-testcase-el/liteflow-testcase-el-solon/src/test/resources/absoluteConfigPath/flow.el.xml b/liteflow-testcase-el/liteflow-testcase-el-solon/src/test/resources/absoluteConfigPath/flow.el.xml index 2fda05e60..4871fa66c 100644 --- a/liteflow-testcase-el/liteflow-testcase-el-solon/src/test/resources/absoluteConfigPath/flow.el.xml +++ b/liteflow-testcase-el/liteflow-testcase-el-solon/src/test/resources/absoluteConfigPath/flow.el.xml @@ -1,5 +1,5 @@ - + WHEN(a,b,c); diff --git a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/absoluteConfigPath/AbsoluteConfigPathELSpringbootTest.java b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/absoluteConfigPath/AbsoluteConfigPathELSpringbootTest.java index ca844f9cc..5bf77bb7d 100644 --- a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/absoluteConfigPath/AbsoluteConfigPathELSpringbootTest.java +++ b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/absoluteConfigPath/AbsoluteConfigPathELSpringbootTest.java @@ -1,9 +1,15 @@ package com.yomahub.liteflow.test.absoluteConfigPath; +import cn.hutool.core.io.FileUtil; +import cn.hutool.core.util.CharsetUtil; import com.yomahub.liteflow.core.FlowExecutor; import com.yomahub.liteflow.flow.LiteflowResponse; +import com.yomahub.liteflow.property.LiteflowConfig; +import com.yomahub.liteflow.property.LiteflowConfigGetter; import com.yomahub.liteflow.test.BaseTest; +import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -20,21 +26,46 @@ import javax.annotation.Resource; * @author Bryan.Zhang * @since 2.6.4 */ -@TestPropertySource(value = "classpath:/absoluteConfigPath/application.properties") @SpringBootTest(classes = AbsoluteConfigPathELSpringbootTest.class) @EnableAutoConfiguration @ComponentScan({ "com.yomahub.liteflow.test.absoluteConfigPath.cmp" }) public class AbsoluteConfigPathELSpringbootTest extends BaseTest { - private final Logger log = LoggerFactory.getLogger(this.getClass()); @Resource private FlowExecutor flowExecutor; @Test public void testAbsoluteConfig() throws Exception { - LiteflowResponse response = flowExecutor.execute2Resp("chain1", "arg"); - Assertions.assertTrue(response.isSuccess()); + Assertions.assertTrue(() -> { + LiteflowConfig config = LiteflowConfigGetter.get(); + config.setRuleSource("C:/LiteFlow/Test/a/b/c/flow.el.xml"); + flowExecutor.reloadRule(); + return flowExecutor.execute2Resp("chain1", "arg").isSuccess(); + }); + } + + @Test + public void testAbsolutePathMatch() throws Exception { + Assertions.assertTrue(() -> { + LiteflowConfig config = LiteflowConfigGetter.get(); + config.setRuleSource("C:/LiteFlow/Tes*/**/c/*.el.xml"); + flowExecutor.reloadRule(); + return flowExecutor.execute2Resp("chain1", "arg").isSuccess(); + }); + } + + @BeforeAll + public static void createFiles() { + String filePath = "C:/LiteFlow/Test/a/b/c"; + String content = "WHEN(a, b, c);"; + FileUtil.mkdir(filePath); + FileUtil.writeString(content, filePath + "/flow.el.xml", CharsetUtil.CHARSET_UTF_8); + } + + @AfterAll + public static void removeFiles() { + FileUtil.del("C:/LiteFlow"); } } diff --git a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/absoluteConfigPath/application.properties b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/absoluteConfigPath/application.properties index cfd4db495..93a30df79 100644 --- a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/absoluteConfigPath/application.properties +++ b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/absoluteConfigPath/application.properties @@ -1,2 +1 @@ -liteflow.rule-source=/usr/local/flow.el.xml -#liteflow.rule-source=/usr/**/*.xml \ No newline at end of file +liteflow.rule-source=C:/LiteFlow/Test/a/b/c/flow.el.xml \ No newline at end of file diff --git a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/absoluteConfigPath/flow.el.xml b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/absoluteConfigPath/flow.el.xml index 2fda05e60..4871fa66c 100644 --- a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/absoluteConfigPath/flow.el.xml +++ b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/absoluteConfigPath/flow.el.xml @@ -1,5 +1,5 @@ - + WHEN(a,b,c); diff --git a/liteflow-testcase-el/liteflow-testcase-el-springnative/src/test/java/com/yomahub/liteflow/test/absoluteConfigPath/AbsoluteConfigPathELSpringTest.java b/liteflow-testcase-el/liteflow-testcase-el-springnative/src/test/java/com/yomahub/liteflow/test/absoluteConfigPath/AbsoluteConfigPathELSpringTest.java index 5a662976c..447d6e965 100644 --- a/liteflow-testcase-el/liteflow-testcase-el-springnative/src/test/java/com/yomahub/liteflow/test/absoluteConfigPath/AbsoluteConfigPathELSpringTest.java +++ b/liteflow-testcase-el/liteflow-testcase-el-springnative/src/test/java/com/yomahub/liteflow/test/absoluteConfigPath/AbsoluteConfigPathELSpringTest.java @@ -1,9 +1,15 @@ package com.yomahub.liteflow.test.absoluteConfigPath; +import cn.hutool.core.io.FileUtil; +import cn.hutool.core.util.CharsetUtil; import com.yomahub.liteflow.core.FlowExecutor; import com.yomahub.liteflow.flow.LiteflowResponse; +import com.yomahub.liteflow.property.LiteflowConfig; +import com.yomahub.liteflow.property.LiteflowConfigGetter; import com.yomahub.liteflow.test.BaseTest; +import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.test.context.ContextConfiguration; @@ -25,9 +31,36 @@ public class AbsoluteConfigPathELSpringTest extends BaseTest { private FlowExecutor flowExecutor; @Test - public void testAbsoluteConfig() { - LiteflowResponse response = flowExecutor.execute2Resp("chain1", "arg"); - Assertions.assertTrue(response.isSuccess()); + public void testAbsoluteConfig() throws Exception { + Assertions.assertTrue(() -> { + LiteflowConfig config = LiteflowConfigGetter.get(); + config.setRuleSource("C:/LiteFlow/Test/a/b/c/flow.el.xml"); + flowExecutor.reloadRule(); + return flowExecutor.execute2Resp("chain1", "arg").isSuccess(); + }); + } + + @Test + public void testAbsolutePathMatch() throws Exception { + Assertions.assertTrue(() -> { + LiteflowConfig config = LiteflowConfigGetter.get(); + config.setRuleSource("C:/LiteFlow/Tes*/**/c/*.el.xml"); + flowExecutor.reloadRule(); + return flowExecutor.execute2Resp("chain1", "arg").isSuccess(); + }); + } + + @BeforeAll + public static void createFiles() { + String filePath = "C:/LiteFlow/Test/a/b/c"; + String content = "WHEN(a, b, c);"; + FileUtil.mkdir(filePath); + FileUtil.writeString(content, filePath + "/flow.el.xml", CharsetUtil.CHARSET_UTF_8); + } + + @AfterAll + public static void removeFiles() { + FileUtil.del("C:/LiteFlow"); } } diff --git a/liteflow-testcase-el/liteflow-testcase-el-springnative/src/test/resources/absoluteConfigPath/application.xml b/liteflow-testcase-el/liteflow-testcase-el-springnative/src/test/resources/absoluteConfigPath/application.xml index c3e5fe362..a27805f4c 100644 --- a/liteflow-testcase-el/liteflow-testcase-el-springnative/src/test/resources/absoluteConfigPath/application.xml +++ b/liteflow-testcase-el/liteflow-testcase-el-springnative/src/test/resources/absoluteConfigPath/application.xml @@ -14,13 +14,9 @@ - + - - - - diff --git a/liteflow-testcase-el/liteflow-testcase-el-springnative/src/test/resources/absoluteConfigPath/flow.el.xml b/liteflow-testcase-el/liteflow-testcase-el-springnative/src/test/resources/absoluteConfigPath/flow.el.xml index 507e19d62..4871fa66c 100644 --- a/liteflow-testcase-el/liteflow-testcase-el-springnative/src/test/resources/absoluteConfigPath/flow.el.xml +++ b/liteflow-testcase-el/liteflow-testcase-el-springnative/src/test/resources/absoluteConfigPath/flow.el.xml @@ -1,5 +1,5 @@ - + WHEN(a,b,c); From 4e6f19dd6024d32c732d4c1dc6a47cf2ef555d5e Mon Sep 17 00:00:00 2001 From: rain <672378783@qq.com> Date: Mon, 9 Oct 2023 16:11:57 +0800 Subject: [PATCH 49/53] =?UTF-8?q?=E6=94=AF=E6=8C=81=E7=BB=9D=E5=AF=B9?= =?UTF-8?q?=E8=B7=AF=E5=BE=84=E7=9A=84=E6=A8=A1=E7=B3=8A=E5=8C=B9=E9=85=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/yomahub/liteflow/parser/factory/LocalParserFactory.java | 2 +- liteflow-testcase-el/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/parser/factory/LocalParserFactory.java b/liteflow-core/src/main/java/com/yomahub/liteflow/parser/factory/LocalParserFactory.java index 53ef7cfb9..2a8e6b650 100644 --- a/liteflow-core/src/main/java/com/yomahub/liteflow/parser/factory/LocalParserFactory.java +++ b/liteflow-core/src/main/java/com/yomahub/liteflow/parser/factory/LocalParserFactory.java @@ -1,6 +1,6 @@ package com.yomahub.liteflow.parser.factory; -import com.yomahub.liteflow.parser.*; +//import com.yomahub.liteflow.parser.*; import com.yomahub.liteflow.parser.el.*; /** diff --git a/liteflow-testcase-el/pom.xml b/liteflow-testcase-el/pom.xml index 3aacdd528..fa9ba90e1 100644 --- a/liteflow-testcase-el/pom.xml +++ b/liteflow-testcase-el/pom.xml @@ -46,7 +46,7 @@ maven-deploy-plugin 2.8.2 - true + false From 7deb548d105aa102d11699020dde02b079638baf Mon Sep 17 00:00:00 2001 From: rain <672378783@qq.com> Date: Mon, 9 Oct 2023 16:14:52 +0800 Subject: [PATCH 50/53] =?UTF-8?q?=E6=94=AF=E6=8C=81=E7=BB=9D=E5=AF=B9?= =?UTF-8?q?=E8=B7=AF=E5=BE=84=E7=9A=84=E6=A8=A1=E7=B3=8A=E5=8C=B9=E9=85=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/yomahub/liteflow/parser/factory/LocalParserFactory.java | 2 +- liteflow-testcase-el/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/parser/factory/LocalParserFactory.java b/liteflow-core/src/main/java/com/yomahub/liteflow/parser/factory/LocalParserFactory.java index 2a8e6b650..53ef7cfb9 100644 --- a/liteflow-core/src/main/java/com/yomahub/liteflow/parser/factory/LocalParserFactory.java +++ b/liteflow-core/src/main/java/com/yomahub/liteflow/parser/factory/LocalParserFactory.java @@ -1,6 +1,6 @@ package com.yomahub.liteflow.parser.factory; -//import com.yomahub.liteflow.parser.*; +import com.yomahub.liteflow.parser.*; import com.yomahub.liteflow.parser.el.*; /** diff --git a/liteflow-testcase-el/pom.xml b/liteflow-testcase-el/pom.xml index fa9ba90e1..3aacdd528 100644 --- a/liteflow-testcase-el/pom.xml +++ b/liteflow-testcase-el/pom.xml @@ -46,7 +46,7 @@ maven-deploy-plugin 2.8.2 - false + true From f137700babbc010c868fff92f5ecff3b4dce8098 Mon Sep 17 00:00:00 2001 From: "everywhere.z" Date: Mon, 9 Oct 2023 18:57:45 +0800 Subject: [PATCH 51/53] =?UTF-8?q?=E4=BC=98=E5=8C=96=E7=BB=9D=E5=AF=B9?= =?UTF-8?q?=E8=B7=AF=E5=BE=84=E7=9A=84=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 --- ...teConfigPathELDeclMultiSpringbootTest.java | 27 +++++++--- .../absoluteConfigPath/application.properties | 1 - .../resources/absoluteConfigPath/flow.el.xml | 7 --- ...bsoluteConfigPathELDeclSpringbootTest.java | 27 +++++++--- .../absoluteConfigPath/application.properties | 1 - .../resources/absoluteConfigPath/flow.el.xml | 7 --- .../AbsoluteConfigPathTest.java | 50 +++++++++---------- .../resources/absoluteConfigPath/flow.el.xml | 13 ----- .../AbsoluteConfigPathELSpringbootTest.java | 27 +++++++--- .../absoluteConfigPath/application.properties | 1 - .../resources/absoluteConfigPath/flow.el.xml | 7 --- .../AbsoluteConfigPathELSpringbootTest.java | 29 ++++++++--- .../MonitorFileELSpringbootTest.java | 2 +- .../absoluteConfigPath/application.properties | 1 - .../resources/absoluteConfigPath/flow.el.xml | 7 --- .../AbsoluteConfigPathELSpringTest.java | 27 +++++++--- .../absoluteConfigPath/application.xml | 1 - .../resources/absoluteConfigPath/flow.el.xml | 7 --- 18 files changed, 127 insertions(+), 115 deletions(-) delete mode 100644 liteflow-testcase-el/liteflow-testcase-el-declare-multi-springboot/src/test/resources/absoluteConfigPath/application.properties delete mode 100644 liteflow-testcase-el/liteflow-testcase-el-declare-multi-springboot/src/test/resources/absoluteConfigPath/flow.el.xml delete mode 100644 liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/resources/absoluteConfigPath/application.properties delete mode 100644 liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/resources/absoluteConfigPath/flow.el.xml delete mode 100644 liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/resources/absoluteConfigPath/flow.el.xml delete mode 100644 liteflow-testcase-el/liteflow-testcase-el-solon/src/test/resources/absoluteConfigPath/application.properties delete mode 100644 liteflow-testcase-el/liteflow-testcase-el-solon/src/test/resources/absoluteConfigPath/flow.el.xml delete mode 100644 liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/absoluteConfigPath/application.properties delete mode 100644 liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/absoluteConfigPath/flow.el.xml delete mode 100644 liteflow-testcase-el/liteflow-testcase-el-springnative/src/test/resources/absoluteConfigPath/flow.el.xml diff --git a/liteflow-testcase-el/liteflow-testcase-el-declare-multi-springboot/src/test/java/com/yomahub/liteflow/test/absoluteConfigPath/AbsoluteConfigPathELDeclMultiSpringbootTest.java b/liteflow-testcase-el/liteflow-testcase-el-declare-multi-springboot/src/test/java/com/yomahub/liteflow/test/absoluteConfigPath/AbsoluteConfigPathELDeclMultiSpringbootTest.java index e04dbc456..fd619cdf2 100644 --- a/liteflow-testcase-el/liteflow-testcase-el-declare-multi-springboot/src/test/java/com/yomahub/liteflow/test/absoluteConfigPath/AbsoluteConfigPathELDeclMultiSpringbootTest.java +++ b/liteflow-testcase-el/liteflow-testcase-el-declare-multi-springboot/src/test/java/com/yomahub/liteflow/test/absoluteConfigPath/AbsoluteConfigPathELDeclMultiSpringbootTest.java @@ -2,6 +2,7 @@ package com.yomahub.liteflow.test.absoluteConfigPath; import cn.hutool.core.io.FileUtil; import cn.hutool.core.util.CharsetUtil; +import cn.hutool.core.util.StrUtil; import com.yomahub.liteflow.core.FlowExecutor; import com.yomahub.liteflow.flow.LiteflowResponse; import com.yomahub.liteflow.property.LiteflowConfig; @@ -22,6 +23,7 @@ import org.springframework.test.context.TestPropertySource; import org.springframework.test.context.junit4.SpringRunner; import javax.annotation.Resource; +import java.util.Objects; /** * springboot环境下异步线程超时日志打印测试 @@ -35,6 +37,8 @@ import javax.annotation.Resource; @ComponentScan({ "com.yomahub.liteflow.test.absoluteConfigPath.cmp" }) public class AbsoluteConfigPathELDeclMultiSpringbootTest extends BaseTest { + private static String rootDir; + @Resource private FlowExecutor flowExecutor; @@ -42,7 +46,7 @@ public class AbsoluteConfigPathELDeclMultiSpringbootTest extends BaseTest { public void testAbsoluteConfig() throws Exception { Assertions.assertTrue(() -> { LiteflowConfig config = LiteflowConfigGetter.get(); - config.setRuleSource("C:/LiteFlow/Test/a/b/c/flow.el.xml"); + config.setRuleSource(StrUtil.format("{}/sub/a/flow1.xml",rootDir)); flowExecutor.reloadRule(); return flowExecutor.execute2Resp("chain1", "arg").isSuccess(); }); @@ -52,7 +56,7 @@ public class AbsoluteConfigPathELDeclMultiSpringbootTest extends BaseTest { public void testAbsolutePathMatch() throws Exception { Assertions.assertTrue(() -> { LiteflowConfig config = LiteflowConfigGetter.get(); - config.setRuleSource("C:/LiteFlow/Tes*/**/c/*.el.xml"); + config.setRuleSource(StrUtil.format("{}/sub/**/*.xml",rootDir)); flowExecutor.reloadRule(); return flowExecutor.execute2Resp("chain1", "arg").isSuccess(); }); @@ -60,15 +64,24 @@ public class AbsoluteConfigPathELDeclMultiSpringbootTest extends BaseTest { @BeforeAll public static void createFiles() { - String filePath = "C:/LiteFlow/Test/a/b/c"; - String content = "WHEN(a, b, c);"; - FileUtil.mkdir(filePath); - FileUtil.writeString(content, filePath + "/flow.el.xml", CharsetUtil.CHARSET_UTF_8); + rootDir = Objects.requireNonNull(AbsoluteConfigPathELDeclMultiSpringbootTest.class.getResource("/")).getPath(); + + String path1 = StrUtil.format("{}/sub/a", rootDir); + String path2 = StrUtil.format("{}/sub/b", rootDir); + + FileUtil.mkdir(path1); + FileUtil.mkdir(path2); + + String content1 = "WHEN(a, b, c);"; + String content2 = "THEN(c, chain1);"; + + FileUtil.writeString(content1, path1 + "/flow1.xml", CharsetUtil.CHARSET_UTF_8); + FileUtil.writeString(content2, path2 + "/flow2.xml", CharsetUtil.CHARSET_UTF_8); } @AfterAll public static void removeFiles() { - FileUtil.del("C:/LiteFlow"); + FileUtil.del(StrUtil.format("{}/sub", rootDir)); } } diff --git a/liteflow-testcase-el/liteflow-testcase-el-declare-multi-springboot/src/test/resources/absoluteConfigPath/application.properties b/liteflow-testcase-el/liteflow-testcase-el-declare-multi-springboot/src/test/resources/absoluteConfigPath/application.properties deleted file mode 100644 index 93a30df79..000000000 --- a/liteflow-testcase-el/liteflow-testcase-el-declare-multi-springboot/src/test/resources/absoluteConfigPath/application.properties +++ /dev/null @@ -1 +0,0 @@ -liteflow.rule-source=C:/LiteFlow/Test/a/b/c/flow.el.xml \ No newline at end of file diff --git a/liteflow-testcase-el/liteflow-testcase-el-declare-multi-springboot/src/test/resources/absoluteConfigPath/flow.el.xml b/liteflow-testcase-el/liteflow-testcase-el-declare-multi-springboot/src/test/resources/absoluteConfigPath/flow.el.xml deleted file mode 100644 index 4871fa66c..000000000 --- a/liteflow-testcase-el/liteflow-testcase-el-declare-multi-springboot/src/test/resources/absoluteConfigPath/flow.el.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - - WHEN(a,b,c); - - \ No newline at end of file diff --git a/liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/java/com/yomahub/liteflow/test/absoluteConfigPath/AbsoluteConfigPathELDeclSpringbootTest.java b/liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/java/com/yomahub/liteflow/test/absoluteConfigPath/AbsoluteConfigPathELDeclSpringbootTest.java index c59dbe1a5..1acd5c5f3 100644 --- a/liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/java/com/yomahub/liteflow/test/absoluteConfigPath/AbsoluteConfigPathELDeclSpringbootTest.java +++ b/liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/java/com/yomahub/liteflow/test/absoluteConfigPath/AbsoluteConfigPathELDeclSpringbootTest.java @@ -2,6 +2,7 @@ package com.yomahub.liteflow.test.absoluteConfigPath; import cn.hutool.core.io.FileUtil; import cn.hutool.core.util.CharsetUtil; +import cn.hutool.core.util.StrUtil; import com.yomahub.liteflow.core.FlowExecutor; import com.yomahub.liteflow.flow.LiteflowResponse; import com.yomahub.liteflow.property.LiteflowConfig; @@ -22,6 +23,7 @@ import org.springframework.test.context.TestPropertySource; import org.springframework.test.context.junit4.SpringRunner; import javax.annotation.Resource; +import java.util.Objects; /** * springboot环境下异步线程超时日志打印测试 @@ -35,6 +37,8 @@ import javax.annotation.Resource; @ComponentScan({ "com.yomahub.liteflow.test.absoluteConfigPath.cmp" }) public class AbsoluteConfigPathELDeclSpringbootTest extends BaseTest { + private static String rootDir; + @Resource private FlowExecutor flowExecutor; @@ -42,7 +46,7 @@ public class AbsoluteConfigPathELDeclSpringbootTest extends BaseTest { public void testAbsoluteConfig() throws Exception { Assertions.assertTrue(() -> { LiteflowConfig config = LiteflowConfigGetter.get(); - config.setRuleSource("C:/LiteFlow/Test/a/b/c/flow.el.xml"); + config.setRuleSource(StrUtil.format("{}/sub/a/flow1.xml",rootDir)); flowExecutor.reloadRule(); return flowExecutor.execute2Resp("chain1", "arg").isSuccess(); }); @@ -52,7 +56,7 @@ public class AbsoluteConfigPathELDeclSpringbootTest extends BaseTest { public void testAbsolutePathMatch() throws Exception { Assertions.assertTrue(() -> { LiteflowConfig config = LiteflowConfigGetter.get(); - config.setRuleSource("C:/LiteFlow/Tes*/**/c/*.el.xml"); + config.setRuleSource(StrUtil.format("{}/sub/**/*.xml",rootDir)); flowExecutor.reloadRule(); return flowExecutor.execute2Resp("chain1", "arg").isSuccess(); }); @@ -60,15 +64,24 @@ public class AbsoluteConfigPathELDeclSpringbootTest extends BaseTest { @BeforeAll public static void createFiles() { - String filePath = "C:/LiteFlow/Test/a/b/c"; - String content = "WHEN(a, b, c);"; - FileUtil.mkdir(filePath); - FileUtil.writeString(content, filePath + "/flow.el.xml", CharsetUtil.CHARSET_UTF_8); + rootDir = Objects.requireNonNull(AbsoluteConfigPathELDeclSpringbootTest.class.getResource("/")).getPath(); + + String path1 = StrUtil.format("{}/sub/a", rootDir); + String path2 = StrUtil.format("{}/sub/b", rootDir); + + FileUtil.mkdir(path1); + FileUtil.mkdir(path2); + + String content1 = "WHEN(a, b, c);"; + String content2 = "THEN(c, chain1);"; + + FileUtil.writeString(content1, path1 + "/flow1.xml", CharsetUtil.CHARSET_UTF_8); + FileUtil.writeString(content2, path2 + "/flow2.xml", CharsetUtil.CHARSET_UTF_8); } @AfterAll public static void removeFiles() { - FileUtil.del("C:/LiteFlow"); + FileUtil.del(StrUtil.format("{}/sub", rootDir)); } } diff --git a/liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/resources/absoluteConfigPath/application.properties b/liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/resources/absoluteConfigPath/application.properties deleted file mode 100644 index 93a30df79..000000000 --- a/liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/resources/absoluteConfigPath/application.properties +++ /dev/null @@ -1 +0,0 @@ -liteflow.rule-source=C:/LiteFlow/Test/a/b/c/flow.el.xml \ No newline at end of file diff --git a/liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/resources/absoluteConfigPath/flow.el.xml b/liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/resources/absoluteConfigPath/flow.el.xml deleted file mode 100644 index 4871fa66c..000000000 --- a/liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/resources/absoluteConfigPath/flow.el.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - - WHEN(a,b,c); - - \ No newline at end of file diff --git a/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/java/com/yomahub/liteflow/test/absoluteConfigPath/AbsoluteConfigPathTest.java b/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/java/com/yomahub/liteflow/test/absoluteConfigPath/AbsoluteConfigPathTest.java index f9c1c3139..1cd83da4a 100644 --- a/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/java/com/yomahub/liteflow/test/absoluteConfigPath/AbsoluteConfigPathTest.java +++ b/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/java/com/yomahub/liteflow/test/absoluteConfigPath/AbsoluteConfigPathTest.java @@ -2,6 +2,7 @@ package com.yomahub.liteflow.test.absoluteConfigPath; import cn.hutool.core.io.FileUtil; import cn.hutool.core.util.CharsetUtil; +import cn.hutool.core.util.StrUtil; import com.yomahub.liteflow.core.FlowExecutor; import com.yomahub.liteflow.core.FlowExecutorHolder; import com.yomahub.liteflow.flow.LiteflowResponse; @@ -13,6 +14,8 @@ import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; +import java.util.Objects; + /** * 非spring环境下异步线程超时日志打印测试 * @@ -21,15 +24,17 @@ import org.junit.jupiter.api.Test; */ public class AbsoluteConfigPathTest extends BaseTest { + private static String rootDir; + private static FlowExecutor flowExecutor; @Test public void testAbsoluteConfig() throws Exception { Assertions.assertTrue(() -> { - LiteflowConfig config = LiteflowConfigGetter.get(); - config.setRuleSource("C:/LiteFlow/Test/a/b/c/flow.el.xml"); - flowExecutor.reloadRule(); + LiteflowConfig config = new LiteflowConfig(); + config.setRuleSource(StrUtil.format("{}/sub/a/flow1.xml",rootDir)); + flowExecutor = FlowExecutorHolder.loadInstance(config); return flowExecutor.execute2Resp("chain1", "arg").isSuccess(); }); } @@ -37,37 +42,32 @@ public class AbsoluteConfigPathTest extends BaseTest { @Test public void testAbsolutePathMatch() throws Exception { Assertions.assertTrue(() -> { - LiteflowConfig config = LiteflowConfigGetter.get(); - config.setRuleSource("C:/LiteFlow/Tes*/**/c/*.el.xml"); - flowExecutor.reloadRule(); + LiteflowConfig config = new LiteflowConfig(); + config.setRuleSource(StrUtil.format("{}/sub/**/*.xml",rootDir)); + flowExecutor = FlowExecutorHolder.loadInstance(config); return flowExecutor.execute2Resp("chain1", "arg").isSuccess(); }); } @BeforeAll public static void createFiles() { - String filePath = "C:/LiteFlow/Test/a/b/c"; - String content = "\n" + - "\n" + - "\n" + - " \n" + - " \n" + - " \n" + - "\n" + - "\n" + - "\n" + - " WHEN(a,b,c);\n" + - "\n" + - ""; - FileUtil.mkdir(filePath); - FileUtil.writeString(content, filePath + "/flow.el.xml", CharsetUtil.CHARSET_UTF_8); - LiteflowConfig config = new LiteflowConfig(); - config.setRuleSource("absoluteConfigPath/flow.el.xml"); - flowExecutor = FlowExecutorHolder.loadInstance(config); + rootDir = Objects.requireNonNull(AbsoluteConfigPathTest.class.getResource("/")).getPath(); + + String path1 = StrUtil.format("{}/sub/a", rootDir); + String path2 = StrUtil.format("{}/sub/b", rootDir); + + FileUtil.mkdir(path1); + FileUtil.mkdir(path2); + + String content1 = "WHEN(a, b, c);"; + String content2 = "THEN(c, chain1);"; + + FileUtil.writeString(content1, path1 + "/flow1.xml", CharsetUtil.CHARSET_UTF_8); + FileUtil.writeString(content2, path2 + "/flow2.xml", CharsetUtil.CHARSET_UTF_8); } @AfterAll public static void removeFiles() { - FileUtil.del("C:/LiteFlow"); + FileUtil.del(StrUtil.format("{}/sub", rootDir)); } } diff --git a/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/resources/absoluteConfigPath/flow.el.xml b/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/resources/absoluteConfigPath/flow.el.xml deleted file mode 100644 index 59b01c85c..000000000 --- a/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/resources/absoluteConfigPath/flow.el.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - WHEN(a,b,c); - - \ No newline at end of file diff --git a/liteflow-testcase-el/liteflow-testcase-el-solon/src/test/java/com/yomahub/liteflow/test/absoluteConfigPath/AbsoluteConfigPathELSpringbootTest.java b/liteflow-testcase-el/liteflow-testcase-el-solon/src/test/java/com/yomahub/liteflow/test/absoluteConfigPath/AbsoluteConfigPathELSpringbootTest.java index 0ae3c55b0..923126e18 100644 --- a/liteflow-testcase-el/liteflow-testcase-el-solon/src/test/java/com/yomahub/liteflow/test/absoluteConfigPath/AbsoluteConfigPathELSpringbootTest.java +++ b/liteflow-testcase-el/liteflow-testcase-el-solon/src/test/java/com/yomahub/liteflow/test/absoluteConfigPath/AbsoluteConfigPathELSpringbootTest.java @@ -2,6 +2,7 @@ package com.yomahub.liteflow.test.absoluteConfigPath; import cn.hutool.core.io.FileUtil; import cn.hutool.core.util.CharsetUtil; +import cn.hutool.core.util.StrUtil; import com.yomahub.liteflow.core.FlowExecutor; import com.yomahub.liteflow.flow.LiteflowResponse; import com.yomahub.liteflow.property.LiteflowConfig; @@ -18,6 +19,8 @@ import org.noear.solon.test.annotation.TestPropertySource; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.util.Objects; + /** * springboot环境下异步线程超时日志打印测试 * @@ -27,6 +30,7 @@ import org.slf4j.LoggerFactory; @ExtendWith(SolonJUnit5Extension.class) public class AbsoluteConfigPathELSpringbootTest extends BaseTest { + private static String rootDir; @Inject private FlowExecutor flowExecutor; @@ -35,7 +39,7 @@ public class AbsoluteConfigPathELSpringbootTest extends BaseTest { public void testAbsoluteConfig() throws Exception { Assertions.assertTrue(() -> { LiteflowConfig config = LiteflowConfigGetter.get(); - config.setRuleSource("C:/LiteFlow/Test/a/b/c/flow.el.xml"); + config.setRuleSource(StrUtil.format("{}/sub/a/flow1.xml",rootDir)); flowExecutor.reloadRule(); return flowExecutor.execute2Resp("chain1", "arg").isSuccess(); }); @@ -45,7 +49,7 @@ public class AbsoluteConfigPathELSpringbootTest extends BaseTest { public void testAbsolutePathMatch() throws Exception { Assertions.assertTrue(() -> { LiteflowConfig config = LiteflowConfigGetter.get(); - config.setRuleSource("C:/LiteFlow/Tes*/**/c/*.el.xml"); + config.setRuleSource(StrUtil.format("{}/sub/**/*.xml",rootDir)); flowExecutor.reloadRule(); return flowExecutor.execute2Resp("chain1", "arg").isSuccess(); }); @@ -53,15 +57,24 @@ public class AbsoluteConfigPathELSpringbootTest extends BaseTest { @BeforeAll public static void createFiles() { - String filePath = "C:/LiteFlow/Test/a/b/c"; - String content = "WHEN(a, b, c);"; - FileUtil.mkdir(filePath); - FileUtil.writeString(content, filePath + "/flow.el.xml", CharsetUtil.CHARSET_UTF_8); + rootDir = Objects.requireNonNull(AbsoluteConfigPathELSpringbootTest.class.getResource("/")).getPath(); + + String path1 = StrUtil.format("{}/sub/a", rootDir); + String path2 = StrUtil.format("{}/sub/b", rootDir); + + FileUtil.mkdir(path1); + FileUtil.mkdir(path2); + + String content1 = "WHEN(a, b, c);"; + String content2 = "THEN(c, chain1);"; + + FileUtil.writeString(content1, path1 + "/flow1.xml", CharsetUtil.CHARSET_UTF_8); + FileUtil.writeString(content2, path2 + "/flow2.xml", CharsetUtil.CHARSET_UTF_8); } @AfterAll public static void removeFiles() { - FileUtil.del("C:/LiteFlow"); + FileUtil.del(StrUtil.format("{}/sub", rootDir)); } } diff --git a/liteflow-testcase-el/liteflow-testcase-el-solon/src/test/resources/absoluteConfigPath/application.properties b/liteflow-testcase-el/liteflow-testcase-el-solon/src/test/resources/absoluteConfigPath/application.properties deleted file mode 100644 index 93a30df79..000000000 --- a/liteflow-testcase-el/liteflow-testcase-el-solon/src/test/resources/absoluteConfigPath/application.properties +++ /dev/null @@ -1 +0,0 @@ -liteflow.rule-source=C:/LiteFlow/Test/a/b/c/flow.el.xml \ No newline at end of file diff --git a/liteflow-testcase-el/liteflow-testcase-el-solon/src/test/resources/absoluteConfigPath/flow.el.xml b/liteflow-testcase-el/liteflow-testcase-el-solon/src/test/resources/absoluteConfigPath/flow.el.xml deleted file mode 100644 index 4871fa66c..000000000 --- a/liteflow-testcase-el/liteflow-testcase-el-solon/src/test/resources/absoluteConfigPath/flow.el.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - - WHEN(a,b,c); - - \ No newline at end of file diff --git a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/absoluteConfigPath/AbsoluteConfigPathELSpringbootTest.java b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/absoluteConfigPath/AbsoluteConfigPathELSpringbootTest.java index 5bf77bb7d..f036c48a5 100644 --- a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/absoluteConfigPath/AbsoluteConfigPathELSpringbootTest.java +++ b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/absoluteConfigPath/AbsoluteConfigPathELSpringbootTest.java @@ -2,6 +2,7 @@ package com.yomahub.liteflow.test.absoluteConfigPath; import cn.hutool.core.io.FileUtil; import cn.hutool.core.util.CharsetUtil; +import cn.hutool.core.util.StrUtil; import com.yomahub.liteflow.core.FlowExecutor; import com.yomahub.liteflow.flow.LiteflowResponse; import com.yomahub.liteflow.property.LiteflowConfig; @@ -19,6 +20,7 @@ import org.springframework.context.annotation.ComponentScan; import org.springframework.test.context.TestPropertySource; import javax.annotation.Resource; +import java.util.Objects; /** * springboot环境下异步线程超时日志打印测试 @@ -32,6 +34,8 @@ import javax.annotation.Resource; public class AbsoluteConfigPathELSpringbootTest extends BaseTest { + private static String rootDir; + @Resource private FlowExecutor flowExecutor; @@ -39,7 +43,7 @@ public class AbsoluteConfigPathELSpringbootTest extends BaseTest { public void testAbsoluteConfig() throws Exception { Assertions.assertTrue(() -> { LiteflowConfig config = LiteflowConfigGetter.get(); - config.setRuleSource("C:/LiteFlow/Test/a/b/c/flow.el.xml"); + config.setRuleSource(StrUtil.format("{}/sub/a/flow1.xml",rootDir)); flowExecutor.reloadRule(); return flowExecutor.execute2Resp("chain1", "arg").isSuccess(); }); @@ -49,23 +53,32 @@ public class AbsoluteConfigPathELSpringbootTest extends BaseTest { public void testAbsolutePathMatch() throws Exception { Assertions.assertTrue(() -> { LiteflowConfig config = LiteflowConfigGetter.get(); - config.setRuleSource("C:/LiteFlow/Tes*/**/c/*.el.xml"); + config.setRuleSource(StrUtil.format("{}/sub/**/*.xml",rootDir)); flowExecutor.reloadRule(); - return flowExecutor.execute2Resp("chain1", "arg").isSuccess(); + return flowExecutor.execute2Resp("chain2", "arg").isSuccess(); }); } @BeforeAll public static void createFiles() { - String filePath = "C:/LiteFlow/Test/a/b/c"; - String content = "WHEN(a, b, c);"; - FileUtil.mkdir(filePath); - FileUtil.writeString(content, filePath + "/flow.el.xml", CharsetUtil.CHARSET_UTF_8); + rootDir = Objects.requireNonNull(AbsoluteConfigPathELSpringbootTest.class.getResource("/")).getPath(); + + String path1 = StrUtil.format("{}/sub/a", rootDir); + String path2 = StrUtil.format("{}/sub/b", rootDir); + + FileUtil.mkdir(path1); + FileUtil.mkdir(path2); + + String content1 = "WHEN(a, b, c);"; + String content2 = "THEN(c, chain1);"; + + FileUtil.writeString(content1, path1 + "/flow1.xml", CharsetUtil.CHARSET_UTF_8); + FileUtil.writeString(content2, path2 + "/flow2.xml", CharsetUtil.CHARSET_UTF_8); } @AfterAll public static void removeFiles() { - FileUtil.del("C:/LiteFlow"); + FileUtil.del(StrUtil.format("{}/sub", rootDir)); } } diff --git a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/monitorFile/MonitorFileELSpringbootTest.java b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/monitorFile/MonitorFileELSpringbootTest.java index 3b7194f9e..51dbd9e53 100644 --- a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/monitorFile/MonitorFileELSpringbootTest.java +++ b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/monitorFile/MonitorFileELSpringbootTest.java @@ -43,7 +43,7 @@ public class MonitorFileELSpringbootTest extends BaseTest { */ @Test public void testMonitorAbsolutePath() throws Exception { - String absolutePath = "/your/path/dir"; + String absolutePath = new ClassPathResource("classpath:/monitorFile/flow.el.xml").getAbsolutePath(); FileUtil.writeString("THEN(a, b, c);", new File(absolutePath), CharsetUtil.CHARSET_UTF_8); String content = FileUtil.readUtf8String(absolutePath); String newContent = content.replace("THEN(a, b, c);", "THEN(a, c, b);"); diff --git a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/absoluteConfigPath/application.properties b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/absoluteConfigPath/application.properties deleted file mode 100644 index 93a30df79..000000000 --- a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/absoluteConfigPath/application.properties +++ /dev/null @@ -1 +0,0 @@ -liteflow.rule-source=C:/LiteFlow/Test/a/b/c/flow.el.xml \ No newline at end of file diff --git a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/absoluteConfigPath/flow.el.xml b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/absoluteConfigPath/flow.el.xml deleted file mode 100644 index 4871fa66c..000000000 --- a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/absoluteConfigPath/flow.el.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - - WHEN(a,b,c); - - \ No newline at end of file diff --git a/liteflow-testcase-el/liteflow-testcase-el-springnative/src/test/java/com/yomahub/liteflow/test/absoluteConfigPath/AbsoluteConfigPathELSpringTest.java b/liteflow-testcase-el/liteflow-testcase-el-springnative/src/test/java/com/yomahub/liteflow/test/absoluteConfigPath/AbsoluteConfigPathELSpringTest.java index 447d6e965..50aa12094 100644 --- a/liteflow-testcase-el/liteflow-testcase-el-springnative/src/test/java/com/yomahub/liteflow/test/absoluteConfigPath/AbsoluteConfigPathELSpringTest.java +++ b/liteflow-testcase-el/liteflow-testcase-el-springnative/src/test/java/com/yomahub/liteflow/test/absoluteConfigPath/AbsoluteConfigPathELSpringTest.java @@ -2,6 +2,7 @@ package com.yomahub.liteflow.test.absoluteConfigPath; import cn.hutool.core.io.FileUtil; import cn.hutool.core.util.CharsetUtil; +import cn.hutool.core.util.StrUtil; import com.yomahub.liteflow.core.FlowExecutor; import com.yomahub.liteflow.flow.LiteflowResponse; import com.yomahub.liteflow.property.LiteflowConfig; @@ -16,6 +17,7 @@ import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit.jupiter.SpringExtension; import javax.annotation.Resource; +import java.util.Objects; /** * spring环境下,规则配置文件通过绝对路径获取 @@ -27,6 +29,8 @@ import javax.annotation.Resource; @ContextConfiguration("classpath:/absoluteConfigPath/application.xml") public class AbsoluteConfigPathELSpringTest extends BaseTest { + private static String rootDir; + @Resource private FlowExecutor flowExecutor; @@ -34,7 +38,7 @@ public class AbsoluteConfigPathELSpringTest extends BaseTest { public void testAbsoluteConfig() throws Exception { Assertions.assertTrue(() -> { LiteflowConfig config = LiteflowConfigGetter.get(); - config.setRuleSource("C:/LiteFlow/Test/a/b/c/flow.el.xml"); + config.setRuleSource(StrUtil.format("{}/sub/a/flow1.xml",rootDir)); flowExecutor.reloadRule(); return flowExecutor.execute2Resp("chain1", "arg").isSuccess(); }); @@ -44,7 +48,7 @@ public class AbsoluteConfigPathELSpringTest extends BaseTest { public void testAbsolutePathMatch() throws Exception { Assertions.assertTrue(() -> { LiteflowConfig config = LiteflowConfigGetter.get(); - config.setRuleSource("C:/LiteFlow/Tes*/**/c/*.el.xml"); + config.setRuleSource(StrUtil.format("{}/sub/**/*.xml",rootDir)); flowExecutor.reloadRule(); return flowExecutor.execute2Resp("chain1", "arg").isSuccess(); }); @@ -52,15 +56,24 @@ public class AbsoluteConfigPathELSpringTest extends BaseTest { @BeforeAll public static void createFiles() { - String filePath = "C:/LiteFlow/Test/a/b/c"; - String content = "WHEN(a, b, c);"; - FileUtil.mkdir(filePath); - FileUtil.writeString(content, filePath + "/flow.el.xml", CharsetUtil.CHARSET_UTF_8); + rootDir = Objects.requireNonNull(AbsoluteConfigPathELSpringTest.class.getResource("/")).getPath(); + + String path1 = StrUtil.format("{}/sub/a", rootDir); + String path2 = StrUtil.format("{}/sub/b", rootDir); + + FileUtil.mkdir(path1); + FileUtil.mkdir(path2); + + String content1 = "WHEN(a, b, c);"; + String content2 = "THEN(c, chain1);"; + + FileUtil.writeString(content1, path1 + "/flow1.xml", CharsetUtil.CHARSET_UTF_8); + FileUtil.writeString(content2, path2 + "/flow2.xml", CharsetUtil.CHARSET_UTF_8); } @AfterAll public static void removeFiles() { - FileUtil.del("C:/LiteFlow"); + FileUtil.del(StrUtil.format("{}/sub", rootDir)); } } diff --git a/liteflow-testcase-el/liteflow-testcase-el-springnative/src/test/resources/absoluteConfigPath/application.xml b/liteflow-testcase-el/liteflow-testcase-el-springnative/src/test/resources/absoluteConfigPath/application.xml index a27805f4c..014574a06 100644 --- a/liteflow-testcase-el/liteflow-testcase-el-springnative/src/test/resources/absoluteConfigPath/application.xml +++ b/liteflow-testcase-el/liteflow-testcase-el-springnative/src/test/resources/absoluteConfigPath/application.xml @@ -14,7 +14,6 @@ - diff --git a/liteflow-testcase-el/liteflow-testcase-el-springnative/src/test/resources/absoluteConfigPath/flow.el.xml b/liteflow-testcase-el/liteflow-testcase-el-springnative/src/test/resources/absoluteConfigPath/flow.el.xml deleted file mode 100644 index 4871fa66c..000000000 --- a/liteflow-testcase-el/liteflow-testcase-el-springnative/src/test/resources/absoluteConfigPath/flow.el.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - - WHEN(a,b,c); - - \ No newline at end of file From f2a8a494dd9bed61fd567c844d2effc59eba9e62 Mon Sep 17 00:00:00 2001 From: "everywhere.z" Date: Mon, 9 Oct 2023 20:09:39 +0800 Subject: [PATCH 52/53] =?UTF-8?q?=E7=AE=80=E5=8C=96=E7=BB=84=E4=BB=B6?= =?UTF-8?q?=E9=99=8D=E7=BA=A7=E7=9A=84Node=E8=A3=85=E9=85=8D=E4=BB=A3?= =?UTF-8?q?=E7=90=86=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../liteflow/builder/el/operator/NodeOperator.java | 9 --------- 1 file changed, 9 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 16e3ae0e8..5735dcd87 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,12 +2,9 @@ package com.yomahub.liteflow.builder.el.operator; import com.yomahub.liteflow.builder.el.operator.base.BaseOperator; import com.yomahub.liteflow.builder.el.operator.base.OperatorHelper; -import com.yomahub.liteflow.exception.ELParseException; import com.yomahub.liteflow.flow.FlowBus; import com.yomahub.liteflow.flow.element.FallbackNodeProxy; import com.yomahub.liteflow.flow.element.Node; -import com.yomahub.liteflow.property.LiteflowConfig; -import com.yomahub.liteflow.property.LiteflowConfigGetter; /** * EL规则中的node的操作符 @@ -27,12 +24,6 @@ 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); } From ac7649a28c4ab743eeda701599122dda6fe12df1 Mon Sep 17 00:00:00 2001 From: "everywhere.z" Date: Mon, 9 Oct 2023 20:10:00 +0800 Subject: [PATCH 53/53] =?UTF-8?q?=E5=8D=87=E7=BA=A7QLExpress=E5=88=B03.3.2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index ba38e0837..22fa42648 100644 --- a/pom.xml +++ b/pom.xml @@ -58,7 +58,7 @@ 0.10 0.7.3 1.4.4 - 3.3.1 + 3.3.2 3.0.8 21.3.3.1 1.12.23