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"; } diff --git a/liteflow-testcase-el/liteflow-testcase-el-declare-multi-springboot/src/test/java/com/yomahub/liteflow/test/maxWaitMilliseconds/MaxWaitMillisecondsELDeclMultiSpringbootTest.java b/liteflow-testcase-el/liteflow-testcase-el-declare-multi-springboot/src/test/java/com/yomahub/liteflow/test/maxWaitMilliseconds/MaxWaitMillisecondsELDeclMultiSpringbootTest.java new file mode 100644 index 000000000..28561e5ae --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-declare-multi-springboot/src/test/java/com/yomahub/liteflow/test/maxWaitMilliseconds/MaxWaitMillisecondsELDeclMultiSpringbootTest.java @@ -0,0 +1,179 @@ +package com.yomahub.liteflow.test.maxWaitMilliseconds; + +import com.yomahub.liteflow.builder.el.LiteFlowChainELBuilder; +import com.yomahub.liteflow.core.FlowExecutor; +import com.yomahub.liteflow.exception.WhenTimeoutException; +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; +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.util.concurrent.TimeoutException; + +import static com.yomahub.liteflow.test.maxWaitSeconds.cmp.CmpConfig.CONTENT_KEY; + +/** + * Spring Boot 环境下超时控制测试 - maxWaitMilliseconds + * + * @author Kugaaa + * @since 2.11.1 + */ +@ExtendWith(SpringExtension.class) +@TestPropertySource(value = "classpath:/maxWaitMilliseconds/application.properties") +@SpringBootTest(classes = MaxWaitMillisecondsELDeclMultiSpringbootTest.class) +@EnableAutoConfiguration +@ComponentScan({"com.yomahub.liteflow.test.maxWaitMilliseconds.cmp"}) +public class MaxWaitMillisecondsELDeclMultiSpringbootTest extends BaseTest { + @Resource + private FlowExecutor flowExecutor; + + // 测试 THEN 的超时情况 + @Test + public void testThen1() { + assertTimeout("then1"); + } + + // 测试 THEN 的非超时情况 + @Test + public void testThen2() { + assertNotTimeout("then2"); + } + + // 测试 When 的超时情况 + @Test + public void testWhen1() { + assertWhenTimeout("when1"); + } + + // 测试 WHEN 的非超时情况 + @Test + public void testWhen2() { + assertNotTimeout("when2"); + } + + // 测试 FOR 的超时情况 + @Test + public void testFor1() { + assertTimeout("for1"); + } + + // 测试 FOR 的非超时情况 + @Test + public void testFor2() { + assertNotTimeout("for2"); + } + + // 测试 WHILE 的超时情况 + @Test + public void testWhile1() { + assertTimeout("while1"); + } + + // 测试 WHILE 的非超时情况 + @Test + public void testWhile2() { + assertNotTimeout("while2"); + } + + // 测试 ITERATOR 的超时情况 + @Test + public void testIterator1() { + assertTimeout("iterator1"); + } + + // 测试 ITERATOR 的非超时情况 + @Test + public void testIterator2() { + assertNotTimeout("iterator2"); + } + + // 测试 SWITCH 的超时情况 + @Test + public void testSwitch1() { + assertTimeout("switch1"); + } + + // 测试 SWITCH 的非超时情况 + @Test + public void testSwitch2() { + assertNotTimeout("switch2"); + } + + // 测试 IF 的超时情况 + @Test + public void testIf1() { + assertTimeout("if1"); + } + + // 测试 SWITCH 的非超时情况 + @Test + public void testIf2() { + assertNotTimeout("if2"); + } + + // 测试单个组件的超时情况 + @Test + public void testComponent1() { + assertTimeout("component1"); + } + + // 测试单个组件的非超时情况 + @Test + public void testComponent2() { + assertNotTimeout("component2"); + } + + // 测试 FINALLY,虽然超时,但 FINALLY 仍会执行 + @Test + public void testFinally1() { + LiteflowResponse response = flowExecutor.execute2Resp("finally", "arg"); + Assertions.assertFalse(response.isSuccess()); + Assertions.assertEquals(TimeoutException.class, response.getCause().getClass()); + // FINALLY 执行时在默认数据上下文中放入了 CONTENT_KEY + DefaultContext contextBean = response.getFirstContextBean(); + Assertions.assertTrue(contextBean.hasData(CONTENT_KEY)); + } + + // 测试 maxWaitMilliseconds 关键字不能作用于 Finally + @Test + public void testFinally2() { + Assertions.assertFalse(LiteFlowChainELBuilder.validate("THEN(a, b, FINALLY(c).maxWaitMilliseconds(100))")); + } + + // 测试 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"); + Assertions.assertFalse(response.isSuccess()); + Assertions.assertEquals(TimeoutException.class, response.getCause().getClass()); + } + + private void assertWhenTimeout(String chainId) { + LiteflowResponse response = flowExecutor.execute2Resp(chainId, "arg"); + Assertions.assertFalse(response.isSuccess()); + Assertions.assertEquals(WhenTimeoutException.class, response.getCause().getClass()); + } + + private void assertNotTimeout(String chainId) { + LiteflowResponse response = flowExecutor.execute2Resp(chainId, "arg"); + Assertions.assertTrue(response.isSuccess()); + } +} diff --git a/liteflow-testcase-el/liteflow-testcase-el-declare-multi-springboot/src/test/java/com/yomahub/liteflow/test/maxWaitMilliseconds/cmp/CmpConfig.java b/liteflow-testcase-el/liteflow-testcase-el-declare-multi-springboot/src/test/java/com/yomahub/liteflow/test/maxWaitMilliseconds/cmp/CmpConfig.java new file mode 100644 index 000000000..2e2194dfc --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-declare-multi-springboot/src/test/java/com/yomahub/liteflow/test/maxWaitMilliseconds/cmp/CmpConfig.java @@ -0,0 +1,98 @@ +package com.yomahub.liteflow.test.maxWaitMilliseconds.cmp; + +import cn.hutool.core.collection.ListUtil; +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 com.yomahub.liteflow.slot.DefaultContext; + +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Set; + +@LiteflowComponent +public class CmpConfig { + + public static final String CONTENT_KEY = "testKey"; + + private int count = 0; + + // 执行过的 chain + Set executedChain = new HashSet<>(); + + @LiteflowMethod(value = LiteFlowMethodEnum.PROCESS, nodeId = "a") + public void processA(NodeComponent bindCmp) { + try { + Thread.sleep(100); + } catch (Exception e) { + e.printStackTrace(); + } + + System.out.println("ACmp executed!"); + } + + @LiteflowMethod(value = LiteFlowMethodEnum.PROCESS, nodeId = "b") + public void processB(NodeComponent bindCmp) { + try { + Thread.sleep(200); + } catch (Exception e) { + e.printStackTrace(); + } + + System.out.println("BCmp executed!"); + } + + @LiteflowMethod(value = LiteFlowMethodEnum.PROCESS, nodeId = "c") + public void process(NodeComponent bindCmp) { + try { + Thread.sleep(500); + } catch (Exception e) { + e.printStackTrace(); + } + + System.out.println("CCmp executed!"); + } + + @LiteflowMethod(value = LiteFlowMethodEnum.PROCESS, nodeId = "d") + public void processD(NodeComponent bindCmp) { + try { + Thread.sleep(500); + DefaultContext contextBean = bindCmp.getFirstContextBean(); + contextBean.setData(CONTENT_KEY, "value"); + } catch (Exception e) { + e.printStackTrace(); + } + + System.out.println("DCmp executed!"); + } + + @LiteflowMethod(value = LiteFlowMethodEnum.PROCESS_IF, nodeId = "f", nodeType = NodeTypeEnum.IF) + public boolean processIf(NodeComponent bindCmp) throws Exception { + return true; + } + + @LiteflowMethod(value = LiteFlowMethodEnum.PROCESS_SWITCH, nodeId = "s", nodeType = NodeTypeEnum.SWITCH) + public String processSwitch(NodeComponent bindCmp) throws Exception { + return "b"; + } + + @LiteflowMethod(value = LiteFlowMethodEnum.PROCESS_WHILE, nodeId = "w", nodeType = NodeTypeEnum.WHILE) + public boolean processWhile(NodeComponent bindCmp) throws Exception { + // 判断是否切换了 chain + if (!executedChain.contains(bindCmp.getCurrChainId())) { + count = 0; + executedChain.add(bindCmp.getCurrChainId()); + } + count++; + return count <= 2; + } + + @LiteflowMethod(value = LiteFlowMethodEnum.PROCESS_ITERATOR, nodeId = "x", nodeType = NodeTypeEnum.ITERATOR) + public Iterator processIterator(NodeComponent bindCmp) throws Exception { + List list = ListUtil.toList("one", "two"); + return list.iterator(); + } +} diff --git a/liteflow-testcase-el/liteflow-testcase-el-declare-multi-springboot/src/test/resources/maxWaitMilliseconds/application.properties b/liteflow-testcase-el/liteflow-testcase-el-declare-multi-springboot/src/test/resources/maxWaitMilliseconds/application.properties new file mode 100644 index 000000000..678dc827e --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-declare-multi-springboot/src/test/resources/maxWaitMilliseconds/application.properties @@ -0,0 +1 @@ +liteflow.rule-source=maxWaitMilliseconds/flow.el.xml \ No newline at end of file diff --git a/liteflow-testcase-el/liteflow-testcase-el-declare-multi-springboot/src/test/resources/maxWaitMilliseconds/flow.el.xml b/liteflow-testcase-el/liteflow-testcase-el-declare-multi-springboot/src/test/resources/maxWaitMilliseconds/flow.el.xml new file mode 100644 index 000000000..13ead3d38 --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-declare-multi-springboot/src/test/resources/maxWaitMilliseconds/flow.el.xml @@ -0,0 +1,110 @@ + + + + + + + THEN(a,b).maxWaitMilliseconds(200); + + + + THEN(a,b).maxWaitMilliseconds(500); + + + + + + WHEN(a,c).maxWaitMilliseconds(300); + + + + WHEN(a,b).maxWaitMilliseconds(300); + + + + + + FOR(2).DO(a).maxWaitMilliseconds(100); + + + + FOR(2).DO(a).maxWaitMilliseconds(300); + + + + + WHILE(w).DO(a).maxWaitMilliseconds(100); + + + + WHILE(w).DO(a).maxWaitMilliseconds(300); + + + + + ITERATOR(x).DO(a).maxWaitMilliseconds(100); + + + + ITERATOR(x).DO(a).maxWaitMilliseconds(300); + + + + + + + SWITCH(s).TO(a, b).maxWaitMilliseconds(100); + + + + SWITCH(s).TO(a, b).maxWaitMilliseconds(300); + + + + + + + IF(f, b, c).maxWaitMilliseconds(100); + + + + IF(f, b, c).maxWaitMilliseconds(300); + + + + + + WHEN( + a.maxWaitMilliseconds(200), + c.maxWaitMilliseconds(300) + ); + + + + WHEN( + a.maxWaitMilliseconds(200), + b.maxWaitMilliseconds(300) + ); + + + + + + THEN(PRE(a), b, FINALLY(d)).maxWaitMilliseconds(200); + + + + + THEN(b) + + + + testChain.maxWaitMilliseconds(100); + + + + testChain.maxWaitMilliseconds(300); + + \ No newline at end of file diff --git a/liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/java/com/yomahub/liteflow/test/maxWaitMilliseconds/MaxWaitMillisecondsELDeclSpringbootTest.java b/liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/java/com/yomahub/liteflow/test/maxWaitMilliseconds/MaxWaitMillisecondsELDeclSpringbootTest.java new file mode 100644 index 000000000..61b5f4234 --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/java/com/yomahub/liteflow/test/maxWaitMilliseconds/MaxWaitMillisecondsELDeclSpringbootTest.java @@ -0,0 +1,204 @@ +package com.yomahub.liteflow.test.maxWaitMilliseconds; + +import com.yomahub.liteflow.builder.LiteFlowNodeBuilder; +import com.yomahub.liteflow.builder.el.LiteFlowChainELBuilder; +import com.yomahub.liteflow.core.FlowExecutor; +import com.yomahub.liteflow.enums.NodeTypeEnum; +import com.yomahub.liteflow.exception.WhenTimeoutException; +import com.yomahub.liteflow.flow.LiteflowResponse; +import com.yomahub.liteflow.slot.DefaultContext; +import com.yomahub.liteflow.test.BaseTest; +import com.yomahub.liteflow.test.maxWaitMilliseconds.cmp.ACmp; +import com.yomahub.liteflow.test.maxWaitMilliseconds.cmp.BCmp; +import com.yomahub.liteflow.test.maxWaitMilliseconds.cmp.CCmp; +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.util.concurrent.TimeoutException; + +import static com.yomahub.liteflow.test.maxWaitSeconds.cmp.DCmp.CONTENT_KEY; + +/** + * Spring Boot 环境下超时控制测试 - maxWaitMilliseconds + * + * @author Kugaaa + * @since 2.11.1 + */ +@ExtendWith(SpringExtension.class) +@TestPropertySource(value = "classpath:/maxWaitMilliseconds/application.properties") +@SpringBootTest(classes = MaxWaitMillisecondsELDeclSpringbootTest.class) +@EnableAutoConfiguration +@ComponentScan({"com.yomahub.liteflow.test.maxWaitMilliseconds.cmp"}) +public class MaxWaitMillisecondsELDeclSpringbootTest extends BaseTest { + + @Resource + private FlowExecutor flowExecutor; + + // 测试 THEN 的超时情况 + @Test + public void testThen1() { + assertTimeout("then1"); + } + + // 测试 THEN 的非超时情况 + @Test + public void testThen2() { + assertNotTimeout("then2"); + } + + // 测试 When 的超时情况 + @Test + public void testWhen1() { + // WHEN 抛出的是 WhenTimeoutException + assertWhenTimeout("when1"); + } + + // 测试 WHEN 的非超时情况 + @Test + public void testWhen2() { + assertNotTimeout("when2"); + } + + // 测试 FOR 的超时情况 + @Test + public void testFor1() { + assertTimeout("for1"); + } + + // 测试 FOR 的非超时情况 + @Test + public void testFor2() { + assertNotTimeout("for2"); + } + + // 测试 WHILE 的超时情况 + @Test + public void testWhile1() { + assertTimeout("while1"); + } + + // 测试 WHILE 的非超时情况 + @Test + public void testWhile2() { + assertNotTimeout("while2"); + } + + // 测试 ITERATOR 的超时情况 + @Test + public void testIterator1() { + assertTimeout("iterator1"); + } + + // 测试 ITERATOR 的非超时情况 + @Test + public void testIterator2() { + assertNotTimeout("iterator2"); + } + + // 测试 SWITCH 的超时情况 + @Test + public void testSwitch1() { + assertTimeout("switch1"); + } + + // 测试 SWITCH 的非超时情况 + @Test + public void testSwitch2() { + assertNotTimeout("switch2"); + } + + // 测试 IF 的超时情况 + @Test + public void testIf1() { + assertTimeout("if1"); + } + + // 测试 SWITCH 的非超时情况 + @Test + public void testIf2() { + assertNotTimeout("if2"); + } + + // 测试单个组件的超时情况 + @Test + public void testComponent1() { + assertTimeout("component1"); + } + + // 测试单个组件的非超时情况 + @Test + public void testComponent2() { + assertNotTimeout("component2"); + } + + // 测试 FINALLY,虽然超时,但 FINALLY 仍会执行 + @Test + public void testFinally1() { + LiteflowResponse response = flowExecutor.execute2Resp("finally", "arg"); + Assertions.assertFalse(response.isSuccess()); + Assertions.assertEquals(TimeoutException.class, response.getCause().getClass()); + // FINALLY 执行时在默认数据上下文中放入了 CONTENT_KEY + DefaultContext contextBean = response.getFirstContextBean(); + Assertions.assertTrue(contextBean.hasData(CONTENT_KEY)); + } + + // 测试 maxWaitMilliseconds 关键字不能作用于 Finally + @Test + public void testFinally2() { + LiteFlowNodeBuilder.createNode() + .setId("a") + .setName("组件A") + .setType(NodeTypeEnum.COMMON) + .setClazz(ACmp.class) + .build(); + LiteFlowNodeBuilder.createNode() + .setId("b") + .setName("组件B") + .setType(NodeTypeEnum.COMMON) + .setClazz(BCmp.class) + .build(); + LiteFlowNodeBuilder.createNode() + .setId("c") + .setName("组件C") + .setType(NodeTypeEnum.COMMON) + .setClazz(CCmp.class) + .build(); + Assertions.assertFalse(LiteFlowChainELBuilder.validate("THEN(a, b, FINALLY(c).maxWaitMilliseconds(100))")); + } + + // 测试 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"); + Assertions.assertFalse(response.isSuccess()); + Assertions.assertEquals(TimeoutException.class, response.getCause().getClass()); + } + + private void assertWhenTimeout(String chainId) { + LiteflowResponse response = flowExecutor.execute2Resp(chainId, "arg"); + Assertions.assertFalse(response.isSuccess()); + Assertions.assertEquals(WhenTimeoutException.class, response.getCause().getClass()); + } + + private void assertNotTimeout(String chainId) { + LiteflowResponse response = flowExecutor.execute2Resp(chainId, "arg"); + Assertions.assertTrue(response.isSuccess()); + } +} diff --git a/liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/java/com/yomahub/liteflow/test/maxWaitMilliseconds/cmp/ACmp.java b/liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/java/com/yomahub/liteflow/test/maxWaitMilliseconds/cmp/ACmp.java new file mode 100644 index 000000000..52bc5fe1f --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/java/com/yomahub/liteflow/test/maxWaitMilliseconds/cmp/ACmp.java @@ -0,0 +1,21 @@ +package com.yomahub.liteflow.test.maxWaitMilliseconds.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) { + try { + Thread.sleep(100); + } catch (Exception e) { + e.printStackTrace(); + } + + System.out.println("ACmp executed!"); + } +} diff --git a/liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/java/com/yomahub/liteflow/test/maxWaitMilliseconds/cmp/BCmp.java b/liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/java/com/yomahub/liteflow/test/maxWaitMilliseconds/cmp/BCmp.java new file mode 100644 index 000000000..9bf05392a --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/java/com/yomahub/liteflow/test/maxWaitMilliseconds/cmp/BCmp.java @@ -0,0 +1,21 @@ +package com.yomahub.liteflow.test.maxWaitMilliseconds.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) { + try { + Thread.sleep(200); + } catch (Exception e) { + e.printStackTrace(); + } + + System.out.println("BCmp executed!"); + } +} diff --git a/liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/java/com/yomahub/liteflow/test/maxWaitMilliseconds/cmp/CCmp.java b/liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/java/com/yomahub/liteflow/test/maxWaitMilliseconds/cmp/CCmp.java new file mode 100644 index 000000000..5bb5225fc --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/java/com/yomahub/liteflow/test/maxWaitMilliseconds/cmp/CCmp.java @@ -0,0 +1,21 @@ +package com.yomahub.liteflow.test.maxWaitMilliseconds.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("c") +public class CCmp { + + @LiteflowMethod(LiteFlowMethodEnum.PROCESS) + public void process(NodeComponent bindCmp) { + try { + Thread.sleep(500); + } catch (Exception e) { + e.printStackTrace(); + } + + System.out.println("CCmp executed!"); + } +} diff --git a/liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/java/com/yomahub/liteflow/test/maxWaitMilliseconds/cmp/DCmp.java b/liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/java/com/yomahub/liteflow/test/maxWaitMilliseconds/cmp/DCmp.java new file mode 100644 index 000000000..b844e256c --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/java/com/yomahub/liteflow/test/maxWaitMilliseconds/cmp/DCmp.java @@ -0,0 +1,26 @@ +package com.yomahub.liteflow.test.maxWaitMilliseconds.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; +import com.yomahub.liteflow.slot.DefaultContext; + +@LiteflowComponent("d") +public class DCmp { + + public static final String CONTENT_KEY = "testKey"; + + @LiteflowMethod(LiteFlowMethodEnum.PROCESS) + public void process(NodeComponent bindCmp) { + try { + Thread.sleep(500); + DefaultContext contextBean = bindCmp.getFirstContextBean(); + contextBean.setData(CONTENT_KEY, "value"); + } catch (Exception e) { + e.printStackTrace(); + } + + System.out.println("DCmp executed!"); + } +} diff --git a/liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/java/com/yomahub/liteflow/test/maxWaitMilliseconds/cmp/FCmp.java b/liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/java/com/yomahub/liteflow/test/maxWaitMilliseconds/cmp/FCmp.java new file mode 100644 index 000000000..652e2e682 --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/java/com/yomahub/liteflow/test/maxWaitMilliseconds/cmp/FCmp.java @@ -0,0 +1,18 @@ +package com.yomahub.liteflow.test.maxWaitMilliseconds.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("f") +@LiteflowCmpDefine(NodeTypeEnum.IF) +public class FCmp { + + @LiteflowMethod(value = LiteFlowMethodEnum.PROCESS_IF, nodeType = NodeTypeEnum.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/maxWaitMilliseconds/cmp/SCmp.java b/liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/java/com/yomahub/liteflow/test/maxWaitMilliseconds/cmp/SCmp.java new file mode 100644 index 000000000..68c7a1775 --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/java/com/yomahub/liteflow/test/maxWaitMilliseconds/cmp/SCmp.java @@ -0,0 +1,18 @@ +package com.yomahub.liteflow.test.maxWaitMilliseconds.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("s") +@LiteflowCmpDefine(NodeTypeEnum.SWITCH) +public class SCmp { + + @LiteflowMethod(value = LiteFlowMethodEnum.PROCESS_SWITCH, nodeType = NodeTypeEnum.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/maxWaitMilliseconds/cmp/WCmp.java b/liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/java/com/yomahub/liteflow/test/maxWaitMilliseconds/cmp/WCmp.java new file mode 100644 index 000000000..4809d114c --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/java/com/yomahub/liteflow/test/maxWaitMilliseconds/cmp/WCmp.java @@ -0,0 +1,31 @@ +package com.yomahub.liteflow.test.maxWaitMilliseconds.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("w") +@LiteflowCmpDefine(NodeTypeEnum.WHILE) +public class WCmp { + private int count = 0; + + // 执行过的 chain + Set executedChain = new HashSet<>(); + + @LiteflowMethod(value = LiteFlowMethodEnum.PROCESS_WHILE, nodeType = NodeTypeEnum.WHILE) + public boolean processWhile(NodeComponent bindCmp) throws Exception { + // 判断是否切换了 chain + if (!executedChain.contains(bindCmp.getCurrChainId())) { + count = 0; + executedChain.add(bindCmp.getCurrChainId()); + } + count++; + return count <= 2; + } +} diff --git a/liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/java/com/yomahub/liteflow/test/maxWaitMilliseconds/cmp/XCmp.java b/liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/java/com/yomahub/liteflow/test/maxWaitMilliseconds/cmp/XCmp.java new file mode 100644 index 000000000..a25d33cdb --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/java/com/yomahub/liteflow/test/maxWaitMilliseconds/cmp/XCmp.java @@ -0,0 +1,23 @@ +package com.yomahub.liteflow.test.maxWaitMilliseconds.cmp; + +import cn.hutool.core.collection.ListUtil; +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.Iterator; +import java.util.List; + +@LiteflowComponent("x") +@LiteflowCmpDefine(NodeTypeEnum.ITERATOR) +public class XCmp { + + @LiteflowMethod(value = LiteFlowMethodEnum.PROCESS_ITERATOR, nodeType = NodeTypeEnum.ITERATOR) + public Iterator processIterator(NodeComponent bindCmp) throws Exception { + List list = ListUtil.toList("one", "two"); + return list.iterator(); + } +} diff --git a/liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/resources/maxWaitMilliseconds/application.properties b/liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/resources/maxWaitMilliseconds/application.properties new file mode 100644 index 000000000..678dc827e --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/resources/maxWaitMilliseconds/application.properties @@ -0,0 +1 @@ +liteflow.rule-source=maxWaitMilliseconds/flow.el.xml \ No newline at end of file diff --git a/liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/resources/maxWaitMilliseconds/flow.el.xml b/liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/resources/maxWaitMilliseconds/flow.el.xml new file mode 100644 index 000000000..13ead3d38 --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/resources/maxWaitMilliseconds/flow.el.xml @@ -0,0 +1,110 @@ + + + + + + + THEN(a,b).maxWaitMilliseconds(200); + + + + THEN(a,b).maxWaitMilliseconds(500); + + + + + + WHEN(a,c).maxWaitMilliseconds(300); + + + + WHEN(a,b).maxWaitMilliseconds(300); + + + + + + FOR(2).DO(a).maxWaitMilliseconds(100); + + + + FOR(2).DO(a).maxWaitMilliseconds(300); + + + + + WHILE(w).DO(a).maxWaitMilliseconds(100); + + + + WHILE(w).DO(a).maxWaitMilliseconds(300); + + + + + ITERATOR(x).DO(a).maxWaitMilliseconds(100); + + + + ITERATOR(x).DO(a).maxWaitMilliseconds(300); + + + + + + + SWITCH(s).TO(a, b).maxWaitMilliseconds(100); + + + + SWITCH(s).TO(a, b).maxWaitMilliseconds(300); + + + + + + + IF(f, b, c).maxWaitMilliseconds(100); + + + + IF(f, b, c).maxWaitMilliseconds(300); + + + + + + WHEN( + a.maxWaitMilliseconds(200), + c.maxWaitMilliseconds(300) + ); + + + + WHEN( + a.maxWaitMilliseconds(200), + b.maxWaitMilliseconds(300) + ); + + + + + + THEN(PRE(a), b, FINALLY(d)).maxWaitMilliseconds(200); + + + + + THEN(b) + + + + testChain.maxWaitMilliseconds(100); + + + + testChain.maxWaitMilliseconds(300); + + \ No newline at end of file diff --git a/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/java/com/yomahub/liteflow/test/maxWaitMilliseconds/MaxWaitMillisecondsTest.java b/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/java/com/yomahub/liteflow/test/maxWaitMilliseconds/MaxWaitMillisecondsTest.java new file mode 100644 index 000000000..55ca1e8a5 --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/java/com/yomahub/liteflow/test/maxWaitMilliseconds/MaxWaitMillisecondsTest.java @@ -0,0 +1,202 @@ +package com.yomahub.liteflow.test.maxWaitMilliseconds; + +import com.yomahub.liteflow.builder.LiteFlowNodeBuilder; +import com.yomahub.liteflow.builder.el.LiteFlowChainELBuilder; +import com.yomahub.liteflow.core.FlowExecutor; +import com.yomahub.liteflow.core.FlowExecutorHolder; +import com.yomahub.liteflow.enums.NodeTypeEnum; +import com.yomahub.liteflow.exception.WhenTimeoutException; +import com.yomahub.liteflow.flow.LiteflowResponse; +import com.yomahub.liteflow.property.LiteflowConfig; +import com.yomahub.liteflow.slot.DefaultContext; +import com.yomahub.liteflow.test.BaseTest; +import com.yomahub.liteflow.test.maxWaitSeconds.cmp.ACmp; +import com.yomahub.liteflow.test.maxWaitSeconds.cmp.BCmp; +import com.yomahub.liteflow.test.maxWaitSeconds.cmp.CCmp; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; + +import java.util.concurrent.TimeoutException; + +import static com.yomahub.liteflow.test.maxWaitSeconds.cmp.DCmp.CONTENT_KEY; + +/** + * 非 Spring 环境下超时控制测试 + * + * @author Kugaaa + * @since 2.11.1 + */ +public class MaxWaitMillisecondsTest extends BaseTest { + + private static FlowExecutor flowExecutor; + + @BeforeAll + public static void init() { + LiteflowConfig config = new LiteflowConfig(); + config.setRuleSource("maxWaitMilliseconds/flow.el.xml"); + flowExecutor = FlowExecutorHolder.loadInstance(config); + } + + // 测试 THEN 的超时情况 + @Test + public void testThen1() { + assertTimeout("then1"); + } + + // 测试 THEN 的非超时情况 + @Test + public void testThen2() { + assertNotTimeout("then2"); + } + + // 测试 When 的超时情况 + @Test + public void testWhen1() { + assertWhenTimeout("when1"); + } + + // 测试 WHEN 的非超时情况 + @Test + public void testWhen2() { + assertNotTimeout("when2"); + } + + // 测试 FOR 的超时情况 + @Test + public void testFor1() { + assertTimeout("for1"); + } + + // 测试 FOR 的非超时情况 + @Test + public void testFor2() { + assertNotTimeout("for2"); + } + + // 测试 WHILE 的超时情况 + @Test + public void testWhile1() { + assertTimeout("while1"); + } + + // 测试 WHILE 的非超时情况 + @Test + public void testWhile2() { + assertNotTimeout("while2"); + } + + // 测试 ITERATOR 的超时情况 + @Test + public void testIterator1() { + assertTimeout("iterator1"); + } + + // 测试 ITERATOR 的非超时情况 + @Test + public void testIterator2() { + assertNotTimeout("iterator2"); + } + + // 测试 SWITCH 的超时情况 + @Test + public void testSwitch1() { + assertTimeout("switch1"); + } + + // 测试 SWITCH 的非超时情况 + @Test + public void testSwitch2() { + assertNotTimeout("switch2"); + } + + // 测试 IF 的超时情况 + @Test + public void testIf1() { + assertTimeout("if1"); + } + + // 测试 SWITCH 的非超时情况 + @Test + public void testIf2() { + assertNotTimeout("if2"); + } + + // 测试单个组件的超时情况 + @Test + public void testComponent1() { + assertTimeout("component1"); + } + + // 测试单个组件的非超时情况 + @Test + public void testComponent2() { + assertNotTimeout("component2"); + } + + // 测试 FINALLY,虽然超时,但 FINALLY 仍会执行 + @Test + public void testFinally1() { + LiteflowResponse response = flowExecutor.execute2Resp("finally", "arg"); + Assertions.assertFalse(response.isSuccess()); + Assertions.assertEquals(TimeoutException.class, response.getCause().getClass()); + // FINALLY 执行时在默认数据上下文中放入了 CONTENT_KEY + DefaultContext contextBean = response.getFirstContextBean(); + Assertions.assertTrue(contextBean.hasData(CONTENT_KEY)); + + } + + // 测试 maxWaitMilliseconds 关键字不能作用于 Finally + @Test + public void testFinally2() { + LiteFlowNodeBuilder.createNode() + .setId("a") + .setName("组件A") + .setType(NodeTypeEnum.COMMON) + .setClazz(ACmp.class) + .build(); + LiteFlowNodeBuilder.createNode() + .setId("b") + .setName("组件B") + .setType(NodeTypeEnum.COMMON) + .setClazz(BCmp.class) + .build(); + LiteFlowNodeBuilder.createNode() + .setId("c") + .setName("组件C") + .setType(NodeTypeEnum.COMMON) + .setClazz(CCmp.class) + .build(); + Assertions.assertFalse(LiteFlowChainELBuilder.validate("THEN(a, b, FINALLY(c).maxWaitMilliseconds(100))")); + } + + // 测试 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"); + Assertions.assertFalse(response.isSuccess()); + Assertions.assertEquals(TimeoutException.class, response.getCause().getClass()); + } + + private void assertWhenTimeout(String chainId) { + LiteflowResponse response = flowExecutor.execute2Resp(chainId, "arg"); + Assertions.assertFalse(response.isSuccess()); + Assertions.assertEquals(WhenTimeoutException.class, response.getCause().getClass()); + } + + private void assertNotTimeout(String chainId) { + LiteflowResponse response = flowExecutor.execute2Resp(chainId, "arg"); + Assertions.assertTrue(response.isSuccess()); + } + +} diff --git a/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/java/com/yomahub/liteflow/test/maxWaitMilliseconds/cmp/ACmp.java b/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/java/com/yomahub/liteflow/test/maxWaitMilliseconds/cmp/ACmp.java new file mode 100644 index 000000000..a45dd7b41 --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/java/com/yomahub/liteflow/test/maxWaitMilliseconds/cmp/ACmp.java @@ -0,0 +1,16 @@ +package com.yomahub.liteflow.test.maxWaitMilliseconds.cmp; + +import com.yomahub.liteflow.core.NodeComponent; + +public class ACmp extends NodeComponent { + @Override + public void process() { + try { + Thread.sleep(100); + } catch (Exception e) { + e.printStackTrace(); + } + + System.out.println("ACmp executed!"); + } +} diff --git a/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/java/com/yomahub/liteflow/test/maxWaitMilliseconds/cmp/BCmp.java b/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/java/com/yomahub/liteflow/test/maxWaitMilliseconds/cmp/BCmp.java new file mode 100644 index 000000000..76de9997c --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/java/com/yomahub/liteflow/test/maxWaitMilliseconds/cmp/BCmp.java @@ -0,0 +1,16 @@ +package com.yomahub.liteflow.test.maxWaitMilliseconds.cmp; + +import com.yomahub.liteflow.core.NodeComponent; + +public class BCmp extends NodeComponent { + @Override + public void process() { + try { + Thread.sleep(200); + } catch (Exception e) { + e.printStackTrace(); + } + + System.out.println("BCmp executed!"); + } +} diff --git a/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/java/com/yomahub/liteflow/test/maxWaitMilliseconds/cmp/CCmp.java b/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/java/com/yomahub/liteflow/test/maxWaitMilliseconds/cmp/CCmp.java new file mode 100644 index 000000000..f44a0849e --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/java/com/yomahub/liteflow/test/maxWaitMilliseconds/cmp/CCmp.java @@ -0,0 +1,16 @@ +package com.yomahub.liteflow.test.maxWaitMilliseconds.cmp; + +import com.yomahub.liteflow.core.NodeComponent; + +public class CCmp extends NodeComponent { + @Override + public void process() { + try { + Thread.sleep(500); + } catch (Exception e) { + e.printStackTrace(); + } + + System.out.println("CCmp executed!"); + } +} diff --git a/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/java/com/yomahub/liteflow/test/maxWaitMilliseconds/cmp/DCmp.java b/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/java/com/yomahub/liteflow/test/maxWaitMilliseconds/cmp/DCmp.java new file mode 100644 index 000000000..164a20e83 --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/java/com/yomahub/liteflow/test/maxWaitMilliseconds/cmp/DCmp.java @@ -0,0 +1,23 @@ +package com.yomahub.liteflow.test.maxWaitMilliseconds.cmp; + +import com.yomahub.liteflow.core.NodeComponent; +import com.yomahub.liteflow.slot.DefaultContext; + + +public class DCmp extends NodeComponent { + + public static final String CONTENT_KEY = "testKey"; + + @Override + public void process() { + try { + Thread.sleep(500); + DefaultContext contextBean = this.getFirstContextBean(); + contextBean.setData(CONTENT_KEY, "value"); + } catch (Exception e) { + e.printStackTrace(); + } + + System.out.println("DCmp executed!"); + } +} diff --git a/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/java/com/yomahub/liteflow/test/maxWaitMilliseconds/cmp/FCmp.java b/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/java/com/yomahub/liteflow/test/maxWaitMilliseconds/cmp/FCmp.java new file mode 100644 index 000000000..8b003e024 --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/java/com/yomahub/liteflow/test/maxWaitMilliseconds/cmp/FCmp.java @@ -0,0 +1,10 @@ +package com.yomahub.liteflow.test.maxWaitMilliseconds.cmp; + +import com.yomahub.liteflow.core.NodeIfComponent; + +public class FCmp 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/maxWaitMilliseconds/cmp/SCmp.java b/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/java/com/yomahub/liteflow/test/maxWaitMilliseconds/cmp/SCmp.java new file mode 100644 index 000000000..f64720ec5 --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/java/com/yomahub/liteflow/test/maxWaitMilliseconds/cmp/SCmp.java @@ -0,0 +1,11 @@ +package com.yomahub.liteflow.test.maxWaitMilliseconds.cmp; + +import com.yomahub.liteflow.core.NodeSwitchComponent; + +public class SCmp 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/maxWaitMilliseconds/cmp/WCmp.java b/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/java/com/yomahub/liteflow/test/maxWaitMilliseconds/cmp/WCmp.java new file mode 100644 index 000000000..3f0c50cc2 --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/java/com/yomahub/liteflow/test/maxWaitMilliseconds/cmp/WCmp.java @@ -0,0 +1,24 @@ +package com.yomahub.liteflow.test.maxWaitMilliseconds.cmp; + +import com.yomahub.liteflow.core.NodeWhileComponent; + +import java.util.HashSet; +import java.util.Set; + +public class WCmp 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 <= 2; + } +} diff --git a/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/java/com/yomahub/liteflow/test/maxWaitMilliseconds/cmp/XCmp.java b/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/java/com/yomahub/liteflow/test/maxWaitMilliseconds/cmp/XCmp.java new file mode 100644 index 000000000..4abe35cbe --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/java/com/yomahub/liteflow/test/maxWaitMilliseconds/cmp/XCmp.java @@ -0,0 +1,15 @@ +package com.yomahub.liteflow.test.maxWaitMilliseconds.cmp; + +import cn.hutool.core.collection.ListUtil; +import com.yomahub.liteflow.core.NodeIteratorComponent; + +import java.util.Iterator; +import java.util.List; + +public class XCmp extends NodeIteratorComponent { + @Override + public Iterator processIterator() throws Exception { + List list = ListUtil.toList("one", "two"); + return list.iterator(); + } +} diff --git a/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/resources/maxWaitMilliseconds/flow.el.xml b/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/resources/maxWaitMilliseconds/flow.el.xml new file mode 100644 index 000000000..fdd055cb6 --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/resources/maxWaitMilliseconds/flow.el.xml @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + THEN(a,b).maxWaitMilliseconds(200); + + + + THEN(a,b).maxWaitMilliseconds(500); + + + + + + WHEN(a,c).maxWaitMilliseconds(300); + + + + WHEN(a,b).maxWaitMilliseconds(300); + + + + + + FOR(2).DO(a).maxWaitMilliseconds(100); + + + + FOR(2).DO(a).maxWaitMilliseconds(300); + + + + + WHILE(w).DO(a).maxWaitMilliseconds(100); + + + + WHILE(w).DO(a).maxWaitMilliseconds(300); + + + + + ITERATOR(x).DO(a).maxWaitMilliseconds(100); + + + + ITERATOR(x).DO(a).maxWaitMilliseconds(300); + + + + + + + SWITCH(s).TO(a, b).maxWaitMilliseconds(100); + + + + SWITCH(s).TO(a, b).maxWaitMilliseconds(300); + + + + + + + IF(f, b, c).maxWaitMilliseconds(100); + + + + IF(f, b, c).maxWaitMilliseconds(300); + + + + + + WHEN( + a.maxWaitMilliseconds(200), + c.maxWaitMilliseconds(300) + ); + + + + WHEN( + a.maxWaitMilliseconds(200), + b.maxWaitMilliseconds(300) + ); + + + + + + THEN(PRE(a), b, FINALLY(d)).maxWaitMilliseconds(200); + + + + + THEN(b) + + + + testChain.maxWaitMilliseconds(100); + + + + testChain.maxWaitMilliseconds(300); + + \ No newline at end of file diff --git a/liteflow-testcase-el/liteflow-testcase-el-solon/src/test/java/com/yomahub/liteflow/test/maxWaitMilliseconds/MaxWaitMillisecondsSolonTest.java b/liteflow-testcase-el/liteflow-testcase-el-solon/src/test/java/com/yomahub/liteflow/test/maxWaitMilliseconds/MaxWaitMillisecondsSolonTest.java new file mode 100644 index 000000000..d246c786b --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-solon/src/test/java/com/yomahub/liteflow/test/maxWaitMilliseconds/MaxWaitMillisecondsSolonTest.java @@ -0,0 +1,198 @@ +package com.yomahub.liteflow.test.maxWaitMilliseconds; + +import com.yomahub.liteflow.builder.LiteFlowNodeBuilder; +import com.yomahub.liteflow.builder.el.LiteFlowChainELBuilder; +import com.yomahub.liteflow.core.FlowExecutor; +import com.yomahub.liteflow.enums.NodeTypeEnum; +import com.yomahub.liteflow.exception.WhenTimeoutException; +import com.yomahub.liteflow.flow.LiteflowResponse; +import com.yomahub.liteflow.slot.DefaultContext; +import com.yomahub.liteflow.test.BaseTest; +import com.yomahub.liteflow.test.maxWaitSeconds.cmp.ACmp; +import com.yomahub.liteflow.test.maxWaitSeconds.cmp.BCmp; +import com.yomahub.liteflow.test.maxWaitSeconds.cmp.CCmp; +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.TimeoutException; + +import static com.yomahub.liteflow.test.maxWaitSeconds.cmp.DCmp.CONTENT_KEY; + +/** + * Solon 环境下超时控制测试 - maxWaitMilliseconds + * + * @author Kugaaa + * @since 2.11.1 + */ +@ExtendWith(SolonJUnit5Extension.class) +@TestPropertySource("classpath:/maxWaitMilliseconds/application.properties") +public class MaxWaitMillisecondsSolonTest extends BaseTest { + + @Inject + private FlowExecutor flowExecutor; + + // 测试 THEN 的超时情况 + @Test + public void testThen1() { + assertTimeout("then1"); + } + + // 测试 THEN 的非超时情况 + @Test + public void testThen2() { + assertNotTimeout("then2"); + } + + // 测试 When 的超时情况 + @Test + public void testWhen1() { + assertWhenTimeout("when1"); + } + + // 测试 WHEN 的非超时情况 + @Test + public void testWhen2() { + assertNotTimeout("when2"); + } + + // 测试 FOR 的超时情况 + @Test + public void testFor1() { + assertTimeout("for1"); + } + + // 测试 FOR 的非超时情况 + @Test + public void testFor2() { + assertNotTimeout("for2"); + } + + // 测试 WHILE 的超时情况 + @Test + public void testWhile1() { + assertTimeout("while1"); + } + + // 测试 WHILE 的非超时情况 + @Test + public void testWhile2() { + assertNotTimeout("while2"); + } + + // 测试 ITERATOR 的超时情况 + @Test + public void testIterator1() { + assertTimeout("iterator1"); + } + + // 测试 ITERATOR 的非超时情况 + @Test + public void testIterator2() { + assertNotTimeout("iterator2"); + } + + // 测试 SWITCH 的超时情况 + @Test + public void testSwitch1() { + assertTimeout("switch1"); + } + + // 测试 SWITCH 的非超时情况 + @Test + public void testSwitch2() { + assertNotTimeout("switch2"); + } + + // 测试 IF 的超时情况 + @Test + public void testIf1() { + assertTimeout("if1"); + } + + // 测试 SWITCH 的非超时情况 + @Test + public void testIf2() { + assertNotTimeout("if2"); + } + + // 测试单个组件的超时情况 + @Test + public void testComponent1() { + assertTimeout("component1"); + } + + // 测试单个组件的非超时情况 + @Test + public void testComponent2() { + assertNotTimeout("component2"); + } + + // 测试 FINALLY,虽然超时,但 FINALLY 仍会执行 + @Test + public void testFinally1() { + LiteflowResponse response = flowExecutor.execute2Resp("finally", "arg"); + Assertions.assertFalse(response.isSuccess()); + Assertions.assertEquals(TimeoutException.class, response.getCause().getClass()); + // FINALLY 执行时在默认数据上下文中放入了 CONTENT_KEY + DefaultContext contextBean = response.getFirstContextBean(); + Assertions.assertTrue(contextBean.hasData(CONTENT_KEY)); + + } + + // 测试 maxWaitMilliseconds 关键字不能作用于 Finally + @Test + public void testFinally2() { + LiteFlowNodeBuilder.createNode() + .setId("a") + .setName("组件A") + .setType(NodeTypeEnum.COMMON) + .setClazz(ACmp.class) + .build(); + LiteFlowNodeBuilder.createNode() + .setId("b") + .setName("组件B") + .setType(NodeTypeEnum.COMMON) + .setClazz(BCmp.class) + .build(); + LiteFlowNodeBuilder.createNode() + .setId("c") + .setName("组件C") + .setType(NodeTypeEnum.COMMON) + .setClazz(CCmp.class) + .build(); + Assertions.assertFalse(LiteFlowChainELBuilder.validate("THEN(a, b, FINALLY(c).maxWaitMilliseconds(100))")); + } + + // 测试 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"); + Assertions.assertFalse(response.isSuccess()); + Assertions.assertEquals(TimeoutException.class, response.getCause().getClass()); + } + + private void assertWhenTimeout(String chainId) { + LiteflowResponse response = flowExecutor.execute2Resp(chainId, "arg"); + Assertions.assertFalse(response.isSuccess()); + Assertions.assertEquals(WhenTimeoutException.class, response.getCause().getClass()); + } + + private void assertNotTimeout(String chainId) { + LiteflowResponse response = flowExecutor.execute2Resp(chainId, "arg"); + Assertions.assertTrue(response.isSuccess()); + } +} diff --git a/liteflow-testcase-el/liteflow-testcase-el-solon/src/test/java/com/yomahub/liteflow/test/maxWaitMilliseconds/cmp/ACmp.java b/liteflow-testcase-el/liteflow-testcase-el-solon/src/test/java/com/yomahub/liteflow/test/maxWaitMilliseconds/cmp/ACmp.java new file mode 100644 index 000000000..0a92711c0 --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-solon/src/test/java/com/yomahub/liteflow/test/maxWaitMilliseconds/cmp/ACmp.java @@ -0,0 +1,18 @@ +package com.yomahub.liteflow.test.maxWaitMilliseconds.cmp; + +import com.yomahub.liteflow.annotation.LiteflowComponent; +import com.yomahub.liteflow.core.NodeComponent; + +@LiteflowComponent("a") +public class ACmp extends NodeComponent { + @Override + public void process() { + try { + Thread.sleep(100); + } catch (Exception e) { + e.printStackTrace(); + } + + System.out.println("ACmp executed!"); + } +} diff --git a/liteflow-testcase-el/liteflow-testcase-el-solon/src/test/java/com/yomahub/liteflow/test/maxWaitMilliseconds/cmp/BCmp.java b/liteflow-testcase-el/liteflow-testcase-el-solon/src/test/java/com/yomahub/liteflow/test/maxWaitMilliseconds/cmp/BCmp.java new file mode 100644 index 000000000..0eba389eb --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-solon/src/test/java/com/yomahub/liteflow/test/maxWaitMilliseconds/cmp/BCmp.java @@ -0,0 +1,18 @@ +package com.yomahub.liteflow.test.maxWaitMilliseconds.cmp; + +import com.yomahub.liteflow.annotation.LiteflowComponent; +import com.yomahub.liteflow.core.NodeComponent; + +@LiteflowComponent("b") +public class BCmp extends NodeComponent { + @Override + public void process() { + try { + Thread.sleep(200); + } catch (Exception e) { + e.printStackTrace(); + } + + System.out.println("BCmp executed!"); + } +} diff --git a/liteflow-testcase-el/liteflow-testcase-el-solon/src/test/java/com/yomahub/liteflow/test/maxWaitMilliseconds/cmp/CCmp.java b/liteflow-testcase-el/liteflow-testcase-el-solon/src/test/java/com/yomahub/liteflow/test/maxWaitMilliseconds/cmp/CCmp.java new file mode 100644 index 000000000..b6994f151 --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-solon/src/test/java/com/yomahub/liteflow/test/maxWaitMilliseconds/cmp/CCmp.java @@ -0,0 +1,18 @@ +package com.yomahub.liteflow.test.maxWaitMilliseconds.cmp; + +import com.yomahub.liteflow.annotation.LiteflowComponent; +import com.yomahub.liteflow.core.NodeComponent; + +@LiteflowComponent("c") +public class CCmp extends NodeComponent { + @Override + public void process() { + try { + Thread.sleep(500); + } catch (Exception e) { + e.printStackTrace(); + } + + System.out.println("CCmp executed!"); + } +} diff --git a/liteflow-testcase-el/liteflow-testcase-el-solon/src/test/java/com/yomahub/liteflow/test/maxWaitMilliseconds/cmp/DCmp.java b/liteflow-testcase-el/liteflow-testcase-el-solon/src/test/java/com/yomahub/liteflow/test/maxWaitMilliseconds/cmp/DCmp.java new file mode 100644 index 000000000..d4d22bf9b --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-solon/src/test/java/com/yomahub/liteflow/test/maxWaitMilliseconds/cmp/DCmp.java @@ -0,0 +1,25 @@ +package com.yomahub.liteflow.test.maxWaitMilliseconds.cmp; + +import com.yomahub.liteflow.annotation.LiteflowComponent; +import com.yomahub.liteflow.core.NodeComponent; +import com.yomahub.liteflow.slot.DefaultContext; + + +@LiteflowComponent("d") +public class DCmp extends NodeComponent { + + public static final String CONTENT_KEY = "testKey"; + + @Override + public void process() { + try { + Thread.sleep(500); + DefaultContext contextBean = this.getFirstContextBean(); + contextBean.setData(CONTENT_KEY, "value"); + } catch (Exception e) { + e.printStackTrace(); + } + + System.out.println("DCmp executed!"); + } +} diff --git a/liteflow-testcase-el/liteflow-testcase-el-solon/src/test/java/com/yomahub/liteflow/test/maxWaitMilliseconds/cmp/FCmp.java b/liteflow-testcase-el/liteflow-testcase-el-solon/src/test/java/com/yomahub/liteflow/test/maxWaitMilliseconds/cmp/FCmp.java new file mode 100644 index 000000000..dbed32163 --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-solon/src/test/java/com/yomahub/liteflow/test/maxWaitMilliseconds/cmp/FCmp.java @@ -0,0 +1,12 @@ +package com.yomahub.liteflow.test.maxWaitMilliseconds.cmp; + +import com.yomahub.liteflow.annotation.LiteflowComponent; +import com.yomahub.liteflow.core.NodeIfComponent; + +@LiteflowComponent("f") +public class FCmp 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/maxWaitMilliseconds/cmp/SCmp.java b/liteflow-testcase-el/liteflow-testcase-el-solon/src/test/java/com/yomahub/liteflow/test/maxWaitMilliseconds/cmp/SCmp.java new file mode 100644 index 000000000..b3236d60a --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-solon/src/test/java/com/yomahub/liteflow/test/maxWaitMilliseconds/cmp/SCmp.java @@ -0,0 +1,13 @@ +package com.yomahub.liteflow.test.maxWaitMilliseconds.cmp; + +import com.yomahub.liteflow.annotation.LiteflowComponent; +import com.yomahub.liteflow.core.NodeSwitchComponent; + +@LiteflowComponent("s") +public class SCmp 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/maxWaitMilliseconds/cmp/WCmp.java b/liteflow-testcase-el/liteflow-testcase-el-solon/src/test/java/com/yomahub/liteflow/test/maxWaitMilliseconds/cmp/WCmp.java new file mode 100644 index 000000000..433c8bec5 --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-solon/src/test/java/com/yomahub/liteflow/test/maxWaitMilliseconds/cmp/WCmp.java @@ -0,0 +1,26 @@ +package com.yomahub.liteflow.test.maxWaitMilliseconds.cmp; + +import com.yomahub.liteflow.annotation.LiteflowComponent; +import com.yomahub.liteflow.core.NodeWhileComponent; + +import java.util.HashSet; +import java.util.Set; + +@LiteflowComponent("w") +public class WCmp 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 <= 2; + } +} diff --git a/liteflow-testcase-el/liteflow-testcase-el-solon/src/test/java/com/yomahub/liteflow/test/maxWaitMilliseconds/cmp/XCmp.java b/liteflow-testcase-el/liteflow-testcase-el-solon/src/test/java/com/yomahub/liteflow/test/maxWaitMilliseconds/cmp/XCmp.java new file mode 100644 index 000000000..706ecd7c6 --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-solon/src/test/java/com/yomahub/liteflow/test/maxWaitMilliseconds/cmp/XCmp.java @@ -0,0 +1,17 @@ +package com.yomahub.liteflow.test.maxWaitMilliseconds.cmp; + +import cn.hutool.core.collection.ListUtil; +import com.yomahub.liteflow.annotation.LiteflowComponent; +import com.yomahub.liteflow.core.NodeIteratorComponent; + +import java.util.Iterator; +import java.util.List; + +@LiteflowComponent("x") +public class XCmp extends NodeIteratorComponent { + @Override + public Iterator processIterator() throws Exception { + List list = ListUtil.toList("one", "two"); + return list.iterator(); + } +} diff --git a/liteflow-testcase-el/liteflow-testcase-el-solon/src/test/resources/maxWaitMilliseconds/application.properties b/liteflow-testcase-el/liteflow-testcase-el-solon/src/test/resources/maxWaitMilliseconds/application.properties new file mode 100644 index 000000000..678dc827e --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-solon/src/test/resources/maxWaitMilliseconds/application.properties @@ -0,0 +1 @@ +liteflow.rule-source=maxWaitMilliseconds/flow.el.xml \ No newline at end of file diff --git a/liteflow-testcase-el/liteflow-testcase-el-solon/src/test/resources/maxWaitMilliseconds/flow.el.xml b/liteflow-testcase-el/liteflow-testcase-el-solon/src/test/resources/maxWaitMilliseconds/flow.el.xml new file mode 100644 index 000000000..13ead3d38 --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-solon/src/test/resources/maxWaitMilliseconds/flow.el.xml @@ -0,0 +1,110 @@ + + + + + + + THEN(a,b).maxWaitMilliseconds(200); + + + + THEN(a,b).maxWaitMilliseconds(500); + + + + + + WHEN(a,c).maxWaitMilliseconds(300); + + + + WHEN(a,b).maxWaitMilliseconds(300); + + + + + + FOR(2).DO(a).maxWaitMilliseconds(100); + + + + FOR(2).DO(a).maxWaitMilliseconds(300); + + + + + WHILE(w).DO(a).maxWaitMilliseconds(100); + + + + WHILE(w).DO(a).maxWaitMilliseconds(300); + + + + + ITERATOR(x).DO(a).maxWaitMilliseconds(100); + + + + ITERATOR(x).DO(a).maxWaitMilliseconds(300); + + + + + + + SWITCH(s).TO(a, b).maxWaitMilliseconds(100); + + + + SWITCH(s).TO(a, b).maxWaitMilliseconds(300); + + + + + + + IF(f, b, c).maxWaitMilliseconds(100); + + + + IF(f, b, c).maxWaitMilliseconds(300); + + + + + + WHEN( + a.maxWaitMilliseconds(200), + c.maxWaitMilliseconds(300) + ); + + + + WHEN( + a.maxWaitMilliseconds(200), + b.maxWaitMilliseconds(300) + ); + + + + + + THEN(PRE(a), b, FINALLY(d)).maxWaitMilliseconds(200); + + + + + THEN(b) + + + + testChain.maxWaitMilliseconds(100); + + + + testChain.maxWaitMilliseconds(300); + + \ No newline at end of file diff --git a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/maxWaitMilliseconds/MaxWaitMillisecondsELSpringbootTest.java b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/maxWaitMilliseconds/MaxWaitMillisecondsELSpringbootTest.java new file mode 100644 index 000000000..dbba4288a --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/maxWaitMilliseconds/MaxWaitMillisecondsELSpringbootTest.java @@ -0,0 +1,201 @@ +package com.yomahub.liteflow.test.maxWaitMilliseconds; + +import com.yomahub.liteflow.builder.LiteFlowNodeBuilder; +import com.yomahub.liteflow.builder.el.LiteFlowChainELBuilder; +import com.yomahub.liteflow.core.FlowExecutor; +import com.yomahub.liteflow.enums.NodeTypeEnum; +import com.yomahub.liteflow.exception.WhenTimeoutException; +import com.yomahub.liteflow.flow.LiteflowResponse; +import com.yomahub.liteflow.slot.DefaultContext; +import com.yomahub.liteflow.test.BaseTest; +import com.yomahub.liteflow.test.validateRule.cmp.ACmp; +import com.yomahub.liteflow.test.validateRule.cmp.BCmp; +import com.yomahub.liteflow.test.validateRule.cmp.CCmp; +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.TimeoutException; + +import static com.yomahub.liteflow.test.maxWaitSeconds.cmp.DCmp.CONTENT_KEY; + +/** + * Spring Boot 环境下超时控制测试 - maxWaitMilliseconds + * + * @author Kugaaa + * @since 2.11.1 + */ +@TestPropertySource(value = "classpath:/maxWaitMilliseconds/application.properties") +@SpringBootTest(classes = MaxWaitMillisecondsELSpringbootTest.class) +@EnableAutoConfiguration +@ComponentScan({"com.yomahub.liteflow.test.maxWaitMilliseconds.cmp"}) +public class MaxWaitMillisecondsELSpringbootTest extends BaseTest { + + @Resource + private FlowExecutor flowExecutor; + + // 测试 THEN 的超时情况 + @Test + public void testThen1() { + assertTimeout("then1"); + } + + // 测试 THEN 的非超时情况 + @Test + public void testThen2() { + assertNotTimeout("then2"); + } + + // 测试 When 的超时情况 + @Test + public void testWhen1() { + // WHEN 抛出的是 WhenTimeoutException + assertWhenTimeout("when1"); + } + + // 测试 WHEN 的非超时情况 + @Test + public void testWhen2() { + assertNotTimeout("when2"); + } + + // 测试 FOR 的超时情况 + @Test + public void testFor1() { + assertTimeout("for1"); + } + + // 测试 FOR 的非超时情况 + @Test + public void testFor2() { + assertNotTimeout("for2"); + } + + // 测试 WHILE 的超时情况 + @Test + public void testWhile1() { + assertTimeout("while1"); + } + + // 测试 WHILE 的非超时情况 + @Test + public void testWhile2() { + assertNotTimeout("while2"); + } + + // 测试 ITERATOR 的超时情况 + @Test + public void testIterator1() { + assertTimeout("iterator1"); + } + + // 测试 ITERATOR 的非超时情况 + @Test + public void testIterator2() { + assertNotTimeout("iterator2"); + } + + // 测试 SWITCH 的超时情况 + @Test + public void testSwitch1() { + assertTimeout("switch1"); + } + + // 测试 SWITCH 的非超时情况 + @Test + public void testSwitch2() { + assertNotTimeout("switch2"); + } + + // 测试 IF 的超时情况 + @Test + public void testIf1() { + assertTimeout("if1"); + } + + // 测试 SWITCH 的非超时情况 + @Test + public void testIf2() { + assertNotTimeout("if2"); + } + + // 测试单个组件的超时情况 + @Test + public void testComponent1() { + assertTimeout("component1"); + } + + // 测试单个组件的非超时情况 + @Test + public void testComponent2() { + assertNotTimeout("component2"); + } + + // 测试 FINALLY,虽然超时,但 FINALLY 仍会执行 + @Test + public void testFinally1() { + LiteflowResponse response = flowExecutor.execute2Resp("finally", "arg"); + Assertions.assertFalse(response.isSuccess()); + Assertions.assertEquals(TimeoutException.class, response.getCause().getClass()); + // FINALLY 执行时在默认数据上下文中放入了 CONTENT_KEY + DefaultContext contextBean = response.getFirstContextBean(); + Assertions.assertTrue(contextBean.hasData(CONTENT_KEY)); + } + + // 测试 maxWaitMilliseconds 关键字不能作用于 Finally + @Test + public void testFinally2() { + LiteFlowNodeBuilder.createNode() + .setId("a") + .setName("组件A") + .setType(NodeTypeEnum.COMMON) + .setClazz(ACmp.class) + .build(); + LiteFlowNodeBuilder.createNode() + .setId("b") + .setName("组件B") + .setType(NodeTypeEnum.COMMON) + .setClazz(BCmp.class) + .build(); + LiteFlowNodeBuilder.createNode() + .setId("c") + .setName("组件C") + .setType(NodeTypeEnum.COMMON) + .setClazz(CCmp.class) + .build(); + Assertions.assertFalse(LiteFlowChainELBuilder.validate("THEN(a, b, FINALLY(c).maxWaitMilliseconds(100))")); + } + + // 测试 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"); + Assertions.assertFalse(response.isSuccess()); + Assertions.assertEquals(TimeoutException.class, response.getCause().getClass()); + } + + private void assertWhenTimeout(String chainId) { + LiteflowResponse response = flowExecutor.execute2Resp(chainId, "arg"); + Assertions.assertFalse(response.isSuccess()); + Assertions.assertEquals(WhenTimeoutException.class, response.getCause().getClass()); + } + + private void assertNotTimeout(String chainId) { + LiteflowResponse response = flowExecutor.execute2Resp(chainId, "arg"); + Assertions.assertTrue(response.isSuccess()); + } +} diff --git a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/maxWaitMilliseconds/cmp/ACmp.java b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/maxWaitMilliseconds/cmp/ACmp.java new file mode 100644 index 000000000..0a92711c0 --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/maxWaitMilliseconds/cmp/ACmp.java @@ -0,0 +1,18 @@ +package com.yomahub.liteflow.test.maxWaitMilliseconds.cmp; + +import com.yomahub.liteflow.annotation.LiteflowComponent; +import com.yomahub.liteflow.core.NodeComponent; + +@LiteflowComponent("a") +public class ACmp extends NodeComponent { + @Override + public void process() { + try { + Thread.sleep(100); + } catch (Exception e) { + e.printStackTrace(); + } + + System.out.println("ACmp executed!"); + } +} diff --git a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/maxWaitMilliseconds/cmp/BCmp.java b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/maxWaitMilliseconds/cmp/BCmp.java new file mode 100644 index 000000000..0eba389eb --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/maxWaitMilliseconds/cmp/BCmp.java @@ -0,0 +1,18 @@ +package com.yomahub.liteflow.test.maxWaitMilliseconds.cmp; + +import com.yomahub.liteflow.annotation.LiteflowComponent; +import com.yomahub.liteflow.core.NodeComponent; + +@LiteflowComponent("b") +public class BCmp extends NodeComponent { + @Override + public void process() { + try { + Thread.sleep(200); + } catch (Exception e) { + e.printStackTrace(); + } + + System.out.println("BCmp executed!"); + } +} diff --git a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/maxWaitMilliseconds/cmp/CCmp.java b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/maxWaitMilliseconds/cmp/CCmp.java new file mode 100644 index 000000000..b6994f151 --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/maxWaitMilliseconds/cmp/CCmp.java @@ -0,0 +1,18 @@ +package com.yomahub.liteflow.test.maxWaitMilliseconds.cmp; + +import com.yomahub.liteflow.annotation.LiteflowComponent; +import com.yomahub.liteflow.core.NodeComponent; + +@LiteflowComponent("c") +public class CCmp extends NodeComponent { + @Override + public void process() { + try { + Thread.sleep(500); + } catch (Exception e) { + e.printStackTrace(); + } + + System.out.println("CCmp executed!"); + } +} diff --git a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/maxWaitMilliseconds/cmp/DCmp.java b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/maxWaitMilliseconds/cmp/DCmp.java new file mode 100644 index 000000000..826b28e88 --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/maxWaitMilliseconds/cmp/DCmp.java @@ -0,0 +1,24 @@ +package com.yomahub.liteflow.test.maxWaitMilliseconds.cmp; + +import com.yomahub.liteflow.annotation.LiteflowComponent; +import com.yomahub.liteflow.core.NodeComponent; +import com.yomahub.liteflow.slot.DefaultContext; + +@LiteflowComponent("d") +public class DCmp extends NodeComponent { + + public static final String CONTENT_KEY = "testKey"; + + @Override + public void process() { + try { + Thread.sleep(500); + DefaultContext contextBean = this.getFirstContextBean(); + contextBean.setData(CONTENT_KEY,"value"); + } catch (Exception e) { + e.printStackTrace(); + } + + System.out.println("DCmp executed!"); + } +} diff --git a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/maxWaitMilliseconds/cmp/FCmp.java b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/maxWaitMilliseconds/cmp/FCmp.java new file mode 100644 index 000000000..dbed32163 --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/maxWaitMilliseconds/cmp/FCmp.java @@ -0,0 +1,12 @@ +package com.yomahub.liteflow.test.maxWaitMilliseconds.cmp; + +import com.yomahub.liteflow.annotation.LiteflowComponent; +import com.yomahub.liteflow.core.NodeIfComponent; + +@LiteflowComponent("f") +public class FCmp 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/maxWaitMilliseconds/cmp/SCmp.java b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/maxWaitMilliseconds/cmp/SCmp.java new file mode 100644 index 000000000..b3236d60a --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/maxWaitMilliseconds/cmp/SCmp.java @@ -0,0 +1,13 @@ +package com.yomahub.liteflow.test.maxWaitMilliseconds.cmp; + +import com.yomahub.liteflow.annotation.LiteflowComponent; +import com.yomahub.liteflow.core.NodeSwitchComponent; + +@LiteflowComponent("s") +public class SCmp 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/maxWaitMilliseconds/cmp/WCmp.java b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/maxWaitMilliseconds/cmp/WCmp.java new file mode 100644 index 000000000..433c8bec5 --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/maxWaitMilliseconds/cmp/WCmp.java @@ -0,0 +1,26 @@ +package com.yomahub.liteflow.test.maxWaitMilliseconds.cmp; + +import com.yomahub.liteflow.annotation.LiteflowComponent; +import com.yomahub.liteflow.core.NodeWhileComponent; + +import java.util.HashSet; +import java.util.Set; + +@LiteflowComponent("w") +public class WCmp 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 <= 2; + } +} diff --git a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/maxWaitMilliseconds/cmp/XCmp.java b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/maxWaitMilliseconds/cmp/XCmp.java new file mode 100644 index 000000000..706ecd7c6 --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/maxWaitMilliseconds/cmp/XCmp.java @@ -0,0 +1,17 @@ +package com.yomahub.liteflow.test.maxWaitMilliseconds.cmp; + +import cn.hutool.core.collection.ListUtil; +import com.yomahub.liteflow.annotation.LiteflowComponent; +import com.yomahub.liteflow.core.NodeIteratorComponent; + +import java.util.Iterator; +import java.util.List; + +@LiteflowComponent("x") +public class XCmp extends NodeIteratorComponent { + @Override + public Iterator processIterator() throws Exception { + List list = ListUtil.toList("one", "two"); + return list.iterator(); + } +} diff --git a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/maxWaitMilliseconds/application.properties b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/maxWaitMilliseconds/application.properties new file mode 100644 index 000000000..678dc827e --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/maxWaitMilliseconds/application.properties @@ -0,0 +1 @@ +liteflow.rule-source=maxWaitMilliseconds/flow.el.xml \ No newline at end of file diff --git a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/maxWaitMilliseconds/flow.el.xml b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/maxWaitMilliseconds/flow.el.xml new file mode 100644 index 000000000..13ead3d38 --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/maxWaitMilliseconds/flow.el.xml @@ -0,0 +1,110 @@ + + + + + + + THEN(a,b).maxWaitMilliseconds(200); + + + + THEN(a,b).maxWaitMilliseconds(500); + + + + + + WHEN(a,c).maxWaitMilliseconds(300); + + + + WHEN(a,b).maxWaitMilliseconds(300); + + + + + + FOR(2).DO(a).maxWaitMilliseconds(100); + + + + FOR(2).DO(a).maxWaitMilliseconds(300); + + + + + WHILE(w).DO(a).maxWaitMilliseconds(100); + + + + WHILE(w).DO(a).maxWaitMilliseconds(300); + + + + + ITERATOR(x).DO(a).maxWaitMilliseconds(100); + + + + ITERATOR(x).DO(a).maxWaitMilliseconds(300); + + + + + + + SWITCH(s).TO(a, b).maxWaitMilliseconds(100); + + + + SWITCH(s).TO(a, b).maxWaitMilliseconds(300); + + + + + + + IF(f, b, c).maxWaitMilliseconds(100); + + + + IF(f, b, c).maxWaitMilliseconds(300); + + + + + + WHEN( + a.maxWaitMilliseconds(200), + c.maxWaitMilliseconds(300) + ); + + + + WHEN( + a.maxWaitMilliseconds(200), + b.maxWaitMilliseconds(300) + ); + + + + + + THEN(PRE(a), b, FINALLY(d)).maxWaitMilliseconds(200); + + + + + THEN(b) + + + + testChain.maxWaitMilliseconds(100); + + + + testChain.maxWaitMilliseconds(300); + + \ No newline at end of file diff --git a/liteflow-testcase-el/liteflow-testcase-el-springnative/src/test/java/com/yomahub/liteflow/test/maxWaitMilliseconds/MaxWaitMillisecondsELSpringTest.java b/liteflow-testcase-el/liteflow-testcase-el-springnative/src/test/java/com/yomahub/liteflow/test/maxWaitMilliseconds/MaxWaitMillisecondsELSpringTest.java new file mode 100644 index 000000000..d511a3b53 --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-springnative/src/test/java/com/yomahub/liteflow/test/maxWaitMilliseconds/MaxWaitMillisecondsELSpringTest.java @@ -0,0 +1,196 @@ +package com.yomahub.liteflow.test.maxWaitMilliseconds; + +import com.yomahub.liteflow.builder.LiteFlowNodeBuilder; +import com.yomahub.liteflow.builder.el.LiteFlowChainELBuilder; +import com.yomahub.liteflow.core.FlowExecutor; +import com.yomahub.liteflow.enums.NodeTypeEnum; +import com.yomahub.liteflow.exception.WhenTimeoutException; +import com.yomahub.liteflow.flow.LiteflowResponse; +import com.yomahub.liteflow.slot.DefaultContext; +import com.yomahub.liteflow.test.BaseTest; +import com.yomahub.liteflow.test.maxWaitSeconds.cmp.ACmp; +import com.yomahub.liteflow.test.maxWaitSeconds.cmp.BCmp; +import com.yomahub.liteflow.test.maxWaitSeconds.cmp.CCmp; +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.TimeoutException; + +import static com.yomahub.liteflow.test.maxWaitSeconds.cmp.DCmp.CONTENT_KEY; + +/** + * Spring 环境下超时控制测试 - maxWaitMilliseconds + * + * @author Kugaaa + * @since 2.11.1 + */ +@ExtendWith(SpringExtension.class) +@ContextConfiguration("classpath:/maxWaitMilliseconds/application.xml") +public class MaxWaitMillisecondsELSpringTest extends BaseTest { + @Resource + private FlowExecutor flowExecutor; + + // 测试 THEN 的超时情况 + @Test + public void testThen1() { + assertTimeout("then1"); + } + + // 测试 THEN 的非超时情况 + @Test + public void testThen2() { + assertNotTimeout("then2"); + } + + // 测试 When 的超时情况 + @Test + public void testWhen1() { + assertWhenTimeout("when1"); + } + + // 测试 WHEN 的非超时情况 + @Test + public void testWhen2() { + assertNotTimeout("when2"); + } + + // 测试 FOR 的超时情况 + @Test + public void testFor1() { + assertTimeout("for1"); + } + + // 测试 FOR 的非超时情况 + @Test + public void testFor2() { + assertNotTimeout("for2"); + } + + // 测试 WHILE 的超时情况 + @Test + public void testWhile1() { + assertTimeout("while1"); + } + + // 测试 WHILE 的非超时情况 + @Test + public void testWhile2() { + assertNotTimeout("while2"); + } + + // 测试 ITERATOR 的超时情况 + @Test + public void testIterator1() { + assertTimeout("iterator1"); + } + + // 测试 ITERATOR 的非超时情况 + @Test + public void testIterator2() { + assertNotTimeout("iterator2"); + } + + // 测试 SWITCH 的超时情况 + @Test + public void testSwitch1() { + assertTimeout("switch1"); + } + + // 测试 SWITCH 的非超时情况 + @Test + public void testSwitch2() { + assertNotTimeout("switch2"); + } + + // 测试 IF 的超时情况 + @Test + public void testIf1() { + assertTimeout("if1"); + } + + // 测试 SWITCH 的非超时情况 + @Test + public void testIf2() { + assertNotTimeout("if2"); + } + + // 测试单个组件的超时情况 + @Test + public void testComponent1() { + assertTimeout("component1"); + } + + // 测试单个组件的非超时情况 + @Test + public void testComponent2() { + assertNotTimeout("component2"); + } + + // 测试 FINALLY,虽然超时,但 FINALLY 仍会执行 + @Test + public void testFinally1() { + LiteflowResponse response = flowExecutor.execute2Resp("finally", "arg"); + Assertions.assertFalse(response.isSuccess()); + Assertions.assertEquals(TimeoutException.class, response.getCause().getClass()); + // FINALLY 执行时在默认数据上下文中放入了 CONTENT_KEY + DefaultContext contextBean = response.getFirstContextBean(); + Assertions.assertTrue(contextBean.hasData(CONTENT_KEY)); + } + + // 测试 maxWaitMilliseconds 关键字不能作用于 Finally + @Test + public void testFinally2() { + LiteFlowNodeBuilder.createNode() + .setId("a") + .setName("组件A") + .setType(NodeTypeEnum.COMMON) + .setClazz(ACmp.class) + .build(); + LiteFlowNodeBuilder.createNode() + .setId("b") + .setName("组件B") + .setType(NodeTypeEnum.COMMON) + .setClazz(BCmp.class) + .build(); + LiteFlowNodeBuilder.createNode() + .setId("c") + .setName("组件C") + .setType(NodeTypeEnum.COMMON) + .setClazz(CCmp.class) + .build(); + Assertions.assertFalse(LiteFlowChainELBuilder.validate("THEN(a, b, FINALLY(c).maxWaitMilliseconds(100))")); + } + + // 测试 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"); + Assertions.assertFalse(response.isSuccess()); + Assertions.assertEquals(TimeoutException.class, response.getCause().getClass()); + } + + private void assertWhenTimeout(String chainId) { + LiteflowResponse response = flowExecutor.execute2Resp(chainId, "arg"); + Assertions.assertFalse(response.isSuccess()); + Assertions.assertEquals(WhenTimeoutException.class, response.getCause().getClass()); + } + + private void assertNotTimeout(String chainId) { + LiteflowResponse response = flowExecutor.execute2Resp(chainId, "arg"); + Assertions.assertTrue(response.isSuccess()); + } +} diff --git a/liteflow-testcase-el/liteflow-testcase-el-springnative/src/test/java/com/yomahub/liteflow/test/maxWaitMilliseconds/cmp/ACmp.java b/liteflow-testcase-el/liteflow-testcase-el-springnative/src/test/java/com/yomahub/liteflow/test/maxWaitMilliseconds/cmp/ACmp.java new file mode 100644 index 000000000..0a92711c0 --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-springnative/src/test/java/com/yomahub/liteflow/test/maxWaitMilliseconds/cmp/ACmp.java @@ -0,0 +1,18 @@ +package com.yomahub.liteflow.test.maxWaitMilliseconds.cmp; + +import com.yomahub.liteflow.annotation.LiteflowComponent; +import com.yomahub.liteflow.core.NodeComponent; + +@LiteflowComponent("a") +public class ACmp extends NodeComponent { + @Override + public void process() { + try { + Thread.sleep(100); + } catch (Exception e) { + e.printStackTrace(); + } + + System.out.println("ACmp executed!"); + } +} diff --git a/liteflow-testcase-el/liteflow-testcase-el-springnative/src/test/java/com/yomahub/liteflow/test/maxWaitMilliseconds/cmp/BCmp.java b/liteflow-testcase-el/liteflow-testcase-el-springnative/src/test/java/com/yomahub/liteflow/test/maxWaitMilliseconds/cmp/BCmp.java new file mode 100644 index 000000000..0eba389eb --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-springnative/src/test/java/com/yomahub/liteflow/test/maxWaitMilliseconds/cmp/BCmp.java @@ -0,0 +1,18 @@ +package com.yomahub.liteflow.test.maxWaitMilliseconds.cmp; + +import com.yomahub.liteflow.annotation.LiteflowComponent; +import com.yomahub.liteflow.core.NodeComponent; + +@LiteflowComponent("b") +public class BCmp extends NodeComponent { + @Override + public void process() { + try { + Thread.sleep(200); + } catch (Exception e) { + e.printStackTrace(); + } + + System.out.println("BCmp executed!"); + } +} diff --git a/liteflow-testcase-el/liteflow-testcase-el-springnative/src/test/java/com/yomahub/liteflow/test/maxWaitMilliseconds/cmp/CCmp.java b/liteflow-testcase-el/liteflow-testcase-el-springnative/src/test/java/com/yomahub/liteflow/test/maxWaitMilliseconds/cmp/CCmp.java new file mode 100644 index 000000000..b6994f151 --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-springnative/src/test/java/com/yomahub/liteflow/test/maxWaitMilliseconds/cmp/CCmp.java @@ -0,0 +1,18 @@ +package com.yomahub.liteflow.test.maxWaitMilliseconds.cmp; + +import com.yomahub.liteflow.annotation.LiteflowComponent; +import com.yomahub.liteflow.core.NodeComponent; + +@LiteflowComponent("c") +public class CCmp extends NodeComponent { + @Override + public void process() { + try { + Thread.sleep(500); + } catch (Exception e) { + e.printStackTrace(); + } + + System.out.println("CCmp executed!"); + } +} diff --git a/liteflow-testcase-el/liteflow-testcase-el-springnative/src/test/java/com/yomahub/liteflow/test/maxWaitMilliseconds/cmp/DCmp.java b/liteflow-testcase-el/liteflow-testcase-el-springnative/src/test/java/com/yomahub/liteflow/test/maxWaitMilliseconds/cmp/DCmp.java new file mode 100644 index 000000000..d4d22bf9b --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-springnative/src/test/java/com/yomahub/liteflow/test/maxWaitMilliseconds/cmp/DCmp.java @@ -0,0 +1,25 @@ +package com.yomahub.liteflow.test.maxWaitMilliseconds.cmp; + +import com.yomahub.liteflow.annotation.LiteflowComponent; +import com.yomahub.liteflow.core.NodeComponent; +import com.yomahub.liteflow.slot.DefaultContext; + + +@LiteflowComponent("d") +public class DCmp extends NodeComponent { + + public static final String CONTENT_KEY = "testKey"; + + @Override + public void process() { + try { + Thread.sleep(500); + DefaultContext contextBean = this.getFirstContextBean(); + contextBean.setData(CONTENT_KEY, "value"); + } catch (Exception e) { + e.printStackTrace(); + } + + System.out.println("DCmp executed!"); + } +} diff --git a/liteflow-testcase-el/liteflow-testcase-el-springnative/src/test/java/com/yomahub/liteflow/test/maxWaitMilliseconds/cmp/FCmp.java b/liteflow-testcase-el/liteflow-testcase-el-springnative/src/test/java/com/yomahub/liteflow/test/maxWaitMilliseconds/cmp/FCmp.java new file mode 100644 index 000000000..dbed32163 --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-springnative/src/test/java/com/yomahub/liteflow/test/maxWaitMilliseconds/cmp/FCmp.java @@ -0,0 +1,12 @@ +package com.yomahub.liteflow.test.maxWaitMilliseconds.cmp; + +import com.yomahub.liteflow.annotation.LiteflowComponent; +import com.yomahub.liteflow.core.NodeIfComponent; + +@LiteflowComponent("f") +public class FCmp 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/maxWaitMilliseconds/cmp/SCmp.java b/liteflow-testcase-el/liteflow-testcase-el-springnative/src/test/java/com/yomahub/liteflow/test/maxWaitMilliseconds/cmp/SCmp.java new file mode 100644 index 000000000..b3236d60a --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-springnative/src/test/java/com/yomahub/liteflow/test/maxWaitMilliseconds/cmp/SCmp.java @@ -0,0 +1,13 @@ +package com.yomahub.liteflow.test.maxWaitMilliseconds.cmp; + +import com.yomahub.liteflow.annotation.LiteflowComponent; +import com.yomahub.liteflow.core.NodeSwitchComponent; + +@LiteflowComponent("s") +public class SCmp 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/maxWaitMilliseconds/cmp/WCmp.java b/liteflow-testcase-el/liteflow-testcase-el-springnative/src/test/java/com/yomahub/liteflow/test/maxWaitMilliseconds/cmp/WCmp.java new file mode 100644 index 000000000..433c8bec5 --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-springnative/src/test/java/com/yomahub/liteflow/test/maxWaitMilliseconds/cmp/WCmp.java @@ -0,0 +1,26 @@ +package com.yomahub.liteflow.test.maxWaitMilliseconds.cmp; + +import com.yomahub.liteflow.annotation.LiteflowComponent; +import com.yomahub.liteflow.core.NodeWhileComponent; + +import java.util.HashSet; +import java.util.Set; + +@LiteflowComponent("w") +public class WCmp 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 <= 2; + } +} diff --git a/liteflow-testcase-el/liteflow-testcase-el-springnative/src/test/java/com/yomahub/liteflow/test/maxWaitMilliseconds/cmp/XCmp.java b/liteflow-testcase-el/liteflow-testcase-el-springnative/src/test/java/com/yomahub/liteflow/test/maxWaitMilliseconds/cmp/XCmp.java new file mode 100644 index 000000000..706ecd7c6 --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-springnative/src/test/java/com/yomahub/liteflow/test/maxWaitMilliseconds/cmp/XCmp.java @@ -0,0 +1,17 @@ +package com.yomahub.liteflow.test.maxWaitMilliseconds.cmp; + +import cn.hutool.core.collection.ListUtil; +import com.yomahub.liteflow.annotation.LiteflowComponent; +import com.yomahub.liteflow.core.NodeIteratorComponent; + +import java.util.Iterator; +import java.util.List; + +@LiteflowComponent("x") +public class XCmp extends NodeIteratorComponent { + @Override + public Iterator processIterator() throws Exception { + List list = ListUtil.toList("one", "two"); + return list.iterator(); + } +} diff --git a/liteflow-testcase-el/liteflow-testcase-el-springnative/src/test/resources/maxWaitMilliseconds/application.xml b/liteflow-testcase-el/liteflow-testcase-el-springnative/src/test/resources/maxWaitMilliseconds/application.xml new file mode 100644 index 000000000..a73511dbc --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-springnative/src/test/resources/maxWaitMilliseconds/application.xml @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/liteflow-testcase-el/liteflow-testcase-el-springnative/src/test/resources/maxWaitMilliseconds/flow.el.xml b/liteflow-testcase-el/liteflow-testcase-el-springnative/src/test/resources/maxWaitMilliseconds/flow.el.xml new file mode 100644 index 000000000..13ead3d38 --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-springnative/src/test/resources/maxWaitMilliseconds/flow.el.xml @@ -0,0 +1,110 @@ + + + + + + + THEN(a,b).maxWaitMilliseconds(200); + + + + THEN(a,b).maxWaitMilliseconds(500); + + + + + + WHEN(a,c).maxWaitMilliseconds(300); + + + + WHEN(a,b).maxWaitMilliseconds(300); + + + + + + FOR(2).DO(a).maxWaitMilliseconds(100); + + + + FOR(2).DO(a).maxWaitMilliseconds(300); + + + + + WHILE(w).DO(a).maxWaitMilliseconds(100); + + + + WHILE(w).DO(a).maxWaitMilliseconds(300); + + + + + ITERATOR(x).DO(a).maxWaitMilliseconds(100); + + + + ITERATOR(x).DO(a).maxWaitMilliseconds(300); + + + + + + + SWITCH(s).TO(a, b).maxWaitMilliseconds(100); + + + + SWITCH(s).TO(a, b).maxWaitMilliseconds(300); + + + + + + + IF(f, b, c).maxWaitMilliseconds(100); + + + + IF(f, b, c).maxWaitMilliseconds(300); + + + + + + WHEN( + a.maxWaitMilliseconds(200), + c.maxWaitMilliseconds(300) + ); + + + + WHEN( + a.maxWaitMilliseconds(200), + b.maxWaitMilliseconds(300) + ); + + + + + + THEN(PRE(a), b, FINALLY(d)).maxWaitMilliseconds(200); + + + + + THEN(b) + + + + testChain.maxWaitMilliseconds(100); + + + + testChain.maxWaitMilliseconds(300); + + \ No newline at end of file