feature 超时时间支持毫秒 EL 操作符 maxWaitMilliseconds

This commit is contained in:
Kugaaa
2023-11-03 11:02:43 +08:00
parent 34018069a2
commit f6ca19f561
5 changed files with 158 additions and 88 deletions

View File

@@ -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());
}

View File

@@ -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;
}
}

View File

@@ -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<Condition> {
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<Executable> 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;
}
}

View File

@@ -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<Condition> {
@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<Executable> 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();
}

View File

@@ -85,6 +85,9 @@ public interface ChainConstant {
String NOT = "NOT";
String MAX_WAIT_SECONDS = "maxWaitSeconds";
String MAX_WAIT_MILLISECONDS = "maxWaitMilliseconds";
String EXTENDS = "extends";
}