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 8dd55c9d3c1d9076da49179aff66f8a4ea2a15a6..7ce55ea09773713983c041feb76441ec1e930a9e 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 @@ -1,7 +1,10 @@ package com.yomahub.liteflow.builder.el; import cn.hutool.core.collection.CollUtil; -import cn.hutool.core.util.*; +import cn.hutool.core.util.ArrayUtil; +import cn.hutool.core.util.CharUtil; +import cn.hutool.core.util.ObjectUtil; +import cn.hutool.core.util.StrUtil; import cn.hutool.crypto.digest.MD5; import com.fasterxml.jackson.databind.JsonMappingException; import com.fasterxml.jackson.databind.ObjectMapper; @@ -29,7 +32,10 @@ import com.yomahub.liteflow.property.LiteflowConfig; import com.yomahub.liteflow.property.LiteflowConfigGetter; import com.yomahub.liteflow.util.ElRegexUtil; -import java.util.*; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Objects; /** @@ -38,6 +44,7 @@ import java.util.*; * @author Bryan.Zhang * @author Jay li * @author jason + * @author luo yi * @since 2.8.0 */ public class LiteFlowChainELBuilder { @@ -92,6 +99,7 @@ public class LiteFlowChainELBuilder { EXPRESS_RUNNER.addFunctionAndClassMethod(ChainConstant.TAG, Object.class, new TagOperator()); EXPRESS_RUNNER.addFunctionAndClassMethod(ChainConstant.ANY, Object.class, new AnyOperator()); EXPRESS_RUNNER.addFunctionAndClassMethod(ChainConstant.MUST, Object.class, new MustOperator()); + EXPRESS_RUNNER.addFunctionAndClassMethod(ChainConstant.PERCENTAGE, Object.class, new PercentageOperator()); EXPRESS_RUNNER.addFunctionAndClassMethod(ChainConstant.ID, Object.class, new IdOperator()); EXPRESS_RUNNER.addFunctionAndClassMethod(ChainConstant.IGNORE_ERROR, Object.class, new IgnoreErrorOperator()); EXPRESS_RUNNER.addFunctionAndClassMethod(ChainConstant.THREAD_POOL, Object.class, new ThreadPoolOperator()); diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/PercentageOperator.java b/liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/PercentageOperator.java new file mode 100644 index 0000000000000000000000000000000000000000..0bb172f3a4023bd6cbbc69c87e19fb5f3b92b6b2 --- /dev/null +++ b/liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/PercentageOperator.java @@ -0,0 +1,35 @@ +package com.yomahub.liteflow.builder.el.operator; + +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.enums.ParallelStrategyEnum; +import com.yomahub.liteflow.flow.element.condition.WhenCondition; + +/** + * EL 规则中的 percentage 的操作符 + * + * @author luo yi + * @since 2.13.4 + */ +public class PercentageOperator extends BaseOperator { + + @Override + public WhenCondition build(Object[] objects) throws Exception { + OperatorHelper.checkObjectSizeEqTwo(objects); + + WhenCondition whenCondition = OperatorHelper.convert(objects[0], WhenCondition.class, "The caller must be WhenCondition item"); + + // 指定并行任务需要完成的阈值 + Double percentage = OperatorHelper.convert2Double(objects[1]); + + if (percentage > 1 || percentage < 0) { + throw new QLException("The percentage must be between 0 and 1."); + } + + whenCondition.setParallelStrategy(ParallelStrategyEnum.PERCENTAGE); + whenCondition.setPercentage(percentage); + return whenCondition; + } + +} diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/base/OperatorHelper.java b/liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/base/OperatorHelper.java index 712bced8da299386d39a5d7d508d2c4e44906b4c..a407639ba5d19f4ff70c8f79070f4d81def913ea 100644 --- a/liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/base/OperatorHelper.java +++ b/liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/base/OperatorHelper.java @@ -17,6 +17,7 @@ import java.util.Objects; * Operator 常用工具类 * * @author gaibu + * @author luo yi * @since 2.8.6 */ public class OperatorHelper { @@ -109,6 +110,18 @@ public class OperatorHelper { return convert(object, clazz, errorMsg); } + public static Double convert2Double(Object object) throws QLException { + if (object instanceof Number) { + // 对 float 特别处理,避免精度问题 + if (object instanceof Float) { + // 使用字符串转换避免 float 精度损失 + return Double.parseDouble(Float.toString((Float) object)); + } + return ((Number) object).doubleValue(); + } + throw new QLException(StrUtil.format("Unsupported type: {}, it must be numeric type.", object.getClass().getName())); + } + /** * 转换 object 为指定的类型,自定义错误信息 如果是Node类型的则进行copy */ 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 492c7094f083f3941d98003e66b5d2b0515e5804..2f7dd3223006a91c46bf668557e971f5c28ecce8 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 @@ -45,6 +45,8 @@ public interface ChainConstant { String MUST = "must"; + String PERCENTAGE = "percentage"; + String TYPE = "type"; String THEN = "THEN"; diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/core/FlowExecutor.java b/liteflow-core/src/main/java/com/yomahub/liteflow/core/FlowExecutor.java index 7555e22451e1094e129cbfdf03f6ac04a9b8261c..9f0001764f77025f1945a51fb9eaa92a701074cf 100644 --- a/liteflow-core/src/main/java/com/yomahub/liteflow/core/FlowExecutor.java +++ b/liteflow-core/src/main/java/com/yomahub/liteflow/core/FlowExecutor.java @@ -22,14 +22,14 @@ import com.yomahub.liteflow.enums.ParseModeEnum; import com.yomahub.liteflow.exception.*; import com.yomahub.liteflow.flow.FlowBus; import com.yomahub.liteflow.flow.LiteflowResponse; -import com.yomahub.liteflow.lifecycle.PostProcessChainExecuteLifeCycle; -import com.yomahub.liteflow.lifecycle.impl.ChainCacheLifeCycle; import com.yomahub.liteflow.flow.element.Chain; import com.yomahub.liteflow.flow.element.Node; import com.yomahub.liteflow.flow.element.Rollbackable; import com.yomahub.liteflow.flow.entity.CmpStep; import com.yomahub.liteflow.flow.id.IdGeneratorHolder; import com.yomahub.liteflow.lifecycle.LifeCycleHolder; +import com.yomahub.liteflow.lifecycle.PostProcessChainExecuteLifeCycle; +import com.yomahub.liteflow.lifecycle.impl.ChainCacheLifeCycle; import com.yomahub.liteflow.log.LFLog; import com.yomahub.liteflow.log.LFLoggerManager; import com.yomahub.liteflow.monitor.MonitorFile; diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/enums/ParallelStrategyEnum.java b/liteflow-core/src/main/java/com/yomahub/liteflow/enums/ParallelStrategyEnum.java index 09c9af4376060ce05316c10e7f14579cbdbb79b9..835e2a5a8f5140d4614ba77514070f3d0d37c79f 100644 --- a/liteflow-core/src/main/java/com/yomahub/liteflow/enums/ParallelStrategyEnum.java +++ b/liteflow-core/src/main/java/com/yomahub/liteflow/enums/ParallelStrategyEnum.java @@ -1,9 +1,6 @@ package com.yomahub.liteflow.enums; -import com.yomahub.liteflow.flow.parallel.strategy.AllOfParallelExecutor; -import com.yomahub.liteflow.flow.parallel.strategy.AnyOfParallelExecutor; -import com.yomahub.liteflow.flow.parallel.strategy.ParallelStrategyExecutor; -import com.yomahub.liteflow.flow.parallel.strategy.SpecifyParallelExecutor; +import com.yomahub.liteflow.flow.parallel.strategy.*; /** * 并行策略枚举类 @@ -17,7 +14,10 @@ public enum ParallelStrategyEnum { ALL("allOf", "完成全部任务", AllOfParallelExecutor.class), - SPECIFY("must", "完成指定 ID 任务", SpecifyParallelExecutor.class); + SPECIFY("must", "完成指定 ID 任务", SpecifyParallelExecutor.class), + + PERCENTAGE("percentageOf", "完整指定阈值任务", PercentageOfParallelExecutor.class); + private String strategyType; diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/flow/element/Chain.java b/liteflow-core/src/main/java/com/yomahub/liteflow/flow/element/Chain.java index 0b16c49d54f611d42ea8f839bcd8ab15fa4a3e5a..80aa73bc8b17695cab6b6107b66a307b6b2f4528 100644 --- a/liteflow-core/src/main/java/com/yomahub/liteflow/flow/element/Chain.java +++ b/liteflow-core/src/main/java/com/yomahub/liteflow/flow/element/Chain.java @@ -10,23 +10,20 @@ package com.yomahub.liteflow.flow.element; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.util.BooleanUtil; -import cn.hutool.core.util.ObjectUtil; -import com.alibaba.ttl.TransmittableThreadLocal; import cn.hutool.core.util.IdUtil; import cn.hutool.core.util.StrUtil; +import com.alibaba.ttl.TransmittableThreadLocal; import com.yomahub.liteflow.builder.el.LiteFlowChainELBuilder; import com.yomahub.liteflow.common.ChainConstant; import com.yomahub.liteflow.enums.ExecuteableTypeEnum; import com.yomahub.liteflow.exception.ChainEndException; import com.yomahub.liteflow.exception.FlowSystemException; -import com.yomahub.liteflow.flow.FlowBus; import com.yomahub.liteflow.lifecycle.LifeCycleHolder; import com.yomahub.liteflow.log.LFLog; import com.yomahub.liteflow.log.LFLoggerManager; import com.yomahub.liteflow.meta.LiteflowMetaOperator; import com.yomahub.liteflow.slot.DataBus; import com.yomahub.liteflow.slot.Slot; -import com.yomahub.liteflow.util.ElRegexUtil; import java.util.ArrayList; import java.util.List; diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/flow/element/condition/WhenCondition.java b/liteflow-core/src/main/java/com/yomahub/liteflow/flow/element/condition/WhenCondition.java index 15eb31cbd1aba1641861ab5a19cc701583b81b45..69e544252572502b53b4fd93f2f50a093c713e1e 100644 --- a/liteflow-core/src/main/java/com/yomahub/liteflow/flow/element/condition/WhenCondition.java +++ b/liteflow-core/src/main/java/com/yomahub/liteflow/flow/element/condition/WhenCondition.java @@ -51,6 +51,9 @@ public class WhenCondition extends Condition { // 等待时间单位 private TimeUnit maxWaitTimeUnit; + // 并发任务指定阈值,取值 0 - 1 + private Double percentage; + @Override public void executeCondition(Integer slotIndex) throws Exception { executeAsyncCondition(slotIndex); @@ -130,4 +133,12 @@ public class WhenCondition extends Condition { public void setMaxWaitTimeUnit(TimeUnit maxWaitTimeUnit) { this.maxWaitTimeUnit = maxWaitTimeUnit; } + + public Double getPercentage() { + return percentage; + } + + public void setPercentage(Double percentage) { + this.percentage = percentage; + } } diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/flow/parallel/strategy/PercentageOfParallelExecutor.java b/liteflow-core/src/main/java/com/yomahub/liteflow/flow/parallel/strategy/PercentageOfParallelExecutor.java new file mode 100644 index 0000000000000000000000000000000000000000..181613b270f18cd525b3567687f2b864da0b1215 --- /dev/null +++ b/liteflow-core/src/main/java/com/yomahub/liteflow/flow/parallel/strategy/PercentageOfParallelExecutor.java @@ -0,0 +1,70 @@ +package com.yomahub.liteflow.flow.parallel.strategy; + +import com.yomahub.liteflow.flow.element.condition.WhenCondition; +import com.yomahub.liteflow.flow.parallel.WhenFutureObj; + +import java.util.List; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ConcurrentLinkedQueue; +import java.util.concurrent.atomic.LongAdder; + +/** + * 完成指定阈值任务 + * + * @author luo yi + * @since 2.13.4 + */ +public class PercentageOfParallelExecutor extends ParallelStrategyExecutor { + + @Override + public void execute(WhenCondition whenCondition, Integer slotIndex) throws Exception { + + // 获取所有 CompletableFuture 任务 + List> whenAllTaskList = this.getWhenAllTaskList(whenCondition, slotIndex); + + int total = whenAllTaskList.size(); + + // 计算阈值数量(向上取整),为 0 时取 1,表示只等待一个完成,即 any + int thresholdCount = Math.max(1, (int) Math.ceil(total * whenCondition.getPercentage())); + + // 已完成任务收集器 + ConcurrentLinkedQueue> completedFutures = new ConcurrentLinkedQueue<>(); + + // 阈值触发门闩 + CompletableFuture thresholdFuture = new CompletableFuture<>(); + + // 原子计数器 + LongAdder completedCount = new LongAdder(); + + // 为每个任务添加回调 + whenAllTaskList.forEach(future -> + future.whenComplete((result, ex) -> { + // 计数 +1 + completedCount.increment(); + + int currentCount = completedCount.intValue(); + + if (currentCount <= thresholdCount) { + // 添加已完成任务 + completedFutures.add(future); + } + + // 达到阈值时触发门闩(确保只触发一次) + if (currentCount >= thresholdCount && !thresholdFuture.isDone()) { + thresholdFuture.complete(null); + } + }) + ); + + // 创建组合任务(仅包含已完成任务) + CompletableFuture combinedTask = thresholdFuture.thenRun(() -> { + // 达到阈值时创建 allOf 任务 + CompletableFuture.allOf(completedFutures.toArray(new CompletableFuture[]{})).join(); + }); + + // 处理结果(会阻塞直到阈值任务完成) + this.handleTaskResult(whenCondition, slotIndex, whenAllTaskList, combinedTask); + + } + +} diff --git a/liteflow-el-builder/src/main/java/com/yomahub/liteflow/builder/el/WhenELWrapper.java b/liteflow-el-builder/src/main/java/com/yomahub/liteflow/builder/el/WhenELWrapper.java index 34384e087423070e0acdc3b5c8696aff9b13f0c6..9e3d47935604731b252713a3ee0de858c9bb6fd1 100644 --- a/liteflow-el-builder/src/main/java/com/yomahub/liteflow/builder/el/WhenELWrapper.java +++ b/liteflow-el-builder/src/main/java/com/yomahub/liteflow/builder/el/WhenELWrapper.java @@ -1,9 +1,14 @@ package com.yomahub.liteflow.builder.el; import cn.hutool.core.collection.CollectionUtil; +import cn.hutool.core.util.ObjUtil; import cn.hutool.core.util.StrUtil; -import java.util.*; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.stream.Stream; /** * 并行组件 @@ -23,6 +28,7 @@ public class WhenELWrapper extends ELWrapper { private boolean ignoreError; private String customThreadExecutor; private final List mustExecuteList; + private Double percentage; public WhenELWrapper(ELWrapper... elWrappers) { this.addWrapper(elWrappers); @@ -41,6 +47,11 @@ public class WhenELWrapper extends ELWrapper { return this; } + public WhenELWrapper percentage(double percentage) { + this.percentage = percentage; + return this; + } + public WhenELWrapper ignoreError(boolean ignoreError) { this.ignoreError = ignoreError; return this; @@ -110,6 +121,18 @@ public class WhenELWrapper extends ELWrapper { @Override protected String toEL(Integer depth, StringBuilder paramContext) { + + // 互斥检查:确保三个属性中最多只有一个被设置 + long count = Stream.of( + this.any ? 1 : 0, + CollectionUtil.isNotEmpty(this.mustExecuteList) ? 1 : 0, + ObjUtil.isNotNull(this.percentage) ? 1 : 0 + ).filter(num -> num > 0).count(); + + if (count > 1) { + throw new IllegalArgumentException("Properties 'any', 'must', and 'percentage' are mutually exclusive. Only one can be set at a time."); + } + Integer sonDepth = depth == null ? null : depth + 1; StringBuilder sb = new StringBuilder(); @@ -139,10 +162,6 @@ public class WhenELWrapper extends ELWrapper { sb.append(StrUtil.format(".threadPool(\"{}\")", customThreadExecutor)); } if(CollectionUtil.isNotEmpty(mustExecuteList)){ - // 校验must 语义与 any语义冲突 - if (this.any){ - throw new IllegalArgumentException("'.must()' and '.any()' can use in when component at the same time!"); - } // 处理must子表达式输出 sb.append(".must("); for(int i = 0; i < mustExecuteList.size(); i++){ @@ -154,6 +173,10 @@ public class WhenELWrapper extends ELWrapper { sb.append(")"); } + if (ObjUtil.isNotNull(percentage)){ + sb.append(StrUtil.format(".percentage({})", percentage)); + } + // 处理公共属性输出 processWrapperProperty(sb, paramContext); return sb.toString(); diff --git a/liteflow-testcase-el/liteflow-testcase-el-builder/src/test/java/com/yomahub/liteflow/test/builder/WhenELBuilderTest.java b/liteflow-testcase-el/liteflow-testcase-el-builder/src/test/java/com/yomahub/liteflow/test/builder/WhenELBuilderTest.java index 1f8b1623f077b87a7a30682910a31caf6f593be9..f8293ed468922957ffbc99bec0d0c4d6a4e864ce 100644 --- a/liteflow-testcase-el/liteflow-testcase-el-builder/src/test/java/com/yomahub/liteflow/test/builder/WhenELBuilderTest.java +++ b/liteflow-testcase-el/liteflow-testcase-el-builder/src/test/java/com/yomahub/liteflow/test/builder/WhenELBuilderTest.java @@ -210,4 +210,23 @@ public class WhenELBuilderTest extends BaseTest { WhenELWrapper el = ELBus.when(ELBus.node("a"), ELBus.node("b"), ELBus.node("c")).customThreadExecutor("com.yomahub.liteflow.test.builder.customTreadExecutor.CustomThreadExecutor1"); Assertions.assertTrue(LiteFlowChainELBuilder.validate(el.toEL())); } + + // 测试互斥属性设置 + @Test + public void testWHEN1(){ + WhenELWrapper el = ELBus.when(ELBus.node("a"), ELBus.node("b")).percentage(0.66).any(true); + WhenELWrapper el2 = ELBus.when(ELBus.node("a"), ELBus.node("b")).must("a").any(true); + WhenELWrapper el3 = ELBus.when(ELBus.node("a"), ELBus.node("b")).must("a").percentage(0.55); + Assertions.assertThrowsExactly(IllegalArgumentException.class, el::toEL); + Assertions.assertThrowsExactly(IllegalArgumentException.class, el2::toEL); + Assertions.assertThrowsExactly(IllegalArgumentException.class, el3::toEL); + } + + // 测试 percentage 属性 + @Test + public void testWHEN2(){ + WhenELWrapper el = ELBus.when(ELBus.node("a"), ELBus.node("b")).percentage(0.66); + Assertions.assertTrue(LiteFlowChainELBuilder.validate(el.toEL())); + } + } diff --git a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/asyncNode/AsyncNodeELSpringbootTest.java b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/asyncNode/AsyncNodeELSpringbootTest.java index 37e0413d2a9307807aac24903dcd67bb37fba1c0..9dfe3a0a1d261127a7f83ab50ca1e2ed41b6add2 100644 --- a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/asyncNode/AsyncNodeELSpringbootTest.java +++ b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/asyncNode/AsyncNodeELSpringbootTest.java @@ -184,4 +184,49 @@ public class AsyncNodeELSpringbootTest extends BaseTest { Assertions.assertTrue(context.getData("check").toString().startsWith("akbgc")); } + // 测试 percentage 关键字,percentage 为 0.6,数量为 3 + @Test + public void testAsyncFlow14() throws Exception { + LiteflowResponse response = flowExecutor.execute2Resp("chain14", "it's a base request"); + DefaultContext context = response.getFirstContextBean(); + Assertions.assertTrue(response.isSuccess()); + Assertions.assertEquals("3", context.getData("count").toString()); + } + + // 测试 percentage 关键字,percentage 为 0,相当于 any + @Test + public void testAsyncFlow15() throws Exception { + LiteflowResponse response = flowExecutor.execute2Resp("chain15", "it's a base request"); + DefaultContext context = response.getFirstContextBean(); + Assertions.assertTrue(response.isSuccess()); + Assertions.assertEquals("1", context.getData("count").toString()); + } + + // 测试 percentage 关键字,percentage 为 1,相当于 all + @Test + public void testAsyncFlow16() throws Exception { + LiteflowResponse response = flowExecutor.execute2Resp("chain16", "it's a base request"); + DefaultContext context = response.getFirstContextBean(); + Assertions.assertTrue(response.isSuccess()); + Assertions.assertEquals("5", context.getData("count").toString()); + } + + // 测试 percentage 、ignoreError 关键字 + @Test + public void testAsyncFlow17() throws Exception { + LiteflowResponse response = flowExecutor.execute2Resp("chain17", "it's a base request"); + DefaultContext context = response.getFirstContextBean(); + Assertions.assertTrue(response.isSuccess()); + Assertions.assertEquals("2", context.getData("count").toString()); + } + + // 测试 percentage 、ignoreError 关键字 + @Test + public void testAsyncFlow18() throws Exception { + LiteflowResponse response = flowExecutor.execute2Resp("chain18", "it's a base request"); + DefaultContext context = response.getFirstContextBean(); + Assertions.assertFalse(response.isSuccess()); + Assertions.assertEquals("2", context.getData("count").toString()); + } + } diff --git a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/asyncNode/cmp/MCmp.java b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/asyncNode/cmp/MCmp.java new file mode 100644 index 0000000000000000000000000000000000000000..f12da42550b5419feacfb4a9f1ce5fabe8b4fdd0 --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/asyncNode/cmp/MCmp.java @@ -0,0 +1,26 @@ +package com.yomahub.liteflow.test.asyncNode.cmp; + +import com.yomahub.liteflow.core.NodeComponent; +import com.yomahub.liteflow.slot.DefaultContext; +import org.springframework.stereotype.Component; + +@Component("m") +public class MCmp extends NodeComponent { + + @Override + public void process() throws Exception { + String seconds = this.getTag(); + Thread.sleep((long) (1000 * Double.parseDouble(seconds))); + DefaultContext context = this.getFirstContextBean(); + synchronized (MCmp.class) { + if (context.hasData("count")) { + Integer count = context.getData("count"); + context.setData("count", ++count); + } else { + context.setData("count", 1); + } + } + System.out.println("Mcomp executed!"); + } + +} diff --git a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/asyncNode/cmp/NCmp.java b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/asyncNode/cmp/NCmp.java new file mode 100644 index 0000000000000000000000000000000000000000..5794cfa43c525a7d8a91c70c4feaffec6f641cf6 --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/asyncNode/cmp/NCmp.java @@ -0,0 +1,18 @@ +package com.yomahub.liteflow.test.asyncNode.cmp; + +import com.yomahub.liteflow.core.NodeComponent; +import org.springframework.stereotype.Component; + +@Component("n") +public class NCmp extends NodeComponent { + + @Override + public void process() throws Exception { + String seconds = this.getTag(); + Thread.sleep((long) (1000 * Double.parseDouble(seconds))); + // 手动抛异常 + System.out.println("Ncomp executed with exeption!"); + int a = 1 / 0; + } + +} diff --git a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/asyncNode/flow1.xml b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/asyncNode/flow1.xml index b02c48cf88ca9789f717fce748af2a798b9abb64..fae6b7c465635247ca3fd82ca69dbb13d20ef228 100644 --- a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/asyncNode/flow1.xml +++ b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/asyncNode/flow1.xml @@ -66,4 +66,24 @@ THEN(WHEN(d, g, l, a, THEN(k, b).id("z")).ignoreError(true).must("z", g, "task1", "task2"), c); + + WHEN(m.tag("1"), m.tag("2"), m.tag("3"), m.tag("4"), m.tag("5")).percentage(0.6f); + + + + WHEN(m.tag("1"), m.tag("2"), m.tag("3"), m.tag("4"), m.tag("5")).percentage(0); + + + + WHEN(m.tag("1"), m.tag("2"), m.tag("3"), m.tag("4"), m.tag("5")).percentage(1); + + + + WHEN(m.tag("1"), m.tag("2"), n.tag("2"), m.tag("3"), m.tag("4"), m.tag("5")).ignoreError(true).percentage(0.5); + + + + WHEN(THEN(m.tag("1"), n.tag("1.5")), m.tag("2"), m.tag("3"), m.tag("4"), m.tag("5")).ignoreError(false).percentage(0.4); + + \ No newline at end of file