From f6ca19f561cc0f6d40c44a9851d8c5c4f4ce12a3 Mon Sep 17 00:00:00 2001 From: Kugaaa Date: Fri, 3 Nov 2023 11:02:43 +0800 Subject: [PATCH] =?UTF-8?q?feature=20=E8=B6=85=E6=97=B6=E6=97=B6=E9=97=B4?= =?UTF-8?q?=E6=94=AF=E6=8C=81=E6=AF=AB=E7=A7=92=20EL=20=E6=93=8D=E4=BD=9C?= =?UTF-8?q?=E7=AC=A6=20maxWaitMilliseconds?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../builder/el/LiteFlowChainELBuilder.java | 1 + .../operator/MaxWaitMillisecondsOperator.java | 24 ++++ .../el/operator/MaxWaitSecondsOperator.java | 96 ++------------ .../el/operator/MaxWaitTimeOperator.java | 122 ++++++++++++++++++ .../liteflow/common/ChainConstant.java | 3 + 5 files changed, 158 insertions(+), 88 deletions(-) create mode 100644 liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/MaxWaitMillisecondsOperator.java create mode 100644 liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/MaxWaitTimeOperator.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 c2d22fc92..325dac3db 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 @@ -83,6 +83,7 @@ public class LiteFlowChainELBuilder { EXPRESS_RUNNER.addFunctionAndClassMethod(ChainConstant.BREAK, Object.class, new BreakOperator()); EXPRESS_RUNNER.addFunctionAndClassMethod(ChainConstant.DATA, Object.class, new DataOperator()); EXPRESS_RUNNER.addFunctionAndClassMethod(ChainConstant.MAX_WAIT_SECONDS, Object.class, new MaxWaitSecondsOperator()); + EXPRESS_RUNNER.addFunctionAndClassMethod(ChainConstant.MAX_WAIT_MILLISECONDS, Object.class, new MaxWaitMillisecondsOperator()); EXPRESS_RUNNER.addFunctionAndClassMethod(ChainConstant.PARALLEL, Object.class, new ParallelOperator()); } diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/MaxWaitMillisecondsOperator.java b/liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/MaxWaitMillisecondsOperator.java new file mode 100644 index 000000000..feeb01369 --- /dev/null +++ b/liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/MaxWaitMillisecondsOperator.java @@ -0,0 +1,24 @@ +package com.yomahub.liteflow.builder.el.operator; + +import com.yomahub.liteflow.common.ChainConstant; + +import java.util.concurrent.TimeUnit; + +/** + * EL 规则中的 maxWaitMilliseconds 的操作符 + * + * @author Kugaaa + * @since 2.11.1 + */ +public class MaxWaitMillisecondsOperator extends MaxWaitTimeOperator { + + @Override + TimeUnit getMaxWaitTimeUnit() { + return TimeUnit.MILLISECONDS; + } + + @Override + String operatorName() { + return ChainConstant.MAX_WAIT_MILLISECONDS; + } +} diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/MaxWaitSecondsOperator.java b/liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/MaxWaitSecondsOperator.java index e76252402..1eb33435b 100644 --- a/liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/MaxWaitSecondsOperator.java +++ b/liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/MaxWaitSecondsOperator.java @@ -1,15 +1,7 @@ package com.yomahub.liteflow.builder.el.operator; -import cn.hutool.core.collection.CollUtil; -import cn.hutool.core.text.StrFormatter; -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.flow.element.Condition; -import com.yomahub.liteflow.flow.element.Executable; -import com.yomahub.liteflow.flow.element.condition.*; +import com.yomahub.liteflow.common.ChainConstant; -import java.util.List; import java.util.concurrent.TimeUnit; /** @@ -18,87 +10,15 @@ import java.util.concurrent.TimeUnit; * @author DaleLee * @since 2.11.0 */ -public class MaxWaitSecondsOperator extends BaseOperator { +public class MaxWaitSecondsOperator extends MaxWaitTimeOperator { + @Override - public Condition build(Object[] objects) throws Exception { - OperatorHelper.checkObjectSizeEqTwo(objects); - Executable executable = OperatorHelper.convert(objects[0], Executable.class); - // 获取传入的时间参数 - Integer maxWaitSeconds = OperatorHelper.convert(objects[1], Integer.class); - if (executable instanceof WhenCondition) { - // WhenCondition,直接设置等待时间 - WhenCondition whenCondition = OperatorHelper.convert(executable, WhenCondition.class); - whenCondition.setMaxWaitTime(maxWaitSeconds); - whenCondition.setMaxWaitTimeUnit(TimeUnit.SECONDS); - return whenCondition; - } else if (executable instanceof FinallyCondition) { - // FINALLY,报错 - String errorMsg = StrFormatter.format("The caller [{}] cannot use the keyword \"maxWaitSeconds'\"", executable.toString()); - throw new QLException(errorMsg); - } else if (containsFinally(executable)) { - // 处理 THEN 中的 FINALLY - ThenCondition thenCondition = OperatorHelper.convert(executable, ThenCondition.class); - return handleFinally(thenCondition, maxWaitSeconds); - } else { - // 其他情况,被 WHEN 包装 - return wrappedByTimeout(executable, maxWaitSeconds); - } + TimeUnit getMaxWaitTimeUnit() { + return TimeUnit.SECONDS; } - /** - * 将一个 Executable 包装为带有单独超时控制的 TimeoutCondition - * - * @param executable 待包装对象 - * @param maxWaitSeconds 最大等待秒数 - * @return 包装后的 TimeoutCondition - */ - private TimeoutCondition wrappedByTimeout(Executable executable, Integer maxWaitSeconds) { - TimeoutCondition timeoutCondition = new TimeoutCondition(); - timeoutCondition.addExecutable(executable); - timeoutCondition.setMaxWaitTime(maxWaitSeconds); - timeoutCondition.setMaxWaitTimeUnit(TimeUnit.SECONDS); - return timeoutCondition; - } - - /** - * 判断 THEN 中是否含有 FINALLY 组件 - * - * @param executable 判断对象 - * @return 含有 FINALLY 组件返回 true,否则返回 false - */ - private boolean containsFinally(Executable executable) { - return executable instanceof ThenCondition - && CollUtil.isNotEmpty(((ThenCondition) executable).getFinallyConditionList()); - } - - /** - * 将 FINALLY 排除在超时控制之外 - * - * @param thenCondition 待处理的 ThenCondition - * @param maxWaitSeconds 最大等待秒数 - * @return 处理后的 ThenCondition - */ - private ThenCondition handleFinally(ThenCondition thenCondition, Integer maxWaitSeconds) { - // 进行如下转换 - // THEN(PRE(a),b,FINALLY(c)) - // => THEN( - // WHEN(THEN(PRE(a),b)), - // FINALLY(c)) - - // 定义外层 THEN - ThenCondition outerThenCondition = new ThenCondition(); - - // 把 FINALLY 转移到外层 THEN - List finallyList = thenCondition.getExecutableList(ConditionKey.FINALLY_KEY); - finallyList.forEach(executable - -> outerThenCondition - .addFinallyCondition((FinallyCondition) executable)); - finallyList.clear(); - - // 包装内部 THEN - WhenCondition whenCondition = wrappedByTimeout(thenCondition, maxWaitSeconds); - outerThenCondition.addExecutable(whenCondition); - - return outerThenCondition; + @Override + String operatorName() { + return ChainConstant.MAX_WAIT_SECONDS; } } diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/MaxWaitTimeOperator.java b/liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/MaxWaitTimeOperator.java new file mode 100644 index 000000000..fb5bdfd13 --- /dev/null +++ b/liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/MaxWaitTimeOperator.java @@ -0,0 +1,122 @@ +package com.yomahub.liteflow.builder.el.operator; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.text.StrFormatter; +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.flow.element.Condition; +import com.yomahub.liteflow.flow.element.Executable; +import com.yomahub.liteflow.flow.element.condition.ConditionKey; +import com.yomahub.liteflow.flow.element.condition.FinallyCondition; +import com.yomahub.liteflow.flow.element.condition.ThenCondition; +import com.yomahub.liteflow.flow.element.condition.TimeoutCondition; +import com.yomahub.liteflow.flow.element.condition.WhenCondition; + +import java.util.List; +import java.util.concurrent.TimeUnit; + +/** + * EL 规则中 + * - maxWaitSeconds {@link MaxWaitSecondsOperator} + * - MaxWaitMilliseconds {@link MaxWaitMillisecondsOperator} + * 操作符的抽象 + * + * @author Kugaaa + * @since 2.11.1 + */ +public abstract class MaxWaitTimeOperator extends BaseOperator { + + @Override + public Condition build(Object[] objects) throws Exception { + OperatorHelper.checkObjectSizeEqTwo(objects); + Executable executable = OperatorHelper.convert(objects[0], Executable.class); + // 获取传入的时间参数 + Integer maxWaitTime = OperatorHelper.convert(objects[1], Integer.class); + if (executable instanceof WhenCondition) { + // WhenCondition,直接设置等待时间 + WhenCondition whenCondition = OperatorHelper.convert(executable, WhenCondition.class); + whenCondition.setMaxWaitTime(maxWaitTime); + whenCondition.setMaxWaitTimeUnit(getMaxWaitTimeUnit()); + return whenCondition; + } else if (executable instanceof FinallyCondition) { + // FINALLY,报错 + String errorMsg = StrFormatter.format("The caller [{}] cannot use the keyword \"{}'\"", executable.toString(), operatorName()); + throw new QLException(errorMsg); + } else if (containsFinally(executable)) { + // 处理 THEN 中的 FINALLY + ThenCondition thenCondition = OperatorHelper.convert(executable, ThenCondition.class); + return handleFinally(thenCondition, maxWaitTime); + } else { + // 其他情况,被 WHEN 包装 + return wrappedByTimeout(executable, maxWaitTime); + } + } + + /** + * 将一个 Executable 包装为带有单独超时控制的 TimeoutCondition + * + * @param executable 待包装对象 + * @param maxWaitTime 最大等待时间 + * @return 包装后的 TimeoutCondition + */ + private TimeoutCondition wrappedByTimeout(Executable executable, Integer maxWaitTime) { + TimeoutCondition timeoutCondition = new TimeoutCondition(); + timeoutCondition.addExecutable(executable); + timeoutCondition.setMaxWaitTime(maxWaitTime); + timeoutCondition.setMaxWaitTimeUnit(getMaxWaitTimeUnit()); + return timeoutCondition; + } + + /** + * 判断 THEN 中是否含有 FINALLY 组件 + * + * @param executable 判断对象 + * @return 含有 FINALLY 组件返回 true,否则返回 false + */ + private boolean containsFinally(Executable executable) { + return executable instanceof ThenCondition + && CollUtil.isNotEmpty(((ThenCondition) executable).getFinallyConditionList()); + } + + /** + * 将 FINALLY 排除在超时控制之外 + * + * @param thenCondition 待处理的 ThenCondition + * @param maxWaitTime 最大等待时间 + * @return 处理后的 ThenCondition + */ + private ThenCondition handleFinally(ThenCondition thenCondition, Integer maxWaitTime) { + // 进行如下转换 + // THEN(PRE(a),b,FINALLY(c)) + // => THEN( + // WHEN(THEN(PRE(a),b)), + // FINALLY(c)) + + // 定义外层 THEN + ThenCondition outerThenCondition = new ThenCondition(); + + // 把 FINALLY 转移到外层 THEN + List finallyList = thenCondition.getExecutableList(ConditionKey.FINALLY_KEY); + finallyList.forEach(executable + -> outerThenCondition + .addFinallyCondition((FinallyCondition) executable)); + finallyList.clear(); + + // 包装内部 THEN + WhenCondition whenCondition = wrappedByTimeout(thenCondition, maxWaitTime); + outerThenCondition.addExecutable(whenCondition); + + return outerThenCondition; + } + + /** + * 获取等待时间单位 + */ + abstract TimeUnit getMaxWaitTimeUnit(); + + /** + * 操作符名称 + */ + abstract String operatorName(); +} 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 e71b0c0ac..625b28c55 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 @@ -85,6 +85,9 @@ public interface ChainConstant { String NOT = "NOT"; String MAX_WAIT_SECONDS = "maxWaitSeconds"; + + String MAX_WAIT_MILLISECONDS = "maxWaitMilliseconds"; + String EXTENDS = "extends"; }