mirror of
https://gitee.com/dromara/liteFlow.git
synced 2026-05-14 20:22:07 +08:00
feature #I7I3LL 增加TimeoutCondition
This commit is contained in:
@@ -1,15 +1,13 @@
|
||||
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.WhenCondition;
|
||||
import com.yomahub.liteflow.flow.element.condition.*;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
@@ -35,7 +33,7 @@ public class MaxWaitSecondsOperator extends BaseOperator<Condition> {
|
||||
return whenCondition;
|
||||
} else if (executable instanceof FinallyCondition) {
|
||||
// FINALLY,报错
|
||||
String errorMsg = "The caller cannot be FinallyCondition item";
|
||||
String errorMsg = StrFormatter.format("The caller [{}] cannot use the keyword \"maxWaitSeconds'\"", executable.toString());
|
||||
throw new QLException(errorMsg);
|
||||
} else if (containsFinally(executable)) {
|
||||
// 处理 THEN 中的 FINALLY
|
||||
@@ -43,26 +41,28 @@ public class MaxWaitSecondsOperator extends BaseOperator<Condition> {
|
||||
return handleFinally(thenCondition, maxWaitSeconds);
|
||||
} else {
|
||||
// 其他情况,被 WHEN 包装
|
||||
return wrappedByWhen(executable, maxWaitSeconds);
|
||||
return wrappedByTimeout(executable, maxWaitSeconds);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 将一个 Executable 包装为带有单独超时控制的 WhenCondition
|
||||
* @param executable 带包装对象
|
||||
* 将一个 Executable 包装为带有单独超时控制的 TimeoutCondition
|
||||
*
|
||||
* @param executable 待包装对象
|
||||
* @param maxWaitSeconds 最大等待秒数
|
||||
* @return 包装后的 WhenCondition
|
||||
* @return 包装后的 TimeoutCondition
|
||||
*/
|
||||
private WhenCondition wrappedByWhen(Executable executable, Integer maxWaitSeconds) {
|
||||
WhenCondition whenCondition = new WhenCondition();
|
||||
whenCondition.addExecutable(executable);
|
||||
whenCondition.setMaxWaitTime(maxWaitSeconds);
|
||||
whenCondition.setMaxWaitTimeUnit(TimeUnit.SECONDS);
|
||||
return whenCondition;
|
||||
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
|
||||
*/
|
||||
@@ -73,7 +73,8 @@ public class MaxWaitSecondsOperator extends BaseOperator<Condition> {
|
||||
|
||||
/**
|
||||
* 将 FINALLY 排除在超时控制之外
|
||||
* @param thenCondition 待处理的 ThenCondition
|
||||
*
|
||||
* @param thenCondition 待处理的 ThenCondition
|
||||
* @param maxWaitSeconds 最大等待秒数
|
||||
* @return 处理后的 ThenCondition
|
||||
*/
|
||||
@@ -95,7 +96,7 @@ public class MaxWaitSecondsOperator extends BaseOperator<Condition> {
|
||||
finallyList.clear();
|
||||
|
||||
// 包装内部 THEN
|
||||
WhenCondition whenCondition = wrappedByWhen(thenCondition, maxWaitSeconds);
|
||||
WhenCondition whenCondition = wrappedByTimeout(thenCondition, maxWaitSeconds);
|
||||
outerThenCondition.addExecutable(whenCondition);
|
||||
|
||||
return outerThenCondition;
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
package com.yomahub.liteflow.flow.element.condition;
|
||||
|
||||
import cn.hutool.core.text.StrFormatter;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import com.yomahub.liteflow.exception.WhenTimeoutException;
|
||||
import com.yomahub.liteflow.flow.element.Chain;
|
||||
import com.yomahub.liteflow.flow.element.Condition;
|
||||
import com.yomahub.liteflow.flow.element.Executable;
|
||||
import com.yomahub.liteflow.flow.element.Node;
|
||||
|
||||
import java.util.concurrent.TimeoutException;
|
||||
|
||||
/**
|
||||
* 超时控制 Condition
|
||||
*
|
||||
* @author DaleLee
|
||||
* @since 2.11.0
|
||||
*/
|
||||
public class TimeoutCondition extends WhenCondition {
|
||||
|
||||
@Override
|
||||
public void executeCondition(Integer slotIndex) throws Exception {
|
||||
try {
|
||||
super.executeCondition(slotIndex);
|
||||
} catch (WhenTimeoutException ex) {
|
||||
// 将 WhenTimeoutException 转换为 TimeoutException
|
||||
String errMsg = StrFormatter.format("Timed out when executing the chain [{}] because [{}] exceeded {} {}.",
|
||||
this.getCurrChainId(), this.getCurrentExecutableId(), this.getMaxWaitTime(), this.getMaxWaitTimeUnit().toString().toLowerCase());
|
||||
throw new TimeoutException(errMsg);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前组件的 id
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
private String getCurrentExecutableId() {
|
||||
// TimeoutCondition 只有一个 Executable
|
||||
Executable executable = this.getExecutableList().get(0);
|
||||
if (ObjectUtil.isNotNull(executable.getId())) {
|
||||
// 已经有 id 了
|
||||
return executable.getId();
|
||||
}
|
||||
// 定义 id
|
||||
switch (executable.getExecuteType()) {
|
||||
// chain 和 node 一般都有 id
|
||||
case CHAIN:
|
||||
return ((Chain) executable).getChainId();
|
||||
case CONDITION:
|
||||
return "condition-" + ((Condition) executable).getConditionType().getName();
|
||||
case NODE:
|
||||
return "node-" + ((Node) executable).getType().getCode();
|
||||
default:
|
||||
return "unknown-executable";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -22,6 +22,8 @@ import org.springframework.test.context.junit4.SpringRunner;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
import java.util.concurrent.TimeoutException;
|
||||
|
||||
import static com.yomahub.liteflow.test.maxWaitSeconds.cmp.DCmp.CONTENT_KEY;
|
||||
|
||||
/**
|
||||
@@ -34,7 +36,7 @@ import static com.yomahub.liteflow.test.maxWaitSeconds.cmp.DCmp.CONTENT_KEY;
|
||||
@TestPropertySource(value = "classpath:/maxWaitSeconds/application.properties")
|
||||
@SpringBootTest(classes = MaxWaitSecondsELSpringbootTest.class)
|
||||
@EnableAutoConfiguration
|
||||
@ComponentScan({ "com.yomahub.liteflow.test.maxWaitSeconds.cmp" })
|
||||
@ComponentScan({"com.yomahub.liteflow.test.maxWaitSeconds.cmp"})
|
||||
public class MaxWaitSecondsELSpringbootTest extends BaseTest {
|
||||
|
||||
@Resource
|
||||
@@ -55,7 +57,8 @@ public class MaxWaitSecondsELSpringbootTest extends BaseTest {
|
||||
// 测试 When 的超时情况
|
||||
@Test
|
||||
public void testWhen1() {
|
||||
assertTimeout("when1");
|
||||
// WHEN 抛出的是 WhenTimeoutException
|
||||
assertWhenTimeout("when1");
|
||||
}
|
||||
|
||||
// 测试 WHEN 的非超时情况
|
||||
@@ -141,7 +144,7 @@ public class MaxWaitSecondsELSpringbootTest extends BaseTest {
|
||||
public void testFinally1() {
|
||||
LiteflowResponse response = flowExecutor.execute2Resp("finally", "arg");
|
||||
Assert.assertFalse(response.isSuccess());
|
||||
Assert.assertEquals(WhenTimeoutException.class, response.getCause().getClass());
|
||||
Assert.assertEquals(TimeoutException.class, response.getCause().getClass());
|
||||
// FINALLY 执行时在默认数据上下文中放入了 CONTENT_KEY
|
||||
DefaultContext contextBean = response.getFirstContextBean();
|
||||
Assert.assertTrue(contextBean.hasData(CONTENT_KEY));
|
||||
@@ -172,7 +175,25 @@ public class MaxWaitSecondsELSpringbootTest extends BaseTest {
|
||||
Assert.assertFalse(LiteFlowChainELBuilder.validate("THEN(a, b, FINALLY(c).maxWaitSeconds(10))"));
|
||||
}
|
||||
|
||||
// 测试 chain 的超时情况
|
||||
@Test
|
||||
public void testChain1() {
|
||||
assertTimeout("chain1");
|
||||
}
|
||||
|
||||
// 测试 chain 的非超时情况
|
||||
@Test
|
||||
public void testChain2() {
|
||||
assertNotTimeout("chain2");
|
||||
}
|
||||
|
||||
private void assertTimeout(String chainId) {
|
||||
LiteflowResponse response = flowExecutor.execute2Resp(chainId, "arg");
|
||||
Assert.assertFalse(response.isSuccess());
|
||||
Assert.assertEquals(TimeoutException.class, response.getCause().getClass());
|
||||
}
|
||||
|
||||
private void assertWhenTimeout(String chainId) {
|
||||
LiteflowResponse response = flowExecutor.execute2Resp(chainId, "arg");
|
||||
Assert.assertFalse(response.isSuccess());
|
||||
Assert.assertEquals(WhenTimeoutException.class, response.getCause().getClass());
|
||||
|
||||
@@ -95,4 +95,16 @@
|
||||
THEN(PRE(a), b, FINALLY(d)).maxWaitSeconds(2);
|
||||
</chain>
|
||||
|
||||
<!-- 测试 chain -->
|
||||
<chain name="testChain">
|
||||
THEN(b)
|
||||
</chain>
|
||||
<chain name="chain1">
|
||||
<!-- 超时 -->
|
||||
testChain.maxWaitSeconds(1);
|
||||
</chain>
|
||||
<chain name="chain2">
|
||||
<!-- 不超时 -->
|
||||
testChain.maxWaitSeconds(3);
|
||||
</chain>
|
||||
</flow>
|
||||
Reference in New Issue
Block a user