From 47fe94b2b4d68879f57dc109aaf0654f5ec831f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BE=90=E4=BD=B3?= Date: Thu, 25 Mar 2021 17:22:45 +0800 Subject: [PATCH 01/10] =?UTF-8?q?enhancement=20#I37QVR=20WhenCondition?= =?UTF-8?q?=E6=97=B6=E5=80=99=EF=BC=8C=E5=B9=B6=E5=8F=91=E6=89=A7=E8=A1=8C?= =?UTF-8?q?=E7=9B=AE=E5=89=8D=E4=BC=9A=E6=AF=8F=E6=AC=A1=E6=96=B0=E5=BB=BA?= =?UTF-8?q?=E7=BA=BF=E7=A8=8B=E5=8F=AF=E4=B8=8D=E5=8F=AF=E8=B5=B0=E7=BA=BF?= =?UTF-8?q?=E7=A8=8B=E6=B1=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../yomahub/liteflow/core/FlowExecutor.java | 16 +++ .../yomahub/liteflow/entity/flow/Chain.java | 59 +++++++- ...tionThread.java => ParallelCondition.java} | 17 ++- .../liteflow/entity/flow/WhenCondition.java | 12 ++ .../liteflow/parser/XmlFlowParser.java | 11 +- .../yomahub/liteflow/util/ExecutorHelper.java | 94 ++++++++++++ .../LiteflowExecutorAutoConfiguration.java | 38 +++++ .../LiteflowMainAutoConfiguration.java | 6 +- .../yomahub/liteflow/springboot/Shutdown.java | 37 +++++ .../main/resources/META-INF/spring.factories | 1 + .../flowtest/concurrent/ConcurrentCase.java | 135 ++++++++++++++++++ .../flowtest/concurrent/SpringBootApp.java | 24 ++++ .../flowtest/concurrent/TestParseFlow.java | 85 +++++++++++ .../flowtest/concurrent/TestRunFlow.java | 81 +++++++++++ .../mock/component/c/C10Component.java | 26 ++++ .../mock/component/c/C1Component.java | 26 ++++ .../mock/component/c/C2Component.java | 26 ++++ .../mock/component/c/C3Component.java | 26 ++++ .../mock/component/c/C4Component.java | 26 ++++ .../mock/component/c/C5Component.java | 26 ++++ .../mock/component/c/C6Component.java | 26 ++++ .../mock/component/c/C7Component.java | 26 ++++ .../mock/component/c/C8Component.java | 26 ++++ .../mock/component/c/C9Component.java | 26 ++++ .../mock/component/p/P3Component.java | 25 ++++ .../mock/component/p/P4Component.java | 25 ++++ .../mock/component/p/P5Component.java | 25 ++++ .../mock/component/p/P6Component.java | 25 ++++ .../mock/component/p/P7Component.java | 25 ++++ .../mock/component/p/P8Component.java | 25 ++++ .../mock/component/s/S1Component.java | 25 ++++ .../mock/component/s/S2Component.java | 25 ++++ .../mock/component/s/S3Component.java | 25 ++++ .../mock/component/s/S4Component.java | 25 ++++ .../mock/component/s/S5Component.java | 25 ++++ .../mock/component/s/S6Component.java | 25 ++++ .../src/test/resources/application-test.yml | 18 +++ .../src/test/resources/config/flow-test.xml | 20 +++ 38 files changed, 1200 insertions(+), 14 deletions(-) rename liteflow-core/src/main/java/com/yomahub/liteflow/entity/flow/{WhenConditionThread.java => ParallelCondition.java} (54%) create mode 100644 liteflow-core/src/main/java/com/yomahub/liteflow/util/ExecutorHelper.java create mode 100644 liteflow-spring-boot-starter/src/main/java/com/yomahub/liteflow/springboot/LiteflowExecutorAutoConfiguration.java create mode 100644 liteflow-spring-boot-starter/src/main/java/com/yomahub/liteflow/springboot/Shutdown.java create mode 100644 liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/ConcurrentCase.java create mode 100644 liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/SpringBootApp.java create mode 100644 liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/TestParseFlow.java create mode 100644 liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/TestRunFlow.java create mode 100644 liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/mock/component/c/C10Component.java create mode 100644 liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/mock/component/c/C1Component.java create mode 100644 liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/mock/component/c/C2Component.java create mode 100644 liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/mock/component/c/C3Component.java create mode 100644 liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/mock/component/c/C4Component.java create mode 100644 liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/mock/component/c/C5Component.java create mode 100644 liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/mock/component/c/C6Component.java create mode 100644 liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/mock/component/c/C7Component.java create mode 100644 liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/mock/component/c/C8Component.java create mode 100644 liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/mock/component/c/C9Component.java create mode 100644 liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/mock/component/p/P3Component.java create mode 100644 liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/mock/component/p/P4Component.java create mode 100644 liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/mock/component/p/P5Component.java create mode 100644 liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/mock/component/p/P6Component.java create mode 100644 liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/mock/component/p/P7Component.java create mode 100644 liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/mock/component/p/P8Component.java create mode 100644 liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/mock/component/s/S1Component.java create mode 100644 liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/mock/component/s/S2Component.java create mode 100644 liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/mock/component/s/S3Component.java create mode 100644 liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/mock/component/s/S4Component.java create mode 100644 liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/mock/component/s/S5Component.java create mode 100644 liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/mock/component/s/S6Component.java create mode 100644 liteflow-test-springboot/src/test/resources/application-test.yml create mode 100644 liteflow-test-springboot/src/test/resources/config/flow-test.xml 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 6a9ff0bd2..fc8a09c4a 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 @@ -33,6 +33,8 @@ import com.yomahub.liteflow.parser.LocalXmlFlowParser; import com.yomahub.liteflow.parser.XmlFlowParser; import com.yomahub.liteflow.parser.ZookeeperXmlFlowParser; +import java.util.concurrent.ExecutorService; + /** * 流程规则主要执行器类 * @author Bryan.Zhang @@ -43,6 +45,8 @@ public class FlowExecutor { private LiteflowConfig liteflowConfig; + private ExecutorService parallelExecutor; + private String zkNode; //FlowExecutor的初始化化方式,主要用于parse规则文件 @@ -126,6 +130,10 @@ public class FlowExecutor { throw new ChainNotFoundException(errorMsg); } + if (parallelExecutor != null) { + chain.setParallelExecutor(parallelExecutor); + } + if(!isInnerChain && slotIndex == null) { slotIndex = DataBus.offerSlot(slotClazz); LOG.info("slot[{}] offered",slotIndex); @@ -183,4 +191,12 @@ public class FlowExecutor { public void setLiteflowConfig(LiteflowConfig liteflowConfig) { this.liteflowConfig = liteflowConfig; } + + public ExecutorService getParallelExecutor() { + return parallelExecutor; + } + + public void setParallelExecutor(ExecutorService parallelExecutor) { + this.parallelExecutor = parallelExecutor; + } } diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/entity/flow/Chain.java b/liteflow-core/src/main/java/com/yomahub/liteflow/entity/flow/Chain.java index 320b10ee1..d637428d8 100644 --- a/liteflow-core/src/main/java/com/yomahub/liteflow/entity/flow/Chain.java +++ b/liteflow-core/src/main/java/com/yomahub/liteflow/entity/flow/Chain.java @@ -23,6 +23,9 @@ import java.util.List; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; +import java.util.ArrayList; +import java.util.concurrent.*; + /** * chain对象,实现可执行器 * @author Bryan.Zhang @@ -37,6 +40,8 @@ public class Chain implements Executable { private static int whenMaxWaitSeconds; + private ExecutorService parallelExecutor; + static { LiteflowConfig liteflowConfig = SpringAware.getBean(LiteflowConfig.class); if (ObjectUtil.isNotNull(liteflowConfig)) { @@ -51,6 +56,14 @@ public class Chain implements Executable { this.conditionList = conditionList; } + public ExecutorService getParallelExecutor() { + return parallelExecutor; + } + + public void setParallelExecutor(ExecutorService parallelExecutor) { + this.parallelExecutor = parallelExecutor; + } + public List getConditionList() { return conditionList; } @@ -88,11 +101,18 @@ public class Chain implements Executable { } } } else if (condition instanceof WhenCondition) { - final CountDownLatch latch = new CountDownLatch(condition.getNodeList().size()); - for (Executable executableItem : condition.getNodeList()) { - new WhenConditionThread(executableItem, slotIndex, slot.getRequestId(), latch).start(); + /** + for (Executable executableItem : condition.getNodeList()) { + * 设置了线程池且当前condition isSync = true时,使用异步线程池执行 + new WhenConditionThread(executableItem, slotIndex, slot.getRequestId(), latch).start(); + */ + if (((WhenCondition) condition).isASync() && parallelExecutor != null) { + executeAsyncCondition((WhenCondition) condition, slotIndex, slot.getRequestId()); + } else { + for (Executable executableItem : condition.getNodeList()) { + executableItem.execute(slotIndex); + } } - latch.await(whenMaxWaitSeconds, TimeUnit.SECONDS); } } } @@ -106,4 +126,35 @@ public class Chain implements Executable { public String getExecuteName() { return chainName; } + + + /** + * 使用线程池执行并发流程 + * @param condition + * @param slotIndex + * @param requestId + */ + private void executeAsyncCondition(WhenCondition condition, Integer slotIndex, String requestId) { + final CountDownLatch latch = new CountDownLatch(condition.getNodeList().size()); + final List> futures = new ArrayList<>(condition.getNodeList().size()); + + for (int i = 0; i < condition.getNodeList().size(); i++) { + futures.add(parallelExecutor.submit( + new ParallelCondition(condition.getNodeList().get(i), slotIndex, requestId, latch) + )); + } + + try { + if (!latch.await(whenMaxWaitSeconds, TimeUnit.SECONDS)) { + for (Future f : futures) { + f.cancel(true); + } + } + LOG.warn("requestId [{}] executing async condition has reached max-wait-seconds, condition canceled and move to next executableItem." + , requestId); + } catch (InterruptedException e) { + // ignore InterruptedException + + } + } } diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/entity/flow/WhenConditionThread.java b/liteflow-core/src/main/java/com/yomahub/liteflow/entity/flow/ParallelCondition.java similarity index 54% rename from liteflow-core/src/main/java/com/yomahub/liteflow/entity/flow/WhenConditionThread.java rename to liteflow-core/src/main/java/com/yomahub/liteflow/entity/flow/ParallelCondition.java index bc42440d0..cbfe0e1e3 100644 --- a/liteflow-core/src/main/java/com/yomahub/liteflow/entity/flow/WhenConditionThread.java +++ b/liteflow-core/src/main/java/com/yomahub/liteflow/entity/flow/ParallelCondition.java @@ -2,6 +2,7 @@ package com.yomahub.liteflow.entity.flow; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.util.concurrent.Callable; import java.util.concurrent.CountDownLatch; @@ -9,9 +10,9 @@ import java.util.concurrent.CountDownLatch; * 并行器线程 * @author Bryan.Zhang */ -public class WhenConditionThread extends Thread { +public class ParallelCondition implements Callable { - private static final Logger LOG = LoggerFactory.getLogger(WhenConditionThread.class); + private static final Logger LOG = LoggerFactory.getLogger(ParallelCondition.class); private Executable executableItem; @@ -21,7 +22,7 @@ public class WhenConditionThread extends Thread { private CountDownLatch latch; - public WhenConditionThread(Executable executableItem,Integer slotIndex,String requestId,CountDownLatch latch){ + public ParallelCondition(Executable executableItem, Integer slotIndex, String requestId, CountDownLatch latch) { this.executableItem = executableItem; this.slotIndex = slotIndex; this.requestId = requestId; @@ -29,13 +30,15 @@ public class WhenConditionThread extends Thread { } @Override - public void run() { - try{ + public Boolean call() throws Exception { + try { executableItem.execute(slotIndex); }catch(Exception e){ - LOG.error("item [{}] execute cause error",executableItem.getExecuteName(),e); - }finally{ + LOG.error("requestId [{}], item [{}] execute cause error", requestId, executableItem.getExecuteName(), e); + } finally { latch.countDown(); } + + return true; } } diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/entity/flow/WhenCondition.java b/liteflow-core/src/main/java/com/yomahub/liteflow/entity/flow/WhenCondition.java index fbcd9715e..da80489a5 100644 --- a/liteflow-core/src/main/java/com/yomahub/liteflow/entity/flow/WhenCondition.java +++ b/liteflow-core/src/main/java/com/yomahub/liteflow/entity/flow/WhenCondition.java @@ -14,9 +14,21 @@ import java.util.List; * @author Bryan.Zhang */ public class WhenCondition extends Condition{ + /** + * 增加isSync属性,以区分是循序执行还是并发执行 + */ + private boolean isASync; public WhenCondition(List nodeList) { super(nodeList); + isASync = true; + } + public WhenCondition(List nodeList, boolean isASync) { + super(nodeList); + this.isASync = isASync; } + public boolean isASync() { + return isASync; + } } diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/parser/XmlFlowParser.java b/liteflow-core/src/main/java/com/yomahub/liteflow/parser/XmlFlowParser.java index 372524838..606c5cddf 100644 --- a/liteflow-core/src/main/java/com/yomahub/liteflow/parser/XmlFlowParser.java +++ b/liteflow-core/src/main/java/com/yomahub/liteflow/parser/XmlFlowParser.java @@ -22,6 +22,7 @@ import org.slf4j.LoggerFactory; import com.yomahub.liteflow.core.NodeComponent; import com.yomahub.liteflow.flow.FlowBus; import com.yomahub.liteflow.spring.ComponentScaner; +import org.dom4j.Attribute; /** * xml形式的解析器 @@ -139,7 +140,15 @@ public abstract class XmlFlowParser { if (condE.getName().equals("then")) { conditionList.add(new ThenCondition(chainNodeList)); } else if (condE.getName().equals("when")) { - conditionList.add(new WhenCondition(chainNodeList)); + /** + * 设置是否为async异步 + */ + Attribute isSync = condE.attribute("async"); + if (isSync != null) { + conditionList.add(new WhenCondition(chainNodeList, isSync.getValue().equals("true"))); + } else { + conditionList.add(new WhenCondition(chainNodeList)); + } } } FlowBus.addChain(chainName, new Chain(chainName,conditionList)); diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/util/ExecutorHelper.java b/liteflow-core/src/main/java/com/yomahub/liteflow/util/ExecutorHelper.java new file mode 100644 index 000000000..7438ea303 --- /dev/null +++ b/liteflow-core/src/main/java/com/yomahub/liteflow/util/ExecutorHelper.java @@ -0,0 +1,94 @@ +package com.yomahub.liteflow.util; + +import java.util.concurrent.*; +import java.util.concurrent.atomic.AtomicLong; + +/** + * desc : + * name : ExecutorHelper + * + * @author : xujia + * date : 2021/3/24 + * @since : 1.8 + */ +public class ExecutorHelper { + + private ExecutorHelper() { + } + + /** + * 使用默认的等待时间1分钟,来关闭目标线程组。 + *

+ * + * @param pool 需要关闭的线程组. + */ + public static void shutdownAwaitTermination(ExecutorService pool) { + shutdownAwaitTermination(pool, 60L); + } + + /** + * 关闭ExecutorService的线程管理者 + *

+ * + * @param pool 需要关闭的管理者 + * @param timeout 等待时间 + */ + public static void shutdownAwaitTermination(ExecutorService pool, + long timeout) { + pool.shutdown(); + try { + if (!pool.awaitTermination(timeout, TimeUnit.SECONDS)) { + pool.shutdownNow(); + if (!pool.awaitTermination(timeout, TimeUnit.SECONDS)) { + System.err.println("Pool did not terminate."); + } + } + } catch (InterruptedException ie) { + pool.shutdownNow(); + Thread.currentThread().interrupt(); + } + } + + /** + * 返回一个线程工厂,这是一个可以定义线程名字的线程工厂,返回的线程都将被命名. + * 创建的线程都是非后台线程. + * + * @param name 名称. + * @return 线程工厂实例. + */ + public static ThreadFactory buildExecutorFactory(final String name) { + return buildExecutorFactory(name, false); + } + + /** + * 返回一个线程工厂,这是一个可以定义线程名字的线程工厂,返回的线程都将被命名. + * + * @param name 名称. + * @param daemon 是否为后台线程. + * @return 线程工厂实例. + */ + public static ThreadFactory buildExecutorFactory(final String name, final boolean daemon) { + return new ThreadFactory() { + + private final AtomicLong number = new AtomicLong(); + + @Override + public Thread newThread(Runnable r) { + Thread newThread = Executors.defaultThreadFactory().newThread(r); + newThread.setName(name + "-" + number.getAndIncrement()); + newThread.setDaemon(daemon); + return newThread; + } + + }; + } + + public static ExecutorService buildExecutor(int worker, int queue, String namePrefix, boolean daemon) { + return new ThreadPoolExecutor(worker, worker, + 0L, TimeUnit.MILLISECONDS, + new ArrayBlockingQueue<>(queue), + buildExecutorFactory(namePrefix, daemon), + new ThreadPoolExecutor.AbortPolicy() + ); + } +} diff --git a/liteflow-spring-boot-starter/src/main/java/com/yomahub/liteflow/springboot/LiteflowExecutorAutoConfiguration.java b/liteflow-spring-boot-starter/src/main/java/com/yomahub/liteflow/springboot/LiteflowExecutorAutoConfiguration.java new file mode 100644 index 000000000..1a337697f --- /dev/null +++ b/liteflow-spring-boot-starter/src/main/java/com/yomahub/liteflow/springboot/LiteflowExecutorAutoConfiguration.java @@ -0,0 +1,38 @@ +package com.yomahub.liteflow.springboot; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import java.util.concurrent.ExecutorService; + +import static com.yomahub.liteflow.util.ExecutorHelper.buildExecutor; + +/** + * desc : + * name : LiteflowExecutorAutoConfiguration + * + * @author : xujia + * date : 2021/3/24 + * @since : 1.8 + */ +@Configuration +public class LiteflowExecutorAutoConfiguration { + + @Bean("parallelExecutor") + public ExecutorService parallelExecutor( + @Value("${threadPool.parallel.worker:0}") int worker, + @Value("${threadPool.parallel.queue:512}") int queue) { + int useWorker = worker; + int useQueue = queue; + if (useWorker == 0) { + useWorker = Runtime.getRuntime().availableProcessors() + 1; + } + + if (useQueue < 512) { + useQueue = 512; + } + + return buildExecutor(useWorker, useQueue, "parallel-executors", false); + } +} diff --git a/liteflow-spring-boot-starter/src/main/java/com/yomahub/liteflow/springboot/LiteflowMainAutoConfiguration.java b/liteflow-spring-boot-starter/src/main/java/com/yomahub/liteflow/springboot/LiteflowMainAutoConfiguration.java index 3fe8a8a69..ff64e6166 100644 --- a/liteflow-spring-boot-starter/src/main/java/com/yomahub/liteflow/springboot/LiteflowMainAutoConfiguration.java +++ b/liteflow-spring-boot-starter/src/main/java/com/yomahub/liteflow/springboot/LiteflowMainAutoConfiguration.java @@ -20,6 +20,7 @@ import org.springframework.context.annotation.PropertySource; import javax.swing.*; import java.util.List; +import java.util.concurrent.ExecutorService; /** * 主要的业务装配器 @@ -29,15 +30,16 @@ import java.util.List; */ @Configuration @ConditionalOnBean(LiteflowConfig.class) -@AutoConfigureAfter(LiteflowPropertyAutoConfiguration.class) +@AutoConfigureAfter({LiteflowPropertyAutoConfiguration.class, LiteflowExecutorAutoConfiguration.class}) @Import(SpringAware.class) public class LiteflowMainAutoConfiguration { @Bean - public FlowExecutor flowExecutor(LiteflowConfig liteflowConfig){ + public FlowExecutor flowExecutor(LiteflowConfig liteflowConfig, ExecutorService parallelExecutor){ if(StrUtil.isNotBlank(liteflowConfig.getRuleSource())){ FlowExecutor flowExecutor = new FlowExecutor(); flowExecutor.setLiteflowConfig(liteflowConfig); + flowExecutor.setParallelExecutor(parallelExecutor); return flowExecutor; }else{ return null; diff --git a/liteflow-spring-boot-starter/src/main/java/com/yomahub/liteflow/springboot/Shutdown.java b/liteflow-spring-boot-starter/src/main/java/com/yomahub/liteflow/springboot/Shutdown.java new file mode 100644 index 000000000..07096eabb --- /dev/null +++ b/liteflow-spring-boot-starter/src/main/java/com/yomahub/liteflow/springboot/Shutdown.java @@ -0,0 +1,37 @@ +package com.yomahub.liteflow.springboot; + +import com.yomahub.liteflow.util.ExecutorHelper; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; + +import javax.annotation.PreDestroy; +import javax.annotation.Resource; +import java.util.concurrent.ExecutorService; + +/** + * desc : + * name : Shutdown + * + * @author : xujia + * date : 2021/3/24 + * @since : 1.8 + */ +@Order(Integer.MIN_VALUE) +@Component +public class Shutdown { + + private static final Logger LOG = LoggerFactory.getLogger(Shutdown.class); + + @Resource(name = "parallelExecutor") + private ExecutorService parallelExecutor; + + @PreDestroy + public void destroy() throws Exception { + LOG.info("Start closing the parallel-executors..."); + ExecutorHelper.shutdownAwaitTermination(parallelExecutor, 3600); + LOG.info("Succeed closing the parallel-executors ok..."); + } + +} diff --git a/liteflow-spring-boot-starter/src/main/resources/META-INF/spring.factories b/liteflow-spring-boot-starter/src/main/resources/META-INF/spring.factories index 23669427e..85b579284 100644 --- a/liteflow-spring-boot-starter/src/main/resources/META-INF/spring.factories +++ b/liteflow-spring-boot-starter/src/main/resources/META-INF/spring.factories @@ -1,6 +1,7 @@ org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ com.yomahub.liteflow.springboot.LiteflowComponentScannerAutoConfiguration,\ com.yomahub.liteflow.springboot.LiteflowPropertyAutoConfiguration,\ + com.yomahub.liteflow.springboot.LiteflowExecutorAutoConfiguration,\ com.yomahub.liteflow.springboot.LiteflowMainAutoConfiguration diff --git a/liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/ConcurrentCase.java b/liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/ConcurrentCase.java new file mode 100644 index 000000000..9bd1fa315 --- /dev/null +++ b/liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/ConcurrentCase.java @@ -0,0 +1,135 @@ +package com.yomahub.flowtest.concurrent; + +import org.junit.Assert; + +import java.util.AbstractMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.CopyOnWriteArrayList; + + +/** + * desc : + * name : ConcurrentCase + * + * @author : xujia + * date : 2021/3/25 + * @since : 1.8 + */ +public class ConcurrentCase { + public static final Map, List>> CASES = new ConcurrentHashMap<>(); + + /** + * 初始化一个测试用例的预期 + * @param request + * @param expected + */ + public static void caseInit(String request, List expected) { + CASES.put(request, new AbstractMap.SimpleEntry, List>(expected, new CopyOnWriteArrayList<>())); + } + + /** + * 添加这个测试用例的实际 + * @param request + * @param actual + */ + public static void caseAdd(String request, Routers actual) { + CASES.computeIfPresent(request, (k, v) -> { + v.getValue().add(actual); + return v; + }); + } + + /** + * 测试当前的Expected与Actual是否相同 + * + * @param request + */ + public static void caseAssert(String request) { + AbstractMap.SimpleEntry, List> ca = CASES.get(request); + Assert.assertNotNull(ca); + + Assert.assertEquals(ca.getKey(), ca.getValue()); + + if (ca.getValue().size() > 0) { + Integer expectedIndex = null; + for (Routers actual : ca.getValue()) { + + if (expectedIndex == null) { + expectedIndex = actual.getIndex(); + } else { + Assert.assertEquals(expectedIndex.intValue(), actual.getIndex()); + } + } + } + } + + /** + * 测试当前的Expected与Actual是否相同 + * + * @param request + */ + public static void caseAssertRandom(String request) { + AbstractMap.SimpleEntry, List> ca = CASES.get(request); + Assert.assertNotNull(ca); + + Assert.assertEquals(ca.getKey().size(), ca.getValue().size()); + + if (ca.getValue().size() > 0) { + Integer expectedIndex = null; + for (Routers actual : ca.getValue()) { + boolean find = false; + for(Routers routers : ca.getKey()) { + if (routers.getValue().equals(actual.getValue())) { + find = true; + } + } + Assert.assertTrue(find); + + if (expectedIndex == null) { + expectedIndex = actual.getIndex(); + } else { + Assert.assertEquals(expectedIndex.intValue(), actual.getIndex()); + } + } + } + } + + + public static class Routers { + int index; + String value; + + public Routers(String value) { + this.index = -1; + this.value = value; + } + public Routers(int index, String value) { + this.index = index; + this.value = value; + } + + public int getIndex() { + return index; + } + + public String getValue() { + return value; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + Routers routers = (Routers) o; + return value.equals(routers.value); + } + + @Override + public int hashCode() { + return Objects.hash(value); + } + } +} diff --git a/liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/SpringBootApp.java b/liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/SpringBootApp.java new file mode 100644 index 000000000..2c113b5f0 --- /dev/null +++ b/liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/SpringBootApp.java @@ -0,0 +1,24 @@ +package com.yomahub.flowtest.concurrent; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; + +/** + * desc : + * name : SpringBootApp + * + * @author : xujia + * date : 2021/3/3 + * @since : 1.8 + */ +@SpringBootApplication(exclude={DataSourceAutoConfiguration.class}) +public class SpringBootApp { + /** + * @param args + */ + public static void main(String[] args) { + SpringApplication.run(SpringBootApp.class, args); + } + +} diff --git a/liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/TestParseFlow.java b/liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/TestParseFlow.java new file mode 100644 index 000000000..1f7946153 --- /dev/null +++ b/liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/TestParseFlow.java @@ -0,0 +1,85 @@ +package com.yomahub.flowtest.concurrent; + + +import com.yomahub.liteflow.entity.flow.Chain; +import com.yomahub.liteflow.entity.flow.Condition; +import com.yomahub.liteflow.entity.flow.ThenCondition; +import com.yomahub.liteflow.entity.flow.WhenCondition; +import com.yomahub.liteflow.flow.FlowBus; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.ActiveProfiles; +import org.springframework.test.context.junit4.SpringRunner; + +import java.util.AbstractMap; +import java.util.Arrays; +import java.util.List; + + +/** + * desc : + * name : TestParseFlow + * + * @author : xujia + * date : 2021/3/25 + * @since : 1.8 + */ +@ActiveProfiles("test") +@RunWith(SpringRunner.class) +@SpringBootTest +public class TestParseFlow { + + private Check caseAsync = new Check("async", Arrays.asList( + new AbstractMap.SimpleEntry<>(ThenCondition.class, null), + new AbstractMap.SimpleEntry<>(WhenCondition.class, false), + new AbstractMap.SimpleEntry<>(WhenCondition.class, true), + new AbstractMap.SimpleEntry<>(WhenCondition.class, true) + )); + + private Check caseConcurrent = new Check("async-concurrent1", Arrays.asList( + new AbstractMap.SimpleEntry<>(WhenCondition.class, true) + )); + + @Test + public void parseWhen() throws Exception { + assertTrue(caseAsync, FlowBus.getChain(caseAsync.getChainCode())); + + assertTrue(caseConcurrent, FlowBus.getChain(caseConcurrent.getChainCode())); + } + + private void assertTrue(Check check, Chain chain) { + Assert.assertNotNull(chain); + + Assert.assertTrue(null != chain.getConditionList() && !chain.getConditionList().isEmpty()); + for (int i = 0; i < chain.getConditionList().size(); i ++) { + + AbstractMap.SimpleEntry, Boolean> expected = check.getAsyncWithWhen().get(i); + Condition actual = chain.getConditionList().get(i); + + Assert.assertEquals(expected.getKey(), actual.getClass()); + if (actual.getClass().equals(WhenCondition.class)) { + Assert.assertEquals(expected.getValue(), ((WhenCondition) actual).isASync()); + } + } + } + + public static class Check { + private String chainCode; + private List, Boolean>> asyncWithWhen; + + public Check(String chainCode, List, Boolean>> asyncWithWhen) { + this.chainCode = chainCode; + this.asyncWithWhen = asyncWithWhen; + } + + public String getChainCode() { + return chainCode; + } + + public List, Boolean>> getAsyncWithWhen() { + return asyncWithWhen; + } + } +} diff --git a/liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/TestRunFlow.java b/liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/TestRunFlow.java new file mode 100644 index 000000000..7ec971022 --- /dev/null +++ b/liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/TestRunFlow.java @@ -0,0 +1,81 @@ +package com.yomahub.flowtest.concurrent; + +import com.yomahub.liteflow.core.FlowExecutor; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.ActiveProfiles; +import org.springframework.test.context.junit4.SpringRunner; + +import javax.annotation.Resource; +import java.util.Arrays; +import java.util.List; +import java.util.UUID; +import java.util.stream.Collectors; + +import static com.yomahub.flowtest.concurrent.ConcurrentCase.caseAssertRandom; +import static com.yomahub.flowtest.concurrent.ConcurrentCase.caseInit; + +/** + * desc : + * name : TestRunFlow + * + * @author : xujia + * date : 2021/3/25 + * @since : 1.8 + */ +@ActiveProfiles("test") +@RunWith(SpringRunner.class) +@SpringBootTest +public class TestRunFlow { + + @Resource + private FlowExecutor flowExecutor; + + private String init(List steps) { + + String requestId = UUID.randomUUID().toString(); + + caseInit(requestId, steps.stream().map(ConcurrentCase.Routers::new).collect(Collectors.toList())); + + return requestId; + } + + @Test + public void mixedRunTest() throws Exception { + String requestId = init(Arrays.asList("s1", "s2", "s3", "s4", "s5", "s6", "p3", "p4", "p5", "p6", "p7", "p8")); + + flowExecutor.execute("async", requestId); + + caseAssertRandom(requestId); + } + + @Test + public void parallelTest() throws InterruptedException { + String requestId1 = init(Arrays.asList("c1", "c2", "c3", "c4", "c5")); + String requestId2 = init(Arrays.asList("c6", "c7", "c8", "c9", "c10")); + + List ts = Arrays.asList( + newExecutor("async-concurrent1", requestId1), + newExecutor("async-concurrent2", requestId2) + ); + ts.forEach(Thread::start); + + for (Thread t : ts) { + t.join(); + } + + caseAssertRandom(requestId1); + caseAssertRandom(requestId2); + } + + private Thread newExecutor(String chain, String requestId) { + return new Thread(() -> { + try { + flowExecutor.execute(chain, requestId); + } catch (Exception e) { + e.printStackTrace(); + } + }); + } +} diff --git a/liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/mock/component/c/C10Component.java b/liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/mock/component/c/C10Component.java new file mode 100644 index 000000000..e92c245fc --- /dev/null +++ b/liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/mock/component/c/C10Component.java @@ -0,0 +1,26 @@ +package com.yomahub.flowtest.concurrent.mock.component.c; + +import com.yomahub.flowtest.concurrent.ConcurrentCase; +import com.yomahub.liteflow.core.NodeComponent; +import org.springframework.stereotype.Component; + +/** + * desc : + * name : C10 + * + * @author : xujia + * date : 2021/3/25 + * @since : 1.8 + */ +@Component("c10") +public class C10Component extends NodeComponent { + + private static final String name = "c10"; + + @Override + public void process() throws Exception { + Thread.sleep(1_000); + ConcurrentCase.caseAdd((String) getSlot().getRequestData(), new ConcurrentCase.Routers(getSlotIndex(), name)); + System.out.println(String.format("[%s] component executed, index[%d].", name, getSlotIndex())); + } +} \ No newline at end of file diff --git a/liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/mock/component/c/C1Component.java b/liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/mock/component/c/C1Component.java new file mode 100644 index 000000000..17d3d95f7 --- /dev/null +++ b/liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/mock/component/c/C1Component.java @@ -0,0 +1,26 @@ +package com.yomahub.flowtest.concurrent.mock.component.c; + +import com.yomahub.flowtest.concurrent.ConcurrentCase; +import com.yomahub.liteflow.core.NodeComponent; +import org.springframework.stereotype.Component; + +/** + * desc : + * name : c1 + * + * @author : xujia + * date : 2021/3/25 + * @since : 1.8 + */ +@Component("c1") +public class C1Component extends NodeComponent { + + private static final String name = "c1"; + + @Override + public void process() throws Exception { + Thread.sleep(1_000); + ConcurrentCase.caseAdd((String) getSlot().getRequestData(), new ConcurrentCase.Routers(getSlotIndex(), name)); + System.out.println(String.format("[%s] component executed, index[%d].", name, getSlotIndex())); + } +} diff --git a/liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/mock/component/c/C2Component.java b/liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/mock/component/c/C2Component.java new file mode 100644 index 000000000..82564577d --- /dev/null +++ b/liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/mock/component/c/C2Component.java @@ -0,0 +1,26 @@ +package com.yomahub.flowtest.concurrent.mock.component.c; + +import com.yomahub.flowtest.concurrent.ConcurrentCase; +import com.yomahub.liteflow.core.NodeComponent; +import org.springframework.stereotype.Component; + +/** + * desc : + * name : C2 + * + * @author : xujia + * date : 2021/3/25 + * @since : 1.8 + */ +@Component("c2") +public class C2Component extends NodeComponent { + + private static final String name = "c2"; + + @Override + public void process() throws Exception { + Thread.sleep(1_000); + ConcurrentCase.caseAdd((String) getSlot().getRequestData(), new ConcurrentCase.Routers(getSlotIndex(), name)); + System.out.println(String.format("[%s] component executed, index[%d].", name, getSlotIndex())); + } +} diff --git a/liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/mock/component/c/C3Component.java b/liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/mock/component/c/C3Component.java new file mode 100644 index 000000000..0be98bf76 --- /dev/null +++ b/liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/mock/component/c/C3Component.java @@ -0,0 +1,26 @@ +package com.yomahub.flowtest.concurrent.mock.component.c; + +import com.yomahub.flowtest.concurrent.ConcurrentCase; +import com.yomahub.liteflow.core.NodeComponent; +import org.springframework.stereotype.Component; + +/** + * desc : + * name : C3Component + * + * @author : xujia + * date : 2021/3/25 + * @since : 1.8 + */ +@Component("c3") +public class C3Component extends NodeComponent { + + private static final String name = "c3"; + + @Override + public void process() throws Exception { + Thread.sleep(1_000); + ConcurrentCase.caseAdd((String) getSlot().getRequestData(), new ConcurrentCase.Routers(getSlotIndex(), name)); + System.out.println(String.format("[%s] component executed, index[%d].", name, getSlotIndex())); + } +} diff --git a/liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/mock/component/c/C4Component.java b/liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/mock/component/c/C4Component.java new file mode 100644 index 000000000..d573fc658 --- /dev/null +++ b/liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/mock/component/c/C4Component.java @@ -0,0 +1,26 @@ +package com.yomahub.flowtest.concurrent.mock.component.c; + +import com.yomahub.flowtest.concurrent.ConcurrentCase; +import com.yomahub.liteflow.core.NodeComponent; +import org.springframework.stereotype.Component; + +/** + * desc : + * name : C4 + * + * @author : xujia + * date : 2021/3/25 + * @since : 1.8 + */ +@Component("c4") +public class C4Component extends NodeComponent { + + private static final String name = "c4"; + + @Override + public void process() throws Exception { + Thread.sleep(1_000); + ConcurrentCase.caseAdd((String) getSlot().getRequestData(), new ConcurrentCase.Routers(getSlotIndex(), name)); + System.out.println(String.format("[%s] component executed, index[%d].", name, getSlotIndex())); + } +} \ No newline at end of file diff --git a/liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/mock/component/c/C5Component.java b/liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/mock/component/c/C5Component.java new file mode 100644 index 000000000..29c0a7617 --- /dev/null +++ b/liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/mock/component/c/C5Component.java @@ -0,0 +1,26 @@ +package com.yomahub.flowtest.concurrent.mock.component.c; + +import com.yomahub.flowtest.concurrent.ConcurrentCase; +import com.yomahub.liteflow.core.NodeComponent; +import org.springframework.stereotype.Component; + +/** + * desc : + * name : C5 + * + * @author : xujia + * date : 2021/3/25 + * @since : 1.8 + */ +@Component("c5") +public class C5Component extends NodeComponent { + + private static final String name = "c5"; + + @Override + public void process() throws Exception { + Thread.sleep(1_000); + ConcurrentCase.caseAdd((String) getSlot().getRequestData(), new ConcurrentCase.Routers(getSlotIndex(), name)); + System.out.println(String.format("[%s] component executed, index[%d].", name, getSlotIndex())); + } +} \ No newline at end of file diff --git a/liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/mock/component/c/C6Component.java b/liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/mock/component/c/C6Component.java new file mode 100644 index 000000000..108190689 --- /dev/null +++ b/liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/mock/component/c/C6Component.java @@ -0,0 +1,26 @@ +package com.yomahub.flowtest.concurrent.mock.component.c; + +import com.yomahub.flowtest.concurrent.ConcurrentCase; +import com.yomahub.liteflow.core.NodeComponent; +import org.springframework.stereotype.Component; + +/** + * desc : + * name : C6 + * + * @author : xujia + * date : 2021/3/25 + * @since : 1.8 + */ +@Component("c6") +public class C6Component extends NodeComponent { + + private static final String name = "c6"; + + @Override + public void process() throws Exception { + Thread.sleep(1_000); + ConcurrentCase.caseAdd((String) getSlot().getRequestData(), new ConcurrentCase.Routers(getSlotIndex(), name)); + System.out.println(String.format("[%s] component executed, index[%d].", name, getSlotIndex())); + } +} diff --git a/liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/mock/component/c/C7Component.java b/liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/mock/component/c/C7Component.java new file mode 100644 index 000000000..17d9e6336 --- /dev/null +++ b/liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/mock/component/c/C7Component.java @@ -0,0 +1,26 @@ +package com.yomahub.flowtest.concurrent.mock.component.c; + +import com.yomahub.flowtest.concurrent.ConcurrentCase; +import com.yomahub.liteflow.core.NodeComponent; +import org.springframework.stereotype.Component; + +/** + * desc : + * name : c7 + * + * @author : xujia + * date : 2021/3/25 + * @since : 1.8 + */ +@Component("c7") +public class C7Component extends NodeComponent { + + private static final String name = "c7"; + + @Override + public void process() throws Exception { + Thread.sleep(1_000); + ConcurrentCase.caseAdd((String) getSlot().getRequestData(), new ConcurrentCase.Routers(getSlotIndex(), name)); + System.out.println(String.format("[%s] component executed, index[%d].", name, getSlotIndex())); + } +} diff --git a/liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/mock/component/c/C8Component.java b/liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/mock/component/c/C8Component.java new file mode 100644 index 000000000..eef38003a --- /dev/null +++ b/liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/mock/component/c/C8Component.java @@ -0,0 +1,26 @@ +package com.yomahub.flowtest.concurrent.mock.component.c; + +import com.yomahub.flowtest.concurrent.ConcurrentCase; +import com.yomahub.liteflow.core.NodeComponent; +import org.springframework.stereotype.Component; + +/** + * desc : + * name : C8 + * + * @author : xujia + * date : 2021/3/25 + * @since : 1.8 + */ +@Component("c8") +public class C8Component extends NodeComponent { + + private static final String name = "c8"; + + @Override + public void process() throws Exception { + Thread.sleep(1_000); + ConcurrentCase.caseAdd((String) getSlot().getRequestData(), new ConcurrentCase.Routers(getSlotIndex(), name)); + System.out.println(String.format("[%s] component executed, index[%d].", name, getSlotIndex())); + } +} diff --git a/liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/mock/component/c/C9Component.java b/liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/mock/component/c/C9Component.java new file mode 100644 index 000000000..7ee36f7d7 --- /dev/null +++ b/liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/mock/component/c/C9Component.java @@ -0,0 +1,26 @@ +package com.yomahub.flowtest.concurrent.mock.component.c; + +import com.yomahub.flowtest.concurrent.ConcurrentCase; +import com.yomahub.liteflow.core.NodeComponent; +import org.springframework.stereotype.Component; + +/** + * desc : + * name : C9 + * + * @author : xujia + * date : 2021/3/25 + * @since : 1.8 + */ +@Component("c9") +public class C9Component extends NodeComponent { + + private static final String name = "c9"; + + @Override + public void process() throws Exception { + Thread.sleep(1_000); + ConcurrentCase.caseAdd((String) getSlot().getRequestData(), new ConcurrentCase.Routers(getSlotIndex(), name)); + System.out.println(String.format("[%s] component executed, index[%d].", name, getSlotIndex())); + } +} diff --git a/liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/mock/component/p/P3Component.java b/liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/mock/component/p/P3Component.java new file mode 100644 index 000000000..eae5f65d1 --- /dev/null +++ b/liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/mock/component/p/P3Component.java @@ -0,0 +1,25 @@ +package com.yomahub.flowtest.concurrent.mock.component.p; + +import com.yomahub.flowtest.concurrent.ConcurrentCase; +import com.yomahub.liteflow.core.NodeComponent; +import org.springframework.stereotype.Component; + +/** + * desc : + * name : P3Component + * + * @author : xujia + * date : 2021/3/25 + * @since : 1.8 + */ +@Component("p3") +public class P3Component extends NodeComponent { + + private static final String name = "p3"; + + @Override + public void process() throws Exception { + ConcurrentCase.caseAdd((String) getSlot().getRequestData(), new ConcurrentCase.Routers(getSlotIndex(), name)); + System.out.println(String.format("[%s] component executed, index[%d].", name, getSlotIndex())); + } +} diff --git a/liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/mock/component/p/P4Component.java b/liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/mock/component/p/P4Component.java new file mode 100644 index 000000000..cf7bb188f --- /dev/null +++ b/liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/mock/component/p/P4Component.java @@ -0,0 +1,25 @@ +package com.yomahub.flowtest.concurrent.mock.component.p; + +import com.yomahub.flowtest.concurrent.ConcurrentCase; +import com.yomahub.liteflow.core.NodeComponent; +import org.springframework.stereotype.Component; + +/** + * desc : + * name : P4Component + * + * @author : xujia + * date : 2021/3/25 + * @since : 1.8 + */ +@Component("p4") +public class P4Component extends NodeComponent { + + private static final String name = "p4"; + + @Override + public void process() throws Exception { + ConcurrentCase.caseAdd((String) getSlot().getRequestData(), new ConcurrentCase.Routers(getSlotIndex(), name)); + System.out.println(String.format("[%s] component executed, index[%d].", name, getSlotIndex())); + } +} diff --git a/liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/mock/component/p/P5Component.java b/liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/mock/component/p/P5Component.java new file mode 100644 index 000000000..820944c86 --- /dev/null +++ b/liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/mock/component/p/P5Component.java @@ -0,0 +1,25 @@ +package com.yomahub.flowtest.concurrent.mock.component.p; + +import com.yomahub.flowtest.concurrent.ConcurrentCase; +import com.yomahub.liteflow.core.NodeComponent; +import org.springframework.stereotype.Component; + +/** + * desc : + * name : P5 + * + * @author : xujia + * date : 2021/3/25 + * @since : 1.8 + */ +@Component("p5") +public class P5Component extends NodeComponent { + + private static final String name = "p5"; + + @Override + public void process() throws Exception { + ConcurrentCase.caseAdd((String) getSlot().getRequestData(), new ConcurrentCase.Routers(getSlotIndex(), name)); + System.out.println(String.format("[%s] component executed, index[%d].", name, getSlotIndex())); + } +} \ No newline at end of file diff --git a/liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/mock/component/p/P6Component.java b/liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/mock/component/p/P6Component.java new file mode 100644 index 000000000..be94347e3 --- /dev/null +++ b/liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/mock/component/p/P6Component.java @@ -0,0 +1,25 @@ +package com.yomahub.flowtest.concurrent.mock.component.p; + +import com.yomahub.flowtest.concurrent.ConcurrentCase; +import com.yomahub.liteflow.core.NodeComponent; +import org.springframework.stereotype.Component; + +/** + * desc : + * name : P6 + * + * @author : xujia + * date : 2021/3/25 + * @since : 1.8 + */ +@Component("p6") +public class P6Component extends NodeComponent { + + private static final String name = "p6"; + + @Override + public void process() throws Exception { + ConcurrentCase.caseAdd((String) getSlot().getRequestData(), new ConcurrentCase.Routers(getSlotIndex(), name)); + System.out.println(String.format("[%s] component executed, index[%d].", name, getSlotIndex())); + } +} diff --git a/liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/mock/component/p/P7Component.java b/liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/mock/component/p/P7Component.java new file mode 100644 index 000000000..0c9edd806 --- /dev/null +++ b/liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/mock/component/p/P7Component.java @@ -0,0 +1,25 @@ +package com.yomahub.flowtest.concurrent.mock.component.p; + +import com.yomahub.flowtest.concurrent.ConcurrentCase; +import com.yomahub.liteflow.core.NodeComponent; +import org.springframework.stereotype.Component; + +/** + * desc : + * name : P7Component + * + * @author : xujia + * date : 2021/3/25 + * @since : 1.8 + */ +@Component("p7") +public class P7Component extends NodeComponent { + + private static final String name = "p7"; + + @Override + public void process() throws Exception { + ConcurrentCase.caseAdd((String) getSlot().getRequestData(), new ConcurrentCase.Routers(getSlotIndex(), name)); + System.out.println(String.format("[%s] component executed, index[%d].", name, getSlotIndex())); + } +} diff --git a/liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/mock/component/p/P8Component.java b/liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/mock/component/p/P8Component.java new file mode 100644 index 000000000..5bdf3a7cc --- /dev/null +++ b/liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/mock/component/p/P8Component.java @@ -0,0 +1,25 @@ +package com.yomahub.flowtest.concurrent.mock.component.p; + +import com.yomahub.flowtest.concurrent.ConcurrentCase; +import com.yomahub.liteflow.core.NodeComponent; +import org.springframework.stereotype.Component; + +/** + * desc : + * name : P8Component + * + * @author : xujia + * date : 2021/3/25 + * @since : 1.8 + */ +@Component("p8") +public class P8Component extends NodeComponent { + + private static final String name = "p8"; + + @Override + public void process() throws Exception { + ConcurrentCase.caseAdd((String) getSlot().getRequestData(), new ConcurrentCase.Routers(getSlotIndex(), name)); + System.out.println(String.format("[%s] component executed, index[%d].", name, getSlotIndex())); + } +} \ No newline at end of file diff --git a/liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/mock/component/s/S1Component.java b/liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/mock/component/s/S1Component.java new file mode 100644 index 000000000..01a33d474 --- /dev/null +++ b/liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/mock/component/s/S1Component.java @@ -0,0 +1,25 @@ +package com.yomahub.flowtest.concurrent.mock.component.s; + +import com.yomahub.flowtest.concurrent.ConcurrentCase; +import com.yomahub.liteflow.core.NodeComponent; +import org.springframework.stereotype.Component; + +/** + * desc : + * name : S1Component + * + * @author : xujia + * date : 2021/3/25 + * @since : 1.8 + */ +@Component("s1") +public class S1Component extends NodeComponent { + + private static final String name = "s1"; + + @Override + public void process() throws Exception { + ConcurrentCase.caseAdd((String) getSlot().getRequestData(), new ConcurrentCase.Routers(getSlotIndex(), name)); + System.out.println(String.format("[%s] component executed, index[%d].", name, getSlotIndex())); + } +} diff --git a/liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/mock/component/s/S2Component.java b/liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/mock/component/s/S2Component.java new file mode 100644 index 000000000..6a2aebd45 --- /dev/null +++ b/liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/mock/component/s/S2Component.java @@ -0,0 +1,25 @@ +package com.yomahub.flowtest.concurrent.mock.component.s; + +import com.yomahub.flowtest.concurrent.ConcurrentCase; +import com.yomahub.liteflow.core.NodeComponent; +import org.springframework.stereotype.Component; + +/** + * desc : + * name : S2Component + * + * @author : xujia + * date : 2021/3/25 + * @since : 1.8 + */ +@Component("s2") +public class S2Component extends NodeComponent { + + private static final String name = "s2"; + + @Override + public void process() throws Exception { + ConcurrentCase.caseAdd((String) getSlot().getRequestData(), new ConcurrentCase.Routers(getSlotIndex(), name)); + System.out.println(String.format("[%s] component executed, index[%d].", name, getSlotIndex())); + } +} diff --git a/liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/mock/component/s/S3Component.java b/liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/mock/component/s/S3Component.java new file mode 100644 index 000000000..df52250ae --- /dev/null +++ b/liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/mock/component/s/S3Component.java @@ -0,0 +1,25 @@ +package com.yomahub.flowtest.concurrent.mock.component.s; + +import com.yomahub.flowtest.concurrent.ConcurrentCase; +import com.yomahub.liteflow.core.NodeComponent; +import org.springframework.stereotype.Component; + +/** + * desc : + * name : S3 + * + * @author : xujia + * date : 2021/3/25 + * @since : 1.8 + */ +@Component("s3") +public class S3Component extends NodeComponent { + + private static final String name = "s3"; + + @Override + public void process() throws Exception { + ConcurrentCase.caseAdd((String) getSlot().getRequestData(), new ConcurrentCase.Routers(getSlotIndex(), name)); + System.out.println(String.format("[%s] component executed, index[%d].", name, getSlotIndex())); + } +} \ No newline at end of file diff --git a/liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/mock/component/s/S4Component.java b/liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/mock/component/s/S4Component.java new file mode 100644 index 000000000..a0cb7306a --- /dev/null +++ b/liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/mock/component/s/S4Component.java @@ -0,0 +1,25 @@ +package com.yomahub.flowtest.concurrent.mock.component.s; + +import com.yomahub.flowtest.concurrent.ConcurrentCase; +import com.yomahub.liteflow.core.NodeComponent; +import org.springframework.stereotype.Component; + +/** + * desc : + * name : S4 + * + * @author : xujia + * date : 2021/3/25 + * @since : 1.8 + */ +@Component("s4") +public class S4Component extends NodeComponent { + + private static final String name = "s4"; + + @Override + public void process() throws Exception { + ConcurrentCase.caseAdd((String) getSlot().getRequestData(), new ConcurrentCase.Routers(getSlotIndex(), name)); + System.out.println(String.format("[%s] component executed, index[%d].", name, getSlotIndex())); + } +} diff --git a/liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/mock/component/s/S5Component.java b/liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/mock/component/s/S5Component.java new file mode 100644 index 000000000..4e491d33b --- /dev/null +++ b/liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/mock/component/s/S5Component.java @@ -0,0 +1,25 @@ +package com.yomahub.flowtest.concurrent.mock.component.s; + +import com.yomahub.flowtest.concurrent.ConcurrentCase; +import com.yomahub.liteflow.core.NodeComponent; +import org.springframework.stereotype.Component; + +/** + * desc : + * name : S5 + * + * @author : xujia + * date : 2021/3/25 + * @since : 1.8 + */ +@Component("s5") +public class S5Component extends NodeComponent { + + private static final String name = "s5"; + + @Override + public void process() throws Exception { + ConcurrentCase.caseAdd((String) getSlot().getRequestData(), new ConcurrentCase.Routers(getSlotIndex(), name)); + System.out.println(String.format("[%s] component executed, index[%d].", name, getSlotIndex())); + } +} \ No newline at end of file diff --git a/liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/mock/component/s/S6Component.java b/liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/mock/component/s/S6Component.java new file mode 100644 index 000000000..d7cd20947 --- /dev/null +++ b/liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/mock/component/s/S6Component.java @@ -0,0 +1,25 @@ +package com.yomahub.flowtest.concurrent.mock.component.s; + +import com.yomahub.flowtest.concurrent.ConcurrentCase; +import com.yomahub.liteflow.core.NodeComponent; +import org.springframework.stereotype.Component; + +/** + * desc : + * name : S6 + * + * @author : xujia + * date : 2021/3/25 + * @since : 1.8 + */ +@Component("s6") +public class S6Component extends NodeComponent { + + private static final String name = "s6"; + + @Override + public void process() throws Exception { + ConcurrentCase.caseAdd((String) getSlot().getRequestData(), new ConcurrentCase.Routers(getSlotIndex(), name)); + System.out.println(String.format("[%s] component executed, index[%d].", name, getSlotIndex())); + } +} diff --git a/liteflow-test-springboot/src/test/resources/application-test.yml b/liteflow-test-springboot/src/test/resources/application-test.yml new file mode 100644 index 000000000..a98fcc5ea --- /dev/null +++ b/liteflow-test-springboot/src/test/resources/application-test.yml @@ -0,0 +1,18 @@ +logging: + level: + root: debug + io: + lettuce: info + pattern: + console: "%d{yyyy-MM-dd} %d{hhh:mm:ss},%red(%d{SSS}) %green(%-5level) [%thread] %cyan(%logger{36}) : %msg%n" + +server: + port: 8086 + +liteflow: + rule-source: "config/flow-test.xml" + +threadPool: + parallel: + worker: 3 + queue: 512 diff --git a/liteflow-test-springboot/src/test/resources/config/flow-test.xml b/liteflow-test-springboot/src/test/resources/config/flow-test.xml new file mode 100644 index 000000000..13245b27d --- /dev/null +++ b/liteflow-test-springboot/src/test/resources/config/flow-test.xml @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + From 4b186ef4b3878f398305c2009bda1a0af539cfa0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BE=90=E4=BD=B3?= Date: Fri, 26 Mar 2021 11:36:31 +0800 Subject: [PATCH 02/10] =?UTF-8?q?enhancement=20#I37QVR=20WhenCondition?= =?UTF-8?q?=E6=97=B6=E5=80=99=EF=BC=8C=E5=B9=B6=E5=8F=91=E6=89=A7=E8=A1=8C?= =?UTF-8?q?=E7=9B=AE=E5=89=8D=E4=BC=9A=E6=AF=8F=E6=AC=A1=E6=96=B0=E5=BB=BA?= =?UTF-8?q?=E7=BA=BF=E7=A8=8B=E5=8F=AF=E4=B8=8D=E5=8F=AF=E8=B5=B0=E7=BA=BF?= =?UTF-8?q?=E7=A8=8B=E6=B1=A0=20=E4=BF=AE=E6=AD=A3=E4=BA=86=E6=89=93?= =?UTF-8?q?=E5=8D=B0=E9=94=99=E8=AF=AF=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/java/com/yomahub/liteflow/entity/flow/Chain.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/entity/flow/Chain.java b/liteflow-core/src/main/java/com/yomahub/liteflow/entity/flow/Chain.java index d637428d8..014ccc340 100644 --- a/liteflow-core/src/main/java/com/yomahub/liteflow/entity/flow/Chain.java +++ b/liteflow-core/src/main/java/com/yomahub/liteflow/entity/flow/Chain.java @@ -149,9 +149,9 @@ public class Chain implements Executable { for (Future f : futures) { f.cancel(true); } + LOG.warn("requestId [{}] executing async condition has reached max-wait-seconds, condition canceled and move to next executableItem." + , requestId); } - LOG.warn("requestId [{}] executing async condition has reached max-wait-seconds, condition canceled and move to next executableItem." - , requestId); } catch (InterruptedException e) { // ignore InterruptedException From be6d85c2891b094eced3c2c6a9100bb69cbccde5 Mon Sep 17 00:00:00 2001 From: zendwang Date: Wed, 24 Mar 2021 16:24:21 +0800 Subject: [PATCH 03/10] =?UTF-8?q?enhancement=20#I3CTMQ=20=E6=8A=9B?= =?UTF-8?q?=E5=BC=83org.apache.common=E7=9A=84=E5=8C=85=EF=BC=8C=E4=BE=9D?= =?UTF-8?q?=E8=B5=96hutool?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- liteflow-core/pom.xml | 16 ----- .../yomahub/liteflow/core/FlowExecutor.java | 61 +++++++++---------- .../yomahub/liteflow/core/NodeComponent.java | 49 +++++++-------- .../yomahub/liteflow/entity/data/CmpStep.java | 4 +- .../yomahub/liteflow/entity/data/DataBus.java | 4 +- .../yomahub/liteflow/entity/flow/Chain.java | 19 +++--- .../yomahub/liteflow/entity/flow/Node.java | 17 +++--- .../entity/flow/WhenConditionThread.java | 4 +- .../entity/monitor/CompStatistics.java | 18 +++++- .../com/yomahub/liteflow/flow/FlowBus.java | 8 +-- .../yomahub/liteflow/monitor/MonitorBus.java | 8 +-- .../liteflow/parser/XmlFlowParser.java | 19 +++--- .../parser/ZookeeperXmlFlowParser.java | 6 +- .../liteflow/spring/ComponentScaner.java | 21 ++++--- .../com/yomahub/liteflow/util/LimitQueue.java | 1 - .../yomahub/liteflow/util/SpringAware.java | 12 ++-- .../springboot/LiteflowExecutorInit.java | 1 - .../LiteflowMainAutoConfiguration.java | 22 +++---- .../src/main/resources/applicationContext.xml | 2 +- pom.xml | 24 -------- 20 files changed, 139 insertions(+), 177 deletions(-) diff --git a/liteflow-core/pom.xml b/liteflow-core/pom.xml index a98acb533..bab2fb518 100644 --- a/liteflow-core/pom.xml +++ b/liteflow-core/pom.xml @@ -13,18 +13,6 @@ - - org.apache.commons - commons-lang3 - - - org.apache.commons - commons-collections4 - - - commons-io - commons-io - cn.hutool hutool-core @@ -69,10 +57,6 @@ junit junit - - - commons-logging - commons-logging org.apache.curator 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 6a9ff0bd2..8774fa6c5 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 @@ -9,15 +9,11 @@ package com.yomahub.liteflow.core; import java.text.MessageFormat; import java.util.List; -import java.util.regex.Matcher; -import java.util.regex.Pattern; import cn.hutool.core.util.ObjectUtil; +import cn.hutool.core.util.ReUtil; import cn.hutool.core.util.StrUtil; import com.google.common.collect.Lists; -import com.yomahub.liteflow.exception.ConfigErrorException; -import com.yomahub.liteflow.property.LiteflowConfig; -import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -26,12 +22,14 @@ import com.yomahub.liteflow.entity.data.DataBus; import com.yomahub.liteflow.entity.data.DefaultSlot; import com.yomahub.liteflow.entity.data.Slot; import com.yomahub.liteflow.exception.ChainNotFoundException; +import com.yomahub.liteflow.exception.ConfigErrorException; import com.yomahub.liteflow.exception.FlowExecutorNotInitException; import com.yomahub.liteflow.exception.NoAvailableSlotException; import com.yomahub.liteflow.flow.FlowBus; import com.yomahub.liteflow.parser.LocalXmlFlowParser; import com.yomahub.liteflow.parser.XmlFlowParser; import com.yomahub.liteflow.parser.ZookeeperXmlFlowParser; +import com.yomahub.liteflow.property.LiteflowConfig; /** * 流程规则主要执行器类 @@ -40,7 +38,13 @@ import com.yomahub.liteflow.parser.ZookeeperXmlFlowParser; public class FlowExecutor { private static final Logger LOG = LoggerFactory.getLogger(FlowExecutor.class); - + + private static final String ZK_CONFIG_REGEX = "[\\w\\d][\\w\\d\\.]+\\:(\\d)+(\\,[\\w\\d][\\w\\d\\.]+\\:(\\d)+)*"; + + private static final String LOCAL_CONFIG_REGEX = "^[\\w_\\-\\@\\/]+\\.xml$"; + + private static final String CLASS_CONFIG_REGEX = "^\\w+(\\.\\w+)*$"; + private LiteflowConfig liteflowConfig; private String zkNode; @@ -54,20 +58,19 @@ public class FlowExecutor { List rulePath = Lists.newArrayList(liteflowConfig.getRuleSource().split(",|;")); XmlFlowParser parser = null; - for(String path : rulePath){ + for (String path : rulePath) { try { - - if(isLocalConfig(path)) { //判断是否是本地的xml文件 + if (isLocalConfig(path)) { parser = new LocalXmlFlowParser(); - }else if(isZKConfig(path)){ //判断是否是zk配置 - if(StringUtils.isNotBlank(zkNode)) { + } else if (isZKConfig(path)) { + if (StrUtil.isNotBlank(zkNode)) { parser = new ZookeeperXmlFlowParser(zkNode); - }else { + } else { parser = new ZookeeperXmlFlowParser(); } - }else if(isClassConfig(path)) { //判断是否是自定义配置 + } else if (isClassConfig(path)) { Class c = Class.forName(path); - parser = (XmlFlowParser)c.newInstance(); + parser = (XmlFlowParser) c.newInstance(); } parser.parseMain(path); } catch (Exception e) { @@ -79,21 +82,15 @@ public class FlowExecutor { } private boolean isZKConfig(String path) { - Pattern p = Pattern.compile("[\\w\\d][\\w\\d\\.]+\\:(\\d)+(\\,[\\w\\d][\\w\\d\\.]+\\:(\\d)+)*"); - Matcher m = p.matcher(path); - return m.find(); + return ReUtil.isMatch(ZK_CONFIG_REGEX, path); } private boolean isLocalConfig(String path) { - Pattern p = Pattern.compile("^[\\w_\\-\\@\\/]+\\.xml$"); - Matcher m = p.matcher(path); - return m.find(); + return ReUtil.isMatch(LOCAL_CONFIG_REGEX, path); } private boolean isClassConfig(String path) { - Pattern p = Pattern.compile("^\\w+(\\.\\w+)*$"); - Matcher m = p.matcher(path); - return m.find(); + return ReUtil.isMatch(CLASS_CONFIG_REGEX, path); } public void reloadRule(){ @@ -121,34 +118,34 @@ public class FlowExecutor { Chain chain = FlowBus.getChain(chainId); - if(chain == null){ + if (ObjectUtil.isNull(chain)) { String errorMsg = MessageFormat.format("couldn't find chain with the id[{0}]", chainId); throw new ChainNotFoundException(errorMsg); } - if(!isInnerChain && slotIndex == null) { + if (!isInnerChain && ObjectUtil.isNull(slotIndex)) { slotIndex = DataBus.offerSlot(slotClazz); - LOG.info("slot[{}] offered",slotIndex); + LOG.info("slot[{}] offered", slotIndex); } - if(slotIndex == -1){ + if (slotIndex == -1) { throw new NoAvailableSlotException("there is no available slot"); } slot = DataBus.getSlot(slotIndex); - if(slot == null) { + if (slot == null) { throw new NoAvailableSlotException("the slot is not exist"); } - if(StringUtils.isBlank(slot.getRequestId())) { + if (StrUtil.isBlank(slot.getRequestId())) { slot.generateRequestId(); - LOG.info("requestId[{}] has generated",slot.getRequestId()); + LOG.info("requestId[{}] has generated", slot.getRequestId()); } - if(!isInnerChain) { + if (!isInnerChain) { slot.setRequestData(param); slot.setChainName(chainId); - }else { + } else { slot.setChainReqData(chainId, param); } diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/core/NodeComponent.java b/liteflow-core/src/main/java/com/yomahub/liteflow/core/NodeComponent.java index 8942aa0d7..264c20b3f 100644 --- a/liteflow-core/src/main/java/com/yomahub/liteflow/core/NodeComponent.java +++ b/liteflow-core/src/main/java/com/yomahub/liteflow/core/NodeComponent.java @@ -7,26 +7,26 @@ */ package com.yomahub.liteflow.core; +import cn.hutool.core.date.StopWatch; import cn.hutool.core.util.ObjectUtil; -import com.yomahub.liteflow.entity.flow.Executable; -import com.yomahub.liteflow.spring.ComponentScaner; -import org.apache.commons.lang3.StringUtils; -import org.apache.commons.lang3.time.StopWatch; +import cn.hutool.core.util.StrUtil; + import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; -import com.yomahub.liteflow.entity.flow.Node; import com.yomahub.liteflow.entity.data.CmpStep; import com.yomahub.liteflow.entity.data.CmpStepType; import com.yomahub.liteflow.entity.data.DataBus; import com.yomahub.liteflow.entity.data.Slot; +import com.yomahub.liteflow.entity.flow.Executable; +import com.yomahub.liteflow.entity.flow.Node; import com.yomahub.liteflow.entity.monitor.CompStatistics; import com.yomahub.liteflow.flow.FlowBus; import com.yomahub.liteflow.monitor.MonitorBus; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.lang.Nullable; +import com.yomahub.liteflow.spring.ComponentScaner; + -import javax.annotation.Resource; /** * 普通组件抽象类 @@ -53,39 +53,34 @@ public abstract class NodeComponent { StopWatch stopWatch = new StopWatch(); stopWatch.start(); - //process前置处理 - if(ComponentScaner.cmpAroundAspect != null){ + // process前置处理 + if (ObjectUtil.isNotNull(ComponentScaner.cmpAroundAspect)) { ComponentScaner.cmpAroundAspect.beforeProcess(slot); } - //业务处理逻辑 process(); - //process后置处理 - if(ComponentScaner.cmpAroundAspect != null){ + // process后置处理 + if (ObjectUtil.isNotNull(ComponentScaner.cmpAroundAspect)) { ComponentScaner.cmpAroundAspect.afterProcess(slot); } stopWatch.stop(); - long timeSpent = stopWatch.getTime(); - + // slot.addStep(new CmpStep(nodeId, CmpStepType.END)); - - //性能统计 - CompStatistics statistics = new CompStatistics(); - statistics.setComponentClazzName(this.getClass().getSimpleName()); - statistics.setTimeSpent(timeSpent); - if (ObjectUtil.isNotNull(monitorBus)){ + final long timeSpent = stopWatch.getTotalTimeMillis(); + // 性能统计 + if (ObjectUtil.isNotNull(monitorBus)) { + CompStatistics statistics = new CompStatistics(this.getClass().getSimpleName(), timeSpent); monitorBus.addStatistics(statistics); } - //进行判断是否是条件节点,条件节点最终也会落到node节点或者chain节点上 - if(this instanceof NodeCondComponent){ + if (this instanceof NodeCondComponent) { String condNodeId = slot.getCondResult(this.getClass().getName()); - if(StringUtils.isNotBlank(condNodeId)){ + if (StrUtil.isNotBlank(condNodeId)) { Node thisNode = FlowBus.getNode(nodeId); Executable condExecutor = thisNode.getCondNode(condNodeId); - if(condExecutor != null){ + if (ObjectUtil.isNotNull(condExecutor)) { condExecutor.execute(slotIndexTL.get()); } } @@ -118,9 +113,9 @@ public abstract class NodeComponent { */ public boolean isEnd() { Boolean isEnd = isEndTL.get(); - if(isEnd == null){ + if(ObjectUtil.isNull(isEnd)){ return false; - }else{ + } else { return isEndTL.get(); } } diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/entity/data/CmpStep.java b/liteflow-core/src/main/java/com/yomahub/liteflow/entity/data/CmpStep.java index 7eaa7c14c..3278ceabb 100644 --- a/liteflow-core/src/main/java/com/yomahub/liteflow/entity/data/CmpStep.java +++ b/liteflow-core/src/main/java/com/yomahub/liteflow/entity/data/CmpStep.java @@ -9,6 +9,8 @@ package com.yomahub.liteflow.entity.data; import java.text.MessageFormat; +import cn.hutool.core.util.ObjectUtil; + /** * 组件步骤对象 * @author Bryan.Zhang @@ -52,7 +54,7 @@ public class CmpStep { @Override public boolean equals(Object obj) { - if (obj == null) { + if (ObjectUtil.isNull(obj)) { return false; }else { if(getClass() != obj.getClass()) { diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/entity/data/DataBus.java b/liteflow-core/src/main/java/com/yomahub/liteflow/entity/data/DataBus.java index 0cd59e561..58a0cda91 100644 --- a/liteflow-core/src/main/java/com/yomahub/liteflow/entity/data/DataBus.java +++ b/liteflow-core/src/main/java/com/yomahub/liteflow/entity/data/DataBus.java @@ -41,7 +41,7 @@ public class DataBus { public synchronized static int offerSlot(Class slotClazz){ try{ for(int i = 0; i < slots.length; i++){ - if(slots[i] == null){ + if(ObjectUtil.isNull(slots[i])){ slots[i] = slotClazz.newInstance(); OCCUPY_COUNT.incrementAndGet(); return i; @@ -60,7 +60,7 @@ public class DataBus { } public static void releaseSlot(int slotIndex){ - if(slots[slotIndex] != null){ + if(ObjectUtil.isNotNull(slots[slotIndex])){ LOG.info("[{}]:slot[{}] released",slots[slotIndex].getRequestId(),slotIndex); slots[slotIndex] = null; OCCUPY_COUNT.decrementAndGet(); diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/entity/flow/Chain.java b/liteflow-core/src/main/java/com/yomahub/liteflow/entity/flow/Chain.java index 320b10ee1..6fd7aa363 100644 --- a/liteflow-core/src/main/java/com/yomahub/liteflow/entity/flow/Chain.java +++ b/liteflow-core/src/main/java/com/yomahub/liteflow/entity/flow/Chain.java @@ -8,29 +8,26 @@ */ package com.yomahub.liteflow.entity.flow; +import java.util.List; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; + +import cn.hutool.core.collection.CollUtil; import cn.hutool.core.util.ObjectUtil; + import com.yomahub.liteflow.entity.data.DataBus; import com.yomahub.liteflow.entity.data.Slot; import com.yomahub.liteflow.enums.ExecuteTypeEnum; import com.yomahub.liteflow.exception.FlowSystemException; import com.yomahub.liteflow.property.LiteflowConfig; import com.yomahub.liteflow.util.SpringAware; -import org.apache.commons.collections4.CollectionUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.List; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.TimeUnit; /** * chain对象,实现可执行器 * @author Bryan.Zhang */ public class Chain implements Executable { - - private static final Logger LOG = LoggerFactory.getLogger(Chain.class); - + private String chainName; private List conditionList; @@ -70,7 +67,7 @@ public class Chain implements Executable { //执行chain的主方法 @Override public void execute(Integer slotIndex) throws Exception { - if (CollectionUtils.isEmpty(conditionList)) { + if (CollUtil.isEmpty(conditionList)) { throw new FlowSystemException("no conditionList in this chain[" + chainName + "]"); } diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/entity/flow/Node.java b/liteflow-core/src/main/java/com/yomahub/liteflow/entity/flow/Node.java index a53677c8a..705196eb5 100644 --- a/liteflow-core/src/main/java/com/yomahub/liteflow/entity/flow/Node.java +++ b/liteflow-core/src/main/java/com/yomahub/liteflow/entity/flow/Node.java @@ -11,6 +11,7 @@ import java.text.MessageFormat; import java.util.HashMap; import java.util.Map; +import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.StrUtil; import com.yomahub.liteflow.core.NodeComponent; import com.yomahub.liteflow.entity.data.DataBus; @@ -83,7 +84,7 @@ public class Node implements Executable{ //所有的可执行节点,其实最终都会落到node上来,因为chain中包含的也是node @Override public void execute(Integer slotIndex) throws Exception { - if(instance == null){ + if (ObjectUtil.isNull(instance)) { throw new FlowSystemException("there is no instance for node id " + id); } //每次执行node前,把分配的slot index信息放入threadLocal里 @@ -92,30 +93,30 @@ public class Node implements Executable{ try{ //判断是否可执行,所以isAccess经常作为一个组件进入的实际判断要素,用作检查slot里的参数的完备性 - if(instance.isAccess()){ + if (instance.isAccess()) { //执行业务逻辑的主要入口 instance.execute(); //如果组件覆盖了isEnd方法,或者在在逻辑中主要调用了setEnd(true)的话,流程就会立马结束 - if(instance.isEnd()){ + if (instance.isEnd()) { String errorInfo = StrUtil.format("[{}]:component[{}] lead the chain to end",slot.getRequestId(),instance.getClass().getSimpleName()); throw new ChainEndException(errorInfo); } - }else{ + } else { LOG.info("[{}]:[X]skip component[{}] execution",slot.getRequestId(),instance.getClass().getSimpleName()); } - }catch (Exception e){ + } catch (Exception e) { //如果组件覆盖了isContinueOnError方法,返回为true,那即便出了异常,也会继续流程 - if(instance.isContinueOnError()){ + if (instance.isContinueOnError()) { String errorMsg = MessageFormat.format("[{0}]:component[{1}] cause error,but flow is still go on", slot.getRequestId(),id); LOG.error(errorMsg,e); - }else{ + } else { String errorMsg = MessageFormat.format("[{0}]:component[{1}] cause error,error:{2}",slot.getRequestId(),id,e.getMessage()); LOG.error(errorMsg,e); throw e; } - }finally { + } finally { //移除threadLocal里的信息 instance.removeSlotIndex(); instance.removeIsEnd(); diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/entity/flow/WhenConditionThread.java b/liteflow-core/src/main/java/com/yomahub/liteflow/entity/flow/WhenConditionThread.java index bc42440d0..43574f732 100644 --- a/liteflow-core/src/main/java/com/yomahub/liteflow/entity/flow/WhenConditionThread.java +++ b/liteflow-core/src/main/java/com/yomahub/liteflow/entity/flow/WhenConditionThread.java @@ -32,9 +32,9 @@ public class WhenConditionThread extends Thread { public void run() { try{ executableItem.execute(slotIndex); - }catch(Exception e){ + } catch (Exception e) { LOG.error("item [{}] execute cause error",executableItem.getExecuteName(),e); - }finally{ + } finally { latch.countDown(); } } diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/entity/monitor/CompStatistics.java b/liteflow-core/src/main/java/com/yomahub/liteflow/entity/monitor/CompStatistics.java index ad9c10d2a..70a8ec1a4 100644 --- a/liteflow-core/src/main/java/com/yomahub/liteflow/entity/monitor/CompStatistics.java +++ b/liteflow-core/src/main/java/com/yomahub/liteflow/entity/monitor/CompStatistics.java @@ -19,6 +19,13 @@ public class CompStatistics implements Comparable{ private long memorySpent; + private long recordTime; + + public CompStatistics(String componentClazzName, long timeSpent) { + this.componentClazzName = componentClazzName; + this.timeSpent = timeSpent; + this.recordTime = System.currentTimeMillis(); + } public String getComponentClazzName() { return componentClazzName; } @@ -42,9 +49,16 @@ public class CompStatistics implements Comparable{ public void setMemorySpent(long memorySpent) { this.memorySpent = memorySpent; } - + + public long getRecordTime() { + return recordTime; + } + @Override public int compareTo(Object o) { - return -1; + if( o instanceof CompStatistics) { + return this.recordTime >= ((CompStatistics) o).getRecordTime() ? -1 : 1; + } + return 1; } } diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/flow/FlowBus.java b/liteflow-core/src/main/java/com/yomahub/liteflow/flow/FlowBus.java index f0288b737..4ce599809 100644 --- a/liteflow-core/src/main/java/com/yomahub/liteflow/flow/FlowBus.java +++ b/liteflow-core/src/main/java/com/yomahub/liteflow/flow/FlowBus.java @@ -10,7 +10,7 @@ package com.yomahub.liteflow.flow; import java.util.HashMap; import java.util.Map; -import org.apache.commons.collections4.MapUtils; +import cn.hutool.core.map.MapUtil; import com.yomahub.liteflow.entity.flow.Chain; import com.yomahub.liteflow.entity.flow.Node; @@ -29,7 +29,7 @@ public class FlowBus { } public static Chain getChain(String id) throws Exception { - if (MapUtils.isEmpty(chainMap)) { + if (MapUtil.isEmpty(chainMap)) { throw new Exception("please config the rule first"); } return chainMap.get(id); @@ -44,10 +44,10 @@ public class FlowBus { } public static boolean needInit() { - return MapUtils.isEmpty(chainMap); + return MapUtil.isEmpty(chainMap); } - public static boolean containNode(String nodeId){ + public static boolean containNode(String nodeId) { return nodeMap.containsKey(nodeId); } diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/monitor/MonitorBus.java b/liteflow-core/src/main/java/com/yomahub/liteflow/monitor/MonitorBus.java index d7b6e4242..40d7e7542 100644 --- a/liteflow-core/src/main/java/com/yomahub/liteflow/monitor/MonitorBus.java +++ b/liteflow-core/src/main/java/com/yomahub/liteflow/monitor/MonitorBus.java @@ -12,22 +12,22 @@ import java.math.RoundingMode; import java.text.MessageFormat; import java.util.ArrayList; import java.util.Collections; -import java.util.Comparator; import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.TimerTask; import java.util.Map.Entry; import java.util.Timer; import java.util.concurrent.ConcurrentHashMap; -import cn.hutool.core.collection.BoundedPriorityQueue; import cn.hutool.core.util.ObjectUtil; -import com.yomahub.liteflow.property.LiteflowConfig; +import cn.hutool.core.collection.BoundedPriorityQueue; + import org.slf4j.Logger; import org.slf4j.LoggerFactory; + import com.yomahub.liteflow.entity.data.DataBus; +import com.yomahub.liteflow.property.LiteflowConfig; import com.yomahub.liteflow.entity.monitor.CompStatistics; /** diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/parser/XmlFlowParser.java b/liteflow-core/src/main/java/com/yomahub/liteflow/parser/XmlFlowParser.java index 372524838..66844eb12 100644 --- a/liteflow-core/src/main/java/com/yomahub/liteflow/parser/XmlFlowParser.java +++ b/liteflow-core/src/main/java/com/yomahub/liteflow/parser/XmlFlowParser.java @@ -7,21 +7,26 @@ import java.util.Map.Entry; import java.util.regex.Matcher; import java.util.regex.Pattern; -import cn.hutool.core.util.StrUtil; -import com.yomahub.liteflow.entity.flow.*; -import com.yomahub.liteflow.exception.ExecutableItemNotFoundException; -import com.yomahub.liteflow.exception.ParseException; -import com.yomahub.liteflow.util.SpringAware; -import org.apache.commons.lang3.StringUtils; import org.dom4j.Document; import org.dom4j.DocumentHelper; import org.dom4j.Element; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import cn.hutool.core.util.StrUtil; + import com.yomahub.liteflow.core.NodeComponent; +import com.yomahub.liteflow.entity.flow.Chain; +import com.yomahub.liteflow.entity.flow.Condition; +import com.yomahub.liteflow.entity.flow.Executable; +import com.yomahub.liteflow.entity.flow.Node; +import com.yomahub.liteflow.entity.flow.ThenCondition; +import com.yomahub.liteflow.entity.flow.WhenCondition; +import com.yomahub.liteflow.exception.ExecutableItemNotFoundException; +import com.yomahub.liteflow.exception.ParseException; import com.yomahub.liteflow.flow.FlowBus; import com.yomahub.liteflow.spring.ComponentScaner; +import com.yomahub.liteflow.util.SpringAware; /** * xml形式的解析器 @@ -100,7 +105,7 @@ public abstract class XmlFlowParser { for (Iterator it = e.elementIterator(); it.hasNext();) { Element condE = it.next(); condArrayStr = condE.attributeValue("value"); - if (StringUtils.isBlank(condArrayStr)) { + if (StrUtil.isBlank(condArrayStr)) { continue; } chainNodeList = new ArrayList<>(); diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/parser/ZookeeperXmlFlowParser.java b/liteflow-core/src/main/java/com/yomahub/liteflow/parser/ZookeeperXmlFlowParser.java index c1be7e1f1..a5ac76a7d 100644 --- a/liteflow-core/src/main/java/com/yomahub/liteflow/parser/ZookeeperXmlFlowParser.java +++ b/liteflow-core/src/main/java/com/yomahub/liteflow/parser/ZookeeperXmlFlowParser.java @@ -2,7 +2,8 @@ package com.yomahub.liteflow.parser; import java.text.MessageFormat; -import org.apache.commons.lang3.StringUtils; +import cn.hutool.core.util.StrUtil; + import org.apache.curator.framework.CuratorFramework; import org.apache.curator.framework.CuratorFrameworkFactory; import org.apache.curator.framework.recipes.cache.NodeCache; @@ -10,6 +11,7 @@ import org.apache.curator.framework.recipes.cache.NodeCacheListener; import org.apache.curator.retry.RetryNTimes; import org.slf4j.Logger; import org.slf4j.LoggerFactory; + import com.yomahub.liteflow.exception.ParseException; /** @@ -45,7 +47,7 @@ public class ZookeeperXmlFlowParser extends XmlFlowParser{ String content = new String(client.getData().forPath(nodePath)); - if(StringUtils.isBlank(content)) { + if (StrUtil.isBlank(content)) { String error = MessageFormat.format("the node[{0}] value is empty", nodePath); throw new ParseException(error); } diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/spring/ComponentScaner.java b/liteflow-core/src/main/java/com/yomahub/liteflow/spring/ComponentScaner.java index 9375dcf99..2eafea230 100644 --- a/liteflow-core/src/main/java/com/yomahub/liteflow/spring/ComponentScaner.java +++ b/liteflow-core/src/main/java/com/yomahub/liteflow/spring/ComponentScaner.java @@ -10,13 +10,14 @@ package com.yomahub.liteflow.spring; import java.util.HashMap; import java.util.Map; -import com.yomahub.liteflow.aop.ICmpAroundAspect; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.BeansException; import org.springframework.beans.factory.config.BeanPostProcessor; import org.springframework.core.Ordered; import org.springframework.core.PriorityOrdered; + +import com.yomahub.liteflow.aop.ICmpAroundAspect; import com.yomahub.liteflow.core.NodeComponent; import com.yomahub.liteflow.util.LOGOPrinter; @@ -33,7 +34,7 @@ public class ComponentScaner implements BeanPostProcessor, PriorityOrdered { public static ICmpAroundAspect cmpAroundAspect; static { - //打印liteflow的LOGO + // 打印liteflow的LOGO LOGOPrinter.print(); } @@ -46,18 +47,18 @@ public class ComponentScaner implements BeanPostProcessor, PriorityOrdered { @Override public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { Class clazz = bean.getClass(); - //组件的扫描发现,扫到之后缓存到类属性map中 - if(NodeComponent.class.isAssignableFrom(clazz)){ - LOG.info("component[{}] has been found",beanName); - NodeComponent nodeComponent = (NodeComponent)bean; + // 组件的扫描发现,扫到之后缓存到类属性map中 + if (NodeComponent.class.isAssignableFrom(clazz)) { + LOG.info("component[{}] has been found", beanName); + NodeComponent nodeComponent = (NodeComponent) bean; nodeComponent.setNodeId(beanName); nodeComponentMap.put(beanName, nodeComponent); } - //组件Aop的实现类加载 - if(ICmpAroundAspect.class.isAssignableFrom(clazz)){ - LOG.info("component aspect implement[{}] has been found",beanName); - cmpAroundAspect = (ICmpAroundAspect)bean; + // 组件Aop的实现类加载 + if (ICmpAroundAspect.class.isAssignableFrom(clazz)) { + LOG.info("component aspect implement[{}] has been found", beanName); + cmpAroundAspect = (ICmpAroundAspect) bean; } return bean; diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/util/LimitQueue.java b/liteflow-core/src/main/java/com/yomahub/liteflow/util/LimitQueue.java index 13c4a3861..b4a889990 100644 --- a/liteflow-core/src/main/java/com/yomahub/liteflow/util/LimitQueue.java +++ b/liteflow-core/src/main/java/com/yomahub/liteflow/util/LimitQueue.java @@ -9,7 +9,6 @@ package com.yomahub.liteflow.util; import java.util.Collection; import java.util.Iterator; -import java.util.LinkedList; import java.util.Queue; import java.util.concurrent.ConcurrentLinkedQueue; diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/util/SpringAware.java b/liteflow-core/src/main/java/com/yomahub/liteflow/util/SpringAware.java index a0bedede6..73a94d17b 100644 --- a/liteflow-core/src/main/java/com/yomahub/liteflow/util/SpringAware.java +++ b/liteflow-core/src/main/java/com/yomahub/liteflow/util/SpringAware.java @@ -1,7 +1,5 @@ package com.yomahub.liteflow.util; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import org.springframework.beans.BeansException; import org.springframework.beans.factory.NoSuchBeanDefinitionException; import org.springframework.beans.factory.config.BeanDefinition; @@ -15,7 +13,7 @@ import org.springframework.context.ApplicationContextAware; * @author Bryan.Zhang */ public class SpringAware implements ApplicationContextAware { - private static final Logger log = LoggerFactory.getLogger(SpringAware.class); + private static ApplicationContext applicationContext = null; public SpringAware() { @@ -45,12 +43,12 @@ public class SpringAware implements ApplicationContextAware { return getBean(c.getName()); } - public static T registerOrGet(Class clazz){ + public static T registerOrGet(Class clazz) { T t = null; - try{ + try { t = SpringAware.getBean(clazz); - }catch (NoSuchBeanDefinitionException e){ - if(t == null){ + } catch (NoSuchBeanDefinitionException e) { + if (t == null) { t = SpringAware.registerBean(clazz); } } diff --git a/liteflow-spring-boot-starter/src/main/java/com/yomahub/liteflow/springboot/LiteflowExecutorInit.java b/liteflow-spring-boot-starter/src/main/java/com/yomahub/liteflow/springboot/LiteflowExecutorInit.java index 6099211ce..de3a6bd79 100644 --- a/liteflow-spring-boot-starter/src/main/java/com/yomahub/liteflow/springboot/LiteflowExecutorInit.java +++ b/liteflow-spring-boot-starter/src/main/java/com/yomahub/liteflow/springboot/LiteflowExecutorInit.java @@ -2,7 +2,6 @@ package com.yomahub.liteflow.springboot; import com.yomahub.liteflow.core.FlowExecutor; import org.springframework.beans.factory.InitializingBean; -import javax.annotation.Resource; /** * 执行器初始化类 diff --git a/liteflow-spring-boot-starter/src/main/java/com/yomahub/liteflow/springboot/LiteflowMainAutoConfiguration.java b/liteflow-spring-boot-starter/src/main/java/com/yomahub/liteflow/springboot/LiteflowMainAutoConfiguration.java index 3fe8a8a69..bc1c72eb3 100644 --- a/liteflow-spring-boot-starter/src/main/java/com/yomahub/liteflow/springboot/LiteflowMainAutoConfiguration.java +++ b/liteflow-spring-boot-starter/src/main/java/com/yomahub/liteflow/springboot/LiteflowMainAutoConfiguration.java @@ -1,25 +1,17 @@ package com.yomahub.liteflow.springboot; import cn.hutool.core.util.StrUtil; -import com.google.common.collect.Lists; + import com.yomahub.liteflow.core.FlowExecutor; -import com.yomahub.liteflow.entity.data.DataBus; import com.yomahub.liteflow.monitor.MonitorBus; import com.yomahub.liteflow.property.LiteflowConfig; -import com.yomahub.liteflow.spring.ComponentScaner; import com.yomahub.liteflow.util.SpringAware; -import org.apache.commons.lang3.StringUtils; + import org.springframework.boot.autoconfigure.AutoConfigureAfter; import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; -import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; -import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; -import org.springframework.context.annotation.PropertySource; - -import javax.swing.*; -import java.util.List; /** * 主要的业务装配器 @@ -34,23 +26,23 @@ import java.util.List; public class LiteflowMainAutoConfiguration { @Bean - public FlowExecutor flowExecutor(LiteflowConfig liteflowConfig){ - if(StrUtil.isNotBlank(liteflowConfig.getRuleSource())){ + public FlowExecutor flowExecutor(LiteflowConfig liteflowConfig) { + if (StrUtil.isNotBlank(liteflowConfig.getRuleSource())) { FlowExecutor flowExecutor = new FlowExecutor(); flowExecutor.setLiteflowConfig(liteflowConfig); return flowExecutor; - }else{ + } else { return null; } } @Bean - public LiteflowExecutorInit liteflowExecutorInit(FlowExecutor flowExecutor){ + public LiteflowExecutorInit liteflowExecutorInit(FlowExecutor flowExecutor) { return new LiteflowExecutorInit(flowExecutor); } @Bean - public MonitorBus monitorBus(LiteflowConfig liteflowConfig){ + public MonitorBus monitorBus(LiteflowConfig liteflowConfig) { return new MonitorBus(liteflowConfig); } } diff --git a/liteflow-test-spring/src/main/resources/applicationContext.xml b/liteflow-test-spring/src/main/resources/applicationContext.xml index 944baa722..cb763da99 100644 --- a/liteflow-test-spring/src/main/resources/applicationContext.xml +++ b/liteflow-test-spring/src/main/resources/applicationContext.xml @@ -16,7 +16,7 @@ - + diff --git a/pom.xml b/pom.xml index 3370bfacb..3a25ea5cf 100644 --- a/pom.xml +++ b/pom.xml @@ -41,10 +41,6 @@ UTF-8 1.8 - 3.4 - 4.1 - 2.4 - 1.2 5.0.9.RELEASE 1.7.21 1.2.17 @@ -59,21 +55,6 @@ - - org.apache.commons - commons-lang3 - ${commons.lang3.version} - - - org.apache.commons - commons-collections4 - ${commons-collections.version} - - - commons-io - commons-io - ${commons-io.version} - org.springframework spring-beans @@ -118,11 +99,6 @@ junit junit ${junit.version} - - - commons-logging - commons-logging - ${commons-logging.version} org.apache.curator From c6545469f66afbba954cc9113297df001f5bb3cf Mon Sep 17 00:00:00 2001 From: zendwang Date: Fri, 26 Mar 2021 16:46:37 +0800 Subject: [PATCH 04/10] =?UTF-8?q?bug=20#I3CT9A=20=E7=9B=91=E6=8E=A7?= =?UTF-8?q?=E6=89=93=E5=8D=B0=E7=9A=84=E8=80=97=E6=97=B6=E4=B8=8D=E5=87=86?= =?UTF-8?q?=E7=A1=AE=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../yomahub/liteflow/monitor/MonitorBus.java | 5 ++-- .../monitor/BoundedPriorityQueueTest.java | 28 +++++++++++++++++++ 2 files changed, 30 insertions(+), 3 deletions(-) create mode 100644 liteflow-core/src/test/java/com/yomahub/liteflow/monitor/BoundedPriorityQueueTest.java diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/monitor/MonitorBus.java b/liteflow-core/src/main/java/com/yomahub/liteflow/monitor/MonitorBus.java index 40d7e7542..b1333577b 100644 --- a/liteflow-core/src/main/java/com/yomahub/liteflow/monitor/MonitorBus.java +++ b/liteflow-core/src/main/java/com/yomahub/liteflow/monitor/MonitorBus.java @@ -88,10 +88,9 @@ public class MonitorBus { public void printStatistics(){ try{ Map compAverageTimeSpent = new HashMap(); - - long totalTimeSpent = 0; - + for(Entry> entry : statisticsMap.entrySet()){ + long totalTimeSpent = 0; for(CompStatistics statistics : entry.getValue()){ totalTimeSpent += statistics.getTimeSpent(); } diff --git a/liteflow-core/src/test/java/com/yomahub/liteflow/monitor/BoundedPriorityQueueTest.java b/liteflow-core/src/test/java/com/yomahub/liteflow/monitor/BoundedPriorityQueueTest.java new file mode 100644 index 000000000..a705ba105 --- /dev/null +++ b/liteflow-core/src/test/java/com/yomahub/liteflow/monitor/BoundedPriorityQueueTest.java @@ -0,0 +1,28 @@ +package com.yomahub.liteflow.monitor; + +import java.util.Iterator; +import java.util.PriorityQueue; +import cn.hutool.core.collection.BoundedPriorityQueue; +import cn.hutool.core.util.RandomUtil; +import org.junit.Test; + +import com.yomahub.liteflow.entity.monitor.CompStatistics; + +public class BoundedPriorityQueueTest { + + @Test + public void test() throws InterruptedException { + PriorityQueue queue = new BoundedPriorityQueue<>(6); + for (int i = 0; i < 20 ; i ++) { + long randomTime = RandomUtil.randomLong(20); + Thread.sleep(randomTime); + queue.add(new CompStatistics("comp" + i, randomTime)); + } + + Iterator iterator = queue.iterator(); + while(iterator.hasNext()) { + CompStatistics compStatistics = iterator.next(); + System.out.println(compStatistics.getComponentClazzName() + " " + compStatistics.getTimeSpent()); + } + } +} From 300dd49c62b8b498af693daad02696387b033afb Mon Sep 17 00:00:00 2001 From: zendwang Date: Fri, 26 Mar 2021 17:05:05 +0800 Subject: [PATCH 05/10] =?UTF-8?q?enhancement=20#I3CTUK=20=E6=AF=8F?= =?UTF-8?q?=E4=B8=AA=E7=BB=84=E4=BB=B6=E7=9A=84=E5=AF=B9slot=20index?= =?UTF-8?q?=E7=9A=84=E5=AD=98=E5=82=A8=EF=BC=8C=E6=8D=A2=E6=88=90=E9=98=BF?= =?UTF-8?q?=E9=87=8C=E7=9A=84TTL?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- liteflow-core/pom.xml | 4 ++++ .../java/com/yomahub/liteflow/core/NodeComponent.java | 8 +++----- pom.xml | 6 ++++++ 3 files changed, 13 insertions(+), 5 deletions(-) diff --git a/liteflow-core/pom.xml b/liteflow-core/pom.xml index bab2fb518..1cd1e781b 100644 --- a/liteflow-core/pom.xml +++ b/liteflow-core/pom.xml @@ -76,5 +76,9 @@ org.apache.curator curator-recipes + + com.alibaba + transmittable-thread-local + diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/core/NodeComponent.java b/liteflow-core/src/main/java/com/yomahub/liteflow/core/NodeComponent.java index 264c20b3f..927e4a17a 100644 --- a/liteflow-core/src/main/java/com/yomahub/liteflow/core/NodeComponent.java +++ b/liteflow-core/src/main/java/com/yomahub/liteflow/core/NodeComponent.java @@ -10,7 +10,7 @@ package com.yomahub.liteflow.core; import cn.hutool.core.date.StopWatch; import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.StrUtil; - +import com.alibaba.ttl.TransmittableThreadLocal; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -26,8 +26,6 @@ import com.yomahub.liteflow.flow.FlowBus; import com.yomahub.liteflow.monitor.MonitorBus; import com.yomahub.liteflow.spring.ComponentScaner; - - /** * 普通组件抽象类 * @author Bryan.Zhang @@ -36,7 +34,7 @@ public abstract class NodeComponent { private static final Logger LOG = LoggerFactory.getLogger(NodeComponent.class); - private InheritableThreadLocal slotIndexTL = new InheritableThreadLocal(); + private TransmittableThreadLocal slotIndexTL = new TransmittableThreadLocal(); @Autowired(required = false) private MonitorBus monitorBus; @@ -44,7 +42,7 @@ public abstract class NodeComponent { private String nodeId; //是否结束整个流程,这个只对串行流程有效,并行流程无效 - private InheritableThreadLocal isEndTL = new InheritableThreadLocal<>(); + private TransmittableThreadLocal isEndTL = new TransmittableThreadLocal<>(); public void execute() throws Exception{ Slot slot = this.getSlot(); diff --git a/pom.xml b/pom.xml index 3a25ea5cf..9ab409d0e 100644 --- a/pom.xml +++ b/pom.xml @@ -51,6 +51,7 @@ 2.12.0 4.12 5.3.10 + 2.12.1 @@ -125,6 +126,11 @@ hutool-core ${hutool-core.version} + + com.alibaba + transmittable-thread-local + ${transmittable-thread-local.version} + From e41db2e7b8713ab9dc568ead40f362b0f9777f1e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BE=90=E4=BD=B3?= Date: Fri, 26 Mar 2021 18:47:05 +0800 Subject: [PATCH 06/10] =?UTF-8?q?enhancement=20#I37QVR=20WhenCondition?= =?UTF-8?q?=E6=97=B6=E5=80=99=EF=BC=8C=E5=B9=B6=E5=8F=91=E6=89=A7=E8=A1=8C?= =?UTF-8?q?=E7=9B=AE=E5=89=8D=E4=BC=9A=E6=AF=8F=E6=AC=A1=E6=96=B0=E5=BB=BA?= =?UTF-8?q?=E7=BA=BF=E7=A8=8B=E5=8F=AF=E4=B8=8D=E5=8F=AF=E8=B5=B0=E7=BA=BF?= =?UTF-8?q?=E7=A8=8B=E6=B1=A0=20=E4=BF=AE=E6=AD=A3=E4=BA=86=E6=89=93?= =?UTF-8?q?=E5=8D=B0=E9=94=99=E8=AF=AF=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../yomahub/liteflow/core/FlowExecutor.java | 13 ------- .../yomahub/liteflow/entity/flow/Chain.java | 34 +++-------------- .../liteflow/entity/flow/WhenCondition.java | 13 ------- .../liteflow/parser/XmlFlowParser.java | 11 +----- .../liteflow/property/LiteflowConfig.java | 22 +++++++++++ .../yomahub/liteflow/util/ExecutorHelper.java | 16 +++++--- .../LiteflowExecutorAutoConfiguration.java | 30 +++++++-------- .../LiteflowMainAutoConfiguration.java | 16 +------- .../liteflow/springboot/LiteflowProperty.java | 22 +++++++++++ .../LiteflowPropertyAutoConfiguration.java | 2 + .../yomahub/liteflow/springboot/Shutdown.java | 19 ++++------ .../META-INF/liteflow-default.properties | 4 +- .../src/main/resources/applicationContext.xml | 5 +++ .../flowtest/concurrent/ConcurrentCase.java | 9 +---- .../flowtest/concurrent/SpringBootApp.java | 8 +--- .../flowtest/concurrent/TestParseFlow.java | 38 ++++++++----------- .../flowtest/concurrent/TestRunFlow.java | 8 +--- .../mock/component/c/C10Component.java | 8 +--- .../mock/component/c/C1Component.java | 8 +--- .../mock/component/c/C2Component.java | 8 +--- .../mock/component/c/C3Component.java | 8 +--- .../mock/component/c/C4Component.java | 8 +--- .../mock/component/c/C5Component.java | 8 +--- .../mock/component/c/C6Component.java | 8 +--- .../mock/component/c/C7Component.java | 8 +--- .../mock/component/c/C8Component.java | 8 +--- .../mock/component/c/C9Component.java | 8 +--- .../mock/component/p/P3Component.java | 8 +--- .../mock/component/p/P4Component.java | 8 +--- .../mock/component/p/P5Component.java | 8 +--- .../mock/component/p/P6Component.java | 8 +--- .../mock/component/p/P7Component.java | 8 +--- .../mock/component/p/P8Component.java | 8 +--- .../mock/component/s/S1Component.java | 8 +--- .../mock/component/s/S2Component.java | 8 +--- .../mock/component/s/S3Component.java | 8 +--- .../mock/component/s/S4Component.java | 8 +--- .../mock/component/s/S5Component.java | 8 +--- .../mock/component/s/S6Component.java | 8 +--- .../src/test/resources/config/flow-test.xml | 8 ++-- 40 files changed, 165 insertions(+), 289 deletions(-) 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 fc8a09c4a..3e3bc8db1 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 @@ -45,8 +45,6 @@ public class FlowExecutor { private LiteflowConfig liteflowConfig; - private ExecutorService parallelExecutor; - private String zkNode; //FlowExecutor的初始化化方式,主要用于parse规则文件 @@ -130,10 +128,6 @@ public class FlowExecutor { throw new ChainNotFoundException(errorMsg); } - if (parallelExecutor != null) { - chain.setParallelExecutor(parallelExecutor); - } - if(!isInnerChain && slotIndex == null) { slotIndex = DataBus.offerSlot(slotClazz); LOG.info("slot[{}] offered",slotIndex); @@ -192,11 +186,4 @@ public class FlowExecutor { this.liteflowConfig = liteflowConfig; } - public ExecutorService getParallelExecutor() { - return parallelExecutor; - } - - public void setParallelExecutor(ExecutorService parallelExecutor) { - this.parallelExecutor = parallelExecutor; - } } diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/entity/flow/Chain.java b/liteflow-core/src/main/java/com/yomahub/liteflow/entity/flow/Chain.java index 014ccc340..f6433dc7c 100644 --- a/liteflow-core/src/main/java/com/yomahub/liteflow/entity/flow/Chain.java +++ b/liteflow-core/src/main/java/com/yomahub/liteflow/entity/flow/Chain.java @@ -40,8 +40,6 @@ public class Chain implements Executable { private static int whenMaxWaitSeconds; - private ExecutorService parallelExecutor; - static { LiteflowConfig liteflowConfig = SpringAware.getBean(LiteflowConfig.class); if (ObjectUtil.isNotNull(liteflowConfig)) { @@ -56,14 +54,6 @@ public class Chain implements Executable { this.conditionList = conditionList; } - public ExecutorService getParallelExecutor() { - return parallelExecutor; - } - - public void setParallelExecutor(ExecutorService parallelExecutor) { - this.parallelExecutor = parallelExecutor; - } - public List getConditionList() { return conditionList; } @@ -101,18 +91,8 @@ public class Chain implements Executable { } } } else if (condition instanceof WhenCondition) { - /** - for (Executable executableItem : condition.getNodeList()) { - * 设置了线程池且当前condition isSync = true时,使用异步线程池执行 - new WhenConditionThread(executableItem, slotIndex, slot.getRequestId(), latch).start(); - */ - if (((WhenCondition) condition).isASync() && parallelExecutor != null) { - executeAsyncCondition((WhenCondition) condition, slotIndex, slot.getRequestId()); - } else { - for (Executable executableItem : condition.getNodeList()) { - executableItem.execute(slotIndex); - } - } + + executeAsyncCondition((WhenCondition) condition, slotIndex, slot.getRequestId()); } } } @@ -128,16 +108,14 @@ public class Chain implements Executable { } - /** - * 使用线程池执行并发流程 - * @param condition - * @param slotIndex - * @param requestId - */ + // 使用线程池执行when并发流程 private void executeAsyncCondition(WhenCondition condition, Integer slotIndex, String requestId) { + ExecutorService parallelExecutor = SpringAware.getBean(ExecutorService.class); + final CountDownLatch latch = new CountDownLatch(condition.getNodeList().size()); final List> futures = new ArrayList<>(condition.getNodeList().size()); + for (int i = 0; i < condition.getNodeList().size(); i++) { futures.add(parallelExecutor.submit( new ParallelCondition(condition.getNodeList().get(i), slotIndex, requestId, latch) diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/entity/flow/WhenCondition.java b/liteflow-core/src/main/java/com/yomahub/liteflow/entity/flow/WhenCondition.java index da80489a5..b2ccd929c 100644 --- a/liteflow-core/src/main/java/com/yomahub/liteflow/entity/flow/WhenCondition.java +++ b/liteflow-core/src/main/java/com/yomahub/liteflow/entity/flow/WhenCondition.java @@ -14,21 +14,8 @@ import java.util.List; * @author Bryan.Zhang */ public class WhenCondition extends Condition{ - /** - * 增加isSync属性,以区分是循序执行还是并发执行 - */ - private boolean isASync; public WhenCondition(List nodeList) { super(nodeList); - isASync = true; - } - public WhenCondition(List nodeList, boolean isASync) { - super(nodeList); - this.isASync = isASync; - } - - public boolean isASync() { - return isASync; } } diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/parser/XmlFlowParser.java b/liteflow-core/src/main/java/com/yomahub/liteflow/parser/XmlFlowParser.java index 606c5cddf..372524838 100644 --- a/liteflow-core/src/main/java/com/yomahub/liteflow/parser/XmlFlowParser.java +++ b/liteflow-core/src/main/java/com/yomahub/liteflow/parser/XmlFlowParser.java @@ -22,7 +22,6 @@ import org.slf4j.LoggerFactory; import com.yomahub.liteflow.core.NodeComponent; import com.yomahub.liteflow.flow.FlowBus; import com.yomahub.liteflow.spring.ComponentScaner; -import org.dom4j.Attribute; /** * xml形式的解析器 @@ -140,15 +139,7 @@ public abstract class XmlFlowParser { if (condE.getName().equals("then")) { conditionList.add(new ThenCondition(chainNodeList)); } else if (condE.getName().equals("when")) { - /** - * 设置是否为async异步 - */ - Attribute isSync = condE.attribute("async"); - if (isSync != null) { - conditionList.add(new WhenCondition(chainNodeList, isSync.getValue().equals("true"))); - } else { - conditionList.add(new WhenCondition(chainNodeList)); - } + conditionList.add(new WhenCondition(chainNodeList)); } } FlowBus.addChain(chainName, new Chain(chainName,conditionList)); diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/property/LiteflowConfig.java b/liteflow-core/src/main/java/com/yomahub/liteflow/property/LiteflowConfig.java index 513704519..12b62aef3 100644 --- a/liteflow-core/src/main/java/com/yomahub/liteflow/property/LiteflowConfig.java +++ b/liteflow-core/src/main/java/com/yomahub/liteflow/property/LiteflowConfig.java @@ -34,6 +34,12 @@ public class LiteflowConfig { //每隔多少秒打印 private Long period; + //异步线程池最大线程数 + private int whenMaxWorkers; + + //异步线程池最大队列数量 + private int whenQueueLimit; + public String getRuleSource() { return ruleSource; } @@ -89,4 +95,20 @@ public class LiteflowConfig { public void setEnableLog(Boolean enableLog) { this.enableLog = enableLog; } + + public int getWhenMaxWorkers() { + return whenMaxWorkers; + } + + public void setWhenMaxWorkers(int whenMaxWorkers) { + this.whenMaxWorkers = whenMaxWorkers; + } + + public int getWhenQueueLimit() { + return whenQueueLimit; + } + + public void setWhenQueueLimit(int whenQueueLimit) { + this.whenQueueLimit = whenQueueLimit; + } } diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/util/ExecutorHelper.java b/liteflow-core/src/main/java/com/yomahub/liteflow/util/ExecutorHelper.java index 7438ea303..a381ec7cb 100644 --- a/liteflow-core/src/main/java/com/yomahub/liteflow/util/ExecutorHelper.java +++ b/liteflow-core/src/main/java/com/yomahub/liteflow/util/ExecutorHelper.java @@ -1,15 +1,19 @@ +/** + *

Title: liteflow

+ *

Description: 轻量级的组件式流程框架

+ * @author Bryan.Zhang + * @email weenyc31@163.com + * @Date 2020/4/1 + */ package com.yomahub.liteflow.util; import java.util.concurrent.*; import java.util.concurrent.atomic.AtomicLong; + /** - * desc : - * name : ExecutorHelper - * - * @author : xujia - * date : 2021/3/24 - * @since : 1.8 + * 线程池工具类 + * @author justin.xu */ public class ExecutorHelper { diff --git a/liteflow-spring-boot-starter/src/main/java/com/yomahub/liteflow/springboot/LiteflowExecutorAutoConfiguration.java b/liteflow-spring-boot-starter/src/main/java/com/yomahub/liteflow/springboot/LiteflowExecutorAutoConfiguration.java index 1a337697f..6f6785e3b 100644 --- a/liteflow-spring-boot-starter/src/main/java/com/yomahub/liteflow/springboot/LiteflowExecutorAutoConfiguration.java +++ b/liteflow-spring-boot-starter/src/main/java/com/yomahub/liteflow/springboot/LiteflowExecutorAutoConfiguration.java @@ -1,30 +1,28 @@ package com.yomahub.liteflow.springboot; -import org.springframework.beans.factory.annotation.Value; +import com.yomahub.liteflow.property.LiteflowConfig; +import com.yomahub.liteflow.util.ExecutorHelper; +import org.springframework.boot.autoconfigure.AutoConfigureAfter; +import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import java.util.concurrent.ExecutorService; -import static com.yomahub.liteflow.util.ExecutorHelper.buildExecutor; - /** - * desc : - * name : LiteflowExecutorAutoConfiguration - * - * @author : xujia - * date : 2021/3/24 - * @since : 1.8 + * 线程池装配类 + * 这个装配前置条件是需要LiteflowConfig,LiteflowPropertyAutoConfiguration以及SpringAware + * @author justin.xu */ @Configuration +@ConditionalOnBean(LiteflowConfig.class) +@AutoConfigureAfter({LiteflowPropertyAutoConfiguration.class}) public class LiteflowExecutorAutoConfiguration { - @Bean("parallelExecutor") - public ExecutorService parallelExecutor( - @Value("${threadPool.parallel.worker:0}") int worker, - @Value("${threadPool.parallel.queue:512}") int queue) { - int useWorker = worker; - int useQueue = queue; + @Bean + public ExecutorService executorService(LiteflowConfig liteflowConfig) { + int useWorker = liteflowConfig.getWhenMaxWorkers(); + int useQueue = liteflowConfig.getWhenQueueLimit(); if (useWorker == 0) { useWorker = Runtime.getRuntime().availableProcessors() + 1; } @@ -33,6 +31,6 @@ public class LiteflowExecutorAutoConfiguration { useQueue = 512; } - return buildExecutor(useWorker, useQueue, "parallel-executors", false); + return ExecutorHelper.buildExecutor(useWorker, useQueue, "liteflow-when-calls", false); } } diff --git a/liteflow-spring-boot-starter/src/main/java/com/yomahub/liteflow/springboot/LiteflowMainAutoConfiguration.java b/liteflow-spring-boot-starter/src/main/java/com/yomahub/liteflow/springboot/LiteflowMainAutoConfiguration.java index ff64e6166..19deb7ebc 100644 --- a/liteflow-spring-boot-starter/src/main/java/com/yomahub/liteflow/springboot/LiteflowMainAutoConfiguration.java +++ b/liteflow-spring-boot-starter/src/main/java/com/yomahub/liteflow/springboot/LiteflowMainAutoConfiguration.java @@ -1,26 +1,15 @@ package com.yomahub.liteflow.springboot; import cn.hutool.core.util.StrUtil; -import com.google.common.collect.Lists; import com.yomahub.liteflow.core.FlowExecutor; -import com.yomahub.liteflow.entity.data.DataBus; import com.yomahub.liteflow.monitor.MonitorBus; import com.yomahub.liteflow.property.LiteflowConfig; -import com.yomahub.liteflow.spring.ComponentScaner; import com.yomahub.liteflow.util.SpringAware; -import org.apache.commons.lang3.StringUtils; import org.springframework.boot.autoconfigure.AutoConfigureAfter; import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; -import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; -import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; -import org.springframework.context.annotation.PropertySource; - -import javax.swing.*; -import java.util.List; -import java.util.concurrent.ExecutorService; /** * 主要的业务装配器 @@ -30,16 +19,15 @@ import java.util.concurrent.ExecutorService; */ @Configuration @ConditionalOnBean(LiteflowConfig.class) -@AutoConfigureAfter({LiteflowPropertyAutoConfiguration.class, LiteflowExecutorAutoConfiguration.class}) +@AutoConfigureAfter({LiteflowPropertyAutoConfiguration.class}) @Import(SpringAware.class) public class LiteflowMainAutoConfiguration { @Bean - public FlowExecutor flowExecutor(LiteflowConfig liteflowConfig, ExecutorService parallelExecutor){ + public FlowExecutor flowExecutor(LiteflowConfig liteflowConfig){ if(StrUtil.isNotBlank(liteflowConfig.getRuleSource())){ FlowExecutor flowExecutor = new FlowExecutor(); flowExecutor.setLiteflowConfig(liteflowConfig); - flowExecutor.setParallelExecutor(parallelExecutor); return flowExecutor; }else{ return null; diff --git a/liteflow-spring-boot-starter/src/main/java/com/yomahub/liteflow/springboot/LiteflowProperty.java b/liteflow-spring-boot-starter/src/main/java/com/yomahub/liteflow/springboot/LiteflowProperty.java index 0a6ddbc09..8f538eb48 100644 --- a/liteflow-spring-boot-starter/src/main/java/com/yomahub/liteflow/springboot/LiteflowProperty.java +++ b/liteflow-spring-boot-starter/src/main/java/com/yomahub/liteflow/springboot/LiteflowProperty.java @@ -18,6 +18,12 @@ public class LiteflowProperty { //异步线程最大等待描述 private int whenMaxWaitSeconds; + //异步线程池最大线程数 + private int whenMaxWorkers; + + //异步线程池最大队列数量 + private int whenQueueLimit; + public String getRuleSource() { return ruleSource; } @@ -41,4 +47,20 @@ public class LiteflowProperty { public void setWhenMaxWaitSeconds(int whenMaxWaitSeconds) { this.whenMaxWaitSeconds = whenMaxWaitSeconds; } + + public int getWhenMaxWorkers() { + return whenMaxWorkers; + } + + public void setWhenMaxWorkers(int whenMaxWorkers) { + this.whenMaxWorkers = whenMaxWorkers; + } + + public int getWhenQueueLimit() { + return whenQueueLimit; + } + + public void setWhenQueueLimit(int whenQueueLimit) { + this.whenQueueLimit = whenQueueLimit; + } } diff --git a/liteflow-spring-boot-starter/src/main/java/com/yomahub/liteflow/springboot/LiteflowPropertyAutoConfiguration.java b/liteflow-spring-boot-starter/src/main/java/com/yomahub/liteflow/springboot/LiteflowPropertyAutoConfiguration.java index e43d14842..6d773f3e3 100644 --- a/liteflow-spring-boot-starter/src/main/java/com/yomahub/liteflow/springboot/LiteflowPropertyAutoConfiguration.java +++ b/liteflow-spring-boot-starter/src/main/java/com/yomahub/liteflow/springboot/LiteflowPropertyAutoConfiguration.java @@ -31,6 +31,8 @@ public class LiteflowPropertyAutoConfiguration { liteflowConfig.setQueueLimit(liteflowMonitorProperty.getQueueLimit()); liteflowConfig.setDelay(liteflowMonitorProperty.getDelay()); liteflowConfig.setPeriod(liteflowMonitorProperty.getPeriod()); + liteflowConfig.setWhenMaxWorkers(property.getWhenMaxWorkers()); + liteflowConfig.setWhenQueueLimit(property.getWhenQueueLimit()); return liteflowConfig; } } diff --git a/liteflow-spring-boot-starter/src/main/java/com/yomahub/liteflow/springboot/Shutdown.java b/liteflow-spring-boot-starter/src/main/java/com/yomahub/liteflow/springboot/Shutdown.java index 07096eabb..9450ed6c4 100644 --- a/liteflow-spring-boot-starter/src/main/java/com/yomahub/liteflow/springboot/Shutdown.java +++ b/liteflow-spring-boot-starter/src/main/java/com/yomahub/liteflow/springboot/Shutdown.java @@ -11,12 +11,9 @@ import javax.annotation.Resource; import java.util.concurrent.ExecutorService; /** - * desc : - * name : Shutdown - * - * @author : xujia - * date : 2021/3/24 - * @since : 1.8 + * 关闭shutdown类 + * 执行清理工作 + * @author justin.xu */ @Order(Integer.MIN_VALUE) @Component @@ -24,14 +21,14 @@ public class Shutdown { private static final Logger LOG = LoggerFactory.getLogger(Shutdown.class); - @Resource(name = "parallelExecutor") - private ExecutorService parallelExecutor; + @Resource + private ExecutorService executorService; @PreDestroy public void destroy() throws Exception { - LOG.info("Start closing the parallel-executors..."); - ExecutorHelper.shutdownAwaitTermination(parallelExecutor, 3600); - LOG.info("Succeed closing the parallel-executors ok..."); + LOG.info("Start closing the liteflow-when-calls..."); + ExecutorHelper.shutdownAwaitTermination(executorService); + LOG.info("Succeed closing the liteflow-when-calls ok..."); } } diff --git a/liteflow-spring-boot-starter/src/main/resources/META-INF/liteflow-default.properties b/liteflow-spring-boot-starter/src/main/resources/META-INF/liteflow-default.properties index ef7873807..f85c10dbc 100644 --- a/liteflow-spring-boot-starter/src/main/resources/META-INF/liteflow-default.properties +++ b/liteflow-spring-boot-starter/src/main/resources/META-INF/liteflow-default.properties @@ -1,7 +1,9 @@ liteflow.rule-source=config/flow.xml liteflow.slot-size=1024 liteflow.when-max-wait-second=15 +liteflow.when-max-workers=3 +liteflow.when-queue-limit=512 liteflow.monitor.enable-log=false liteflow.monitor.queue-limit=200 liteflow.monitor.delay=300000 -liteflow.monitor.period=300000 \ No newline at end of file +liteflow.monitor.period=300000 diff --git a/liteflow-test-spring/src/main/resources/applicationContext.xml b/liteflow-test-spring/src/main/resources/applicationContext.xml index 944baa722..57c18aa26 100644 --- a/liteflow-test-spring/src/main/resources/applicationContext.xml +++ b/liteflow-test-spring/src/main/resources/applicationContext.xml @@ -21,6 +21,8 @@ + + @@ -31,5 +33,8 @@ + + + diff --git a/liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/ConcurrentCase.java b/liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/ConcurrentCase.java index 9bd1fa315..e50b26fe9 100644 --- a/liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/ConcurrentCase.java +++ b/liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/ConcurrentCase.java @@ -9,14 +9,9 @@ import java.util.Objects; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.CopyOnWriteArrayList; - /** - * desc : - * name : ConcurrentCase - * - * @author : xujia - * date : 2021/3/25 - * @since : 1.8 + * 流程的顺序执行、并发执行的CASE构造器 + * @author justin.xu */ public class ConcurrentCase { public static final Map, List>> CASES = new ConcurrentHashMap<>(); diff --git a/liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/SpringBootApp.java b/liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/SpringBootApp.java index 2c113b5f0..9846e2fb5 100644 --- a/liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/SpringBootApp.java +++ b/liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/SpringBootApp.java @@ -5,12 +5,8 @@ import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; /** - * desc : - * name : SpringBootApp - * - * @author : xujia - * date : 2021/3/3 - * @since : 1.8 + * 启动类 + * @author justin.xu */ @SpringBootApplication(exclude={DataSourceAutoConfiguration.class}) public class SpringBootApp { diff --git a/liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/TestParseFlow.java b/liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/TestParseFlow.java index 1f7946153..00ba958a3 100644 --- a/liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/TestParseFlow.java +++ b/liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/TestParseFlow.java @@ -15,16 +15,13 @@ import org.springframework.test.context.junit4.SpringRunner; import java.util.AbstractMap; import java.util.Arrays; +import java.util.Collections; import java.util.List; /** - * desc : - * name : TestParseFlow - * - * @author : xujia - * date : 2021/3/25 - * @since : 1.8 + * 测试流程的解析 + * @author justin.xu */ @ActiveProfiles("test") @RunWith(SpringRunner.class) @@ -32,14 +29,14 @@ import java.util.List; public class TestParseFlow { private Check caseAsync = new Check("async", Arrays.asList( - new AbstractMap.SimpleEntry<>(ThenCondition.class, null), - new AbstractMap.SimpleEntry<>(WhenCondition.class, false), - new AbstractMap.SimpleEntry<>(WhenCondition.class, true), - new AbstractMap.SimpleEntry<>(WhenCondition.class, true) + ThenCondition.class, + WhenCondition.class, + WhenCondition.class, + WhenCondition.class )); - private Check caseConcurrent = new Check("async-concurrent1", Arrays.asList( - new AbstractMap.SimpleEntry<>(WhenCondition.class, true) + private Check caseConcurrent = new Check("async-concurrent1", Collections.singletonList( + WhenCondition.class )); @Test @@ -55,31 +52,28 @@ public class TestParseFlow { Assert.assertTrue(null != chain.getConditionList() && !chain.getConditionList().isEmpty()); for (int i = 0; i < chain.getConditionList().size(); i ++) { - AbstractMap.SimpleEntry, Boolean> expected = check.getAsyncWithWhen().get(i); + Class expected = check.getConditionClazz().get(i); Condition actual = chain.getConditionList().get(i); - Assert.assertEquals(expected.getKey(), actual.getClass()); - if (actual.getClass().equals(WhenCondition.class)) { - Assert.assertEquals(expected.getValue(), ((WhenCondition) actual).isASync()); - } + Assert.assertEquals(expected, actual.getClass()); } } public static class Check { private String chainCode; - private List, Boolean>> asyncWithWhen; + private List> conditionClazz; - public Check(String chainCode, List, Boolean>> asyncWithWhen) { + public Check(String chainCode, List> conditionClazz) { this.chainCode = chainCode; - this.asyncWithWhen = asyncWithWhen; + this.conditionClazz = conditionClazz; } public String getChainCode() { return chainCode; } - public List, Boolean>> getAsyncWithWhen() { - return asyncWithWhen; + public List> getConditionClazz() { + return conditionClazz; } } } diff --git a/liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/TestRunFlow.java b/liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/TestRunFlow.java index 7ec971022..bcb90b578 100644 --- a/liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/TestRunFlow.java +++ b/liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/TestRunFlow.java @@ -17,12 +17,8 @@ import static com.yomahub.flowtest.concurrent.ConcurrentCase.caseAssertRandom; import static com.yomahub.flowtest.concurrent.ConcurrentCase.caseInit; /** - * desc : - * name : TestRunFlow - * - * @author : xujia - * date : 2021/3/25 - * @since : 1.8 + * 测试流程的顺序执行、并发执行等 + * @author justin.xu */ @ActiveProfiles("test") @RunWith(SpringRunner.class) diff --git a/liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/mock/component/c/C10Component.java b/liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/mock/component/c/C10Component.java index e92c245fc..360878450 100644 --- a/liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/mock/component/c/C10Component.java +++ b/liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/mock/component/c/C10Component.java @@ -5,12 +5,8 @@ import com.yomahub.liteflow.core.NodeComponent; import org.springframework.stereotype.Component; /** - * desc : - * name : C10 - * - * @author : xujia - * date : 2021/3/25 - * @since : 1.8 + * 测试mock component + * @author justin.xu */ @Component("c10") public class C10Component extends NodeComponent { diff --git a/liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/mock/component/c/C1Component.java b/liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/mock/component/c/C1Component.java index 17d3d95f7..641a67629 100644 --- a/liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/mock/component/c/C1Component.java +++ b/liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/mock/component/c/C1Component.java @@ -5,12 +5,8 @@ import com.yomahub.liteflow.core.NodeComponent; import org.springframework.stereotype.Component; /** - * desc : - * name : c1 - * - * @author : xujia - * date : 2021/3/25 - * @since : 1.8 + * 测试mock component + * @author justin.xu */ @Component("c1") public class C1Component extends NodeComponent { diff --git a/liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/mock/component/c/C2Component.java b/liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/mock/component/c/C2Component.java index 82564577d..7aa9ea9ab 100644 --- a/liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/mock/component/c/C2Component.java +++ b/liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/mock/component/c/C2Component.java @@ -5,12 +5,8 @@ import com.yomahub.liteflow.core.NodeComponent; import org.springframework.stereotype.Component; /** - * desc : - * name : C2 - * - * @author : xujia - * date : 2021/3/25 - * @since : 1.8 + * 测试mock component + * @author justin.xu */ @Component("c2") public class C2Component extends NodeComponent { diff --git a/liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/mock/component/c/C3Component.java b/liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/mock/component/c/C3Component.java index 0be98bf76..104d2e1fd 100644 --- a/liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/mock/component/c/C3Component.java +++ b/liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/mock/component/c/C3Component.java @@ -5,12 +5,8 @@ import com.yomahub.liteflow.core.NodeComponent; import org.springframework.stereotype.Component; /** - * desc : - * name : C3Component - * - * @author : xujia - * date : 2021/3/25 - * @since : 1.8 + * 测试mock component + * @author justin.xu */ @Component("c3") public class C3Component extends NodeComponent { diff --git a/liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/mock/component/c/C4Component.java b/liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/mock/component/c/C4Component.java index d573fc658..207b20309 100644 --- a/liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/mock/component/c/C4Component.java +++ b/liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/mock/component/c/C4Component.java @@ -5,12 +5,8 @@ import com.yomahub.liteflow.core.NodeComponent; import org.springframework.stereotype.Component; /** - * desc : - * name : C4 - * - * @author : xujia - * date : 2021/3/25 - * @since : 1.8 + * 测试mock component + * @author justin.xu */ @Component("c4") public class C4Component extends NodeComponent { diff --git a/liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/mock/component/c/C5Component.java b/liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/mock/component/c/C5Component.java index 29c0a7617..a5877c041 100644 --- a/liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/mock/component/c/C5Component.java +++ b/liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/mock/component/c/C5Component.java @@ -5,12 +5,8 @@ import com.yomahub.liteflow.core.NodeComponent; import org.springframework.stereotype.Component; /** - * desc : - * name : C5 - * - * @author : xujia - * date : 2021/3/25 - * @since : 1.8 + * 测试mock component + * @author justin.xu */ @Component("c5") public class C5Component extends NodeComponent { diff --git a/liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/mock/component/c/C6Component.java b/liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/mock/component/c/C6Component.java index 108190689..af3bca011 100644 --- a/liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/mock/component/c/C6Component.java +++ b/liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/mock/component/c/C6Component.java @@ -5,12 +5,8 @@ import com.yomahub.liteflow.core.NodeComponent; import org.springframework.stereotype.Component; /** - * desc : - * name : C6 - * - * @author : xujia - * date : 2021/3/25 - * @since : 1.8 + * 测试mock component + * @author justin.xu */ @Component("c6") public class C6Component extends NodeComponent { diff --git a/liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/mock/component/c/C7Component.java b/liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/mock/component/c/C7Component.java index 17d9e6336..30f47d0d1 100644 --- a/liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/mock/component/c/C7Component.java +++ b/liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/mock/component/c/C7Component.java @@ -5,12 +5,8 @@ import com.yomahub.liteflow.core.NodeComponent; import org.springframework.stereotype.Component; /** - * desc : - * name : c7 - * - * @author : xujia - * date : 2021/3/25 - * @since : 1.8 + * 测试mock component + * @author justin.xu */ @Component("c7") public class C7Component extends NodeComponent { diff --git a/liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/mock/component/c/C8Component.java b/liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/mock/component/c/C8Component.java index eef38003a..ce9bb91e2 100644 --- a/liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/mock/component/c/C8Component.java +++ b/liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/mock/component/c/C8Component.java @@ -5,12 +5,8 @@ import com.yomahub.liteflow.core.NodeComponent; import org.springframework.stereotype.Component; /** - * desc : - * name : C8 - * - * @author : xujia - * date : 2021/3/25 - * @since : 1.8 + * 测试mock component + * @author justin.xu */ @Component("c8") public class C8Component extends NodeComponent { diff --git a/liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/mock/component/c/C9Component.java b/liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/mock/component/c/C9Component.java index 7ee36f7d7..f770ac294 100644 --- a/liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/mock/component/c/C9Component.java +++ b/liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/mock/component/c/C9Component.java @@ -5,12 +5,8 @@ import com.yomahub.liteflow.core.NodeComponent; import org.springframework.stereotype.Component; /** - * desc : - * name : C9 - * - * @author : xujia - * date : 2021/3/25 - * @since : 1.8 + * 测试mock component + * @author justin.xu */ @Component("c9") public class C9Component extends NodeComponent { diff --git a/liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/mock/component/p/P3Component.java b/liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/mock/component/p/P3Component.java index eae5f65d1..eaaa96423 100644 --- a/liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/mock/component/p/P3Component.java +++ b/liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/mock/component/p/P3Component.java @@ -5,12 +5,8 @@ import com.yomahub.liteflow.core.NodeComponent; import org.springframework.stereotype.Component; /** - * desc : - * name : P3Component - * - * @author : xujia - * date : 2021/3/25 - * @since : 1.8 + * 测试mock component + * @author justin.xu */ @Component("p3") public class P3Component extends NodeComponent { diff --git a/liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/mock/component/p/P4Component.java b/liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/mock/component/p/P4Component.java index cf7bb188f..4b22bb1ad 100644 --- a/liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/mock/component/p/P4Component.java +++ b/liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/mock/component/p/P4Component.java @@ -5,12 +5,8 @@ import com.yomahub.liteflow.core.NodeComponent; import org.springframework.stereotype.Component; /** - * desc : - * name : P4Component - * - * @author : xujia - * date : 2021/3/25 - * @since : 1.8 + * 测试mock component + * @author justin.xu */ @Component("p4") public class P4Component extends NodeComponent { diff --git a/liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/mock/component/p/P5Component.java b/liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/mock/component/p/P5Component.java index 820944c86..c222c5876 100644 --- a/liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/mock/component/p/P5Component.java +++ b/liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/mock/component/p/P5Component.java @@ -5,12 +5,8 @@ import com.yomahub.liteflow.core.NodeComponent; import org.springframework.stereotype.Component; /** - * desc : - * name : P5 - * - * @author : xujia - * date : 2021/3/25 - * @since : 1.8 + * 测试mock component + * @author justin.xu */ @Component("p5") public class P5Component extends NodeComponent { diff --git a/liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/mock/component/p/P6Component.java b/liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/mock/component/p/P6Component.java index be94347e3..a17f1ffcd 100644 --- a/liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/mock/component/p/P6Component.java +++ b/liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/mock/component/p/P6Component.java @@ -5,12 +5,8 @@ import com.yomahub.liteflow.core.NodeComponent; import org.springframework.stereotype.Component; /** - * desc : - * name : P6 - * - * @author : xujia - * date : 2021/3/25 - * @since : 1.8 + * 测试mock component + * @author justin.xu */ @Component("p6") public class P6Component extends NodeComponent { diff --git a/liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/mock/component/p/P7Component.java b/liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/mock/component/p/P7Component.java index 0c9edd806..da1bfa819 100644 --- a/liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/mock/component/p/P7Component.java +++ b/liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/mock/component/p/P7Component.java @@ -5,12 +5,8 @@ import com.yomahub.liteflow.core.NodeComponent; import org.springframework.stereotype.Component; /** - * desc : - * name : P7Component - * - * @author : xujia - * date : 2021/3/25 - * @since : 1.8 + * 测试mock component + * @author justin.xu */ @Component("p7") public class P7Component extends NodeComponent { diff --git a/liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/mock/component/p/P8Component.java b/liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/mock/component/p/P8Component.java index 5bdf3a7cc..12f612e95 100644 --- a/liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/mock/component/p/P8Component.java +++ b/liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/mock/component/p/P8Component.java @@ -5,12 +5,8 @@ import com.yomahub.liteflow.core.NodeComponent; import org.springframework.stereotype.Component; /** - * desc : - * name : P8Component - * - * @author : xujia - * date : 2021/3/25 - * @since : 1.8 + * 测试mock component + * @author justin.xu */ @Component("p8") public class P8Component extends NodeComponent { diff --git a/liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/mock/component/s/S1Component.java b/liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/mock/component/s/S1Component.java index 01a33d474..e78c15f35 100644 --- a/liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/mock/component/s/S1Component.java +++ b/liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/mock/component/s/S1Component.java @@ -5,12 +5,8 @@ import com.yomahub.liteflow.core.NodeComponent; import org.springframework.stereotype.Component; /** - * desc : - * name : S1Component - * - * @author : xujia - * date : 2021/3/25 - * @since : 1.8 + * 测试mock component + * @author justin.xu */ @Component("s1") public class S1Component extends NodeComponent { diff --git a/liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/mock/component/s/S2Component.java b/liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/mock/component/s/S2Component.java index 6a2aebd45..5d67adea1 100644 --- a/liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/mock/component/s/S2Component.java +++ b/liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/mock/component/s/S2Component.java @@ -5,12 +5,8 @@ import com.yomahub.liteflow.core.NodeComponent; import org.springframework.stereotype.Component; /** - * desc : - * name : S2Component - * - * @author : xujia - * date : 2021/3/25 - * @since : 1.8 + * 测试mock component + * @author justin.xu */ @Component("s2") public class S2Component extends NodeComponent { diff --git a/liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/mock/component/s/S3Component.java b/liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/mock/component/s/S3Component.java index df52250ae..d85ca5822 100644 --- a/liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/mock/component/s/S3Component.java +++ b/liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/mock/component/s/S3Component.java @@ -5,12 +5,8 @@ import com.yomahub.liteflow.core.NodeComponent; import org.springframework.stereotype.Component; /** - * desc : - * name : S3 - * - * @author : xujia - * date : 2021/3/25 - * @since : 1.8 + * 测试mock component + * @author justin.xu */ @Component("s3") public class S3Component extends NodeComponent { diff --git a/liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/mock/component/s/S4Component.java b/liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/mock/component/s/S4Component.java index a0cb7306a..47bec234d 100644 --- a/liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/mock/component/s/S4Component.java +++ b/liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/mock/component/s/S4Component.java @@ -5,12 +5,8 @@ import com.yomahub.liteflow.core.NodeComponent; import org.springframework.stereotype.Component; /** - * desc : - * name : S4 - * - * @author : xujia - * date : 2021/3/25 - * @since : 1.8 + * 测试mock component + * @author justin.xu */ @Component("s4") public class S4Component extends NodeComponent { diff --git a/liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/mock/component/s/S5Component.java b/liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/mock/component/s/S5Component.java index 4e491d33b..4c20855dc 100644 --- a/liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/mock/component/s/S5Component.java +++ b/liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/mock/component/s/S5Component.java @@ -5,12 +5,8 @@ import com.yomahub.liteflow.core.NodeComponent; import org.springframework.stereotype.Component; /** - * desc : - * name : S5 - * - * @author : xujia - * date : 2021/3/25 - * @since : 1.8 + * 测试mock component + * @author justin.xu */ @Component("s5") public class S5Component extends NodeComponent { diff --git a/liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/mock/component/s/S6Component.java b/liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/mock/component/s/S6Component.java index d7cd20947..ee2578b6c 100644 --- a/liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/mock/component/s/S6Component.java +++ b/liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/mock/component/s/S6Component.java @@ -5,12 +5,8 @@ import com.yomahub.liteflow.core.NodeComponent; import org.springframework.stereotype.Component; /** - * desc : - * name : S6 - * - * @author : xujia - * date : 2021/3/25 - * @since : 1.8 + * 测试mock component + * @author justin.xu */ @Component("s6") public class S6Component extends NodeComponent { diff --git a/liteflow-test-springboot/src/test/resources/config/flow-test.xml b/liteflow-test-springboot/src/test/resources/config/flow-test.xml index 13245b27d..a2e66e396 100644 --- a/liteflow-test-springboot/src/test/resources/config/flow-test.xml +++ b/liteflow-test-springboot/src/test/resources/config/flow-test.xml @@ -4,17 +4,17 @@ - - + + - + - + From 617440db259f364268e22b56bfe3376c2f4cca4d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BE=90=E4=BD=B3?= Date: Fri, 26 Mar 2021 21:38:13 +0800 Subject: [PATCH 07/10] =?UTF-8?q?enhancement=20#I37QVR=20WhenCondition?= =?UTF-8?q?=E6=97=B6=E5=80=99=EF=BC=8C=E5=B9=B6=E5=8F=91=E6=89=A7=E8=A1=8C?= =?UTF-8?q?=E7=9B=AE=E5=89=8D=E4=BC=9A=E6=AF=8F=E6=AC=A1=E6=96=B0=E5=BB=BA?= =?UTF-8?q?=E7=BA=BF=E7=A8=8B=E5=8F=AF=E4=B8=8D=E5=8F=AF=E8=B5=B0=E7=BA=BF?= =?UTF-8?q?=E7=A8=8B=E6=B1=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../yomahub/liteflow/entity/flow/Chain.java | 40 ++++++++++++++++--- ...elCondition.java => ParallelCallable.java} | 15 ++++--- .../liteflow/entity/flow/WhenCondition.java | 12 ++++++ .../exception/WhenExecuteException.java | 21 ++++++++++ .../liteflow/parser/XmlFlowParser.java | 8 +++- .../yomahub/liteflow/util/ExecutorHelper.java | 2 +- .../com/yomahub/liteflow/util}/Shutdown.java | 16 ++------ .../LiteflowExecutorAutoConfiguration.java | 8 +++- .../src/main/resources/applicationContext.xml | 2 + .../flowtest/concurrent/TestParseFlow.java | 38 ++++++++++-------- .../flowtest/concurrent/TestRunFlow.java | 19 +++++++-- .../mock/component/p/P5Component.java | 4 +- .../src/test/resources/config/flow-test.xml | 17 +++++--- 13 files changed, 148 insertions(+), 54 deletions(-) rename liteflow-core/src/main/java/com/yomahub/liteflow/entity/flow/{ParallelCondition.java => ParallelCallable.java} (69%) create mode 100644 liteflow-core/src/main/java/com/yomahub/liteflow/exception/WhenExecuteException.java rename {liteflow-spring-boot-starter/src/main/java/com/yomahub/liteflow/springboot => liteflow-core/src/main/java/com/yomahub/liteflow/util}/Shutdown.java (62%) diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/entity/flow/Chain.java b/liteflow-core/src/main/java/com/yomahub/liteflow/entity/flow/Chain.java index f6433dc7c..c1e3bf76b 100644 --- a/liteflow-core/src/main/java/com/yomahub/liteflow/entity/flow/Chain.java +++ b/liteflow-core/src/main/java/com/yomahub/liteflow/entity/flow/Chain.java @@ -13,6 +13,7 @@ import com.yomahub.liteflow.entity.data.DataBus; import com.yomahub.liteflow.entity.data.Slot; import com.yomahub.liteflow.enums.ExecuteTypeEnum; import com.yomahub.liteflow.exception.FlowSystemException; +import com.yomahub.liteflow.exception.WhenExecuteException; import com.yomahub.liteflow.property.LiteflowConfig; import com.yomahub.liteflow.util.SpringAware; import org.apache.commons.collections4.CollectionUtils; @@ -110,7 +111,7 @@ public class Chain implements Executable { // 使用线程池执行when并发流程 private void executeAsyncCondition(WhenCondition condition, Integer slotIndex, String requestId) { - ExecutorService parallelExecutor = SpringAware.getBean(ExecutorService.class); + ExecutorService parallelExecutor = SpringAware.getBean("whenExecutors"); final CountDownLatch latch = new CountDownLatch(condition.getNodeList().size()); final List> futures = new ArrayList<>(condition.getNodeList().size()); @@ -118,21 +119,48 @@ public class Chain implements Executable { for (int i = 0; i < condition.getNodeList().size(); i++) { futures.add(parallelExecutor.submit( - new ParallelCondition(condition.getNodeList().get(i), slotIndex, requestId, latch) + new ParallelCallable(condition.getNodeList().get(i), slotIndex, requestId, latch) )); } + boolean interrupted = false; try { if (!latch.await(whenMaxWaitSeconds, TimeUnit.SECONDS)) { for (Future f : futures) { f.cancel(true); } - LOG.warn("requestId [{}] executing async condition has reached max-wait-seconds, condition canceled and move to next executableItem." - , requestId); + interrupted = true; + LOG.warn("requestId [{}] executing async condition has reached max-wait-seconds, condition canceled.", requestId); } } catch (InterruptedException e) { - // ignore InterruptedException - + interrupted = true; } + + /** + * 当配置了errorResume = false,出现interrupted或者!f.get()的情况,将抛出WhenExecuteException + */ + if (!condition.isErrorResume()) { + if (interrupted) { + throw new WhenExecuteException(String.format( + "requestId [%s] when execute interrupted. errorResume [false].", requestId)); + } + + for (Future f : futures) { + try { + if (!f.get()) { + throw new WhenExecuteException(String.format( + "requestId [%s] when execute failed. errorResume [false].", requestId)); + } + } catch (InterruptedException | ExecutionException e) { + throw new WhenExecuteException(String.format( + "requestId [%s] when execute failed. errorResume [false].", requestId)); + } + } + + } else if (interrupted) { + // 这里由于配置了errorResume,所以只打印warn日志 + LOG.warn("requestId [{}] executing when condition timeout , but ignore with errorResume.", requestId); + } + } } diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/entity/flow/ParallelCondition.java b/liteflow-core/src/main/java/com/yomahub/liteflow/entity/flow/ParallelCallable.java similarity index 69% rename from liteflow-core/src/main/java/com/yomahub/liteflow/entity/flow/ParallelCondition.java rename to liteflow-core/src/main/java/com/yomahub/liteflow/entity/flow/ParallelCallable.java index cbfe0e1e3..97b74e133 100644 --- a/liteflow-core/src/main/java/com/yomahub/liteflow/entity/flow/ParallelCondition.java +++ b/liteflow-core/src/main/java/com/yomahub/liteflow/entity/flow/ParallelCallable.java @@ -10,9 +10,9 @@ import java.util.concurrent.CountDownLatch; * 并行器线程 * @author Bryan.Zhang */ -public class ParallelCondition implements Callable { +public class ParallelCallable implements Callable { - private static final Logger LOG = LoggerFactory.getLogger(ParallelCondition.class); + private static final Logger LOG = LoggerFactory.getLogger(ParallelCallable.class); private Executable executableItem; @@ -20,9 +20,10 @@ public class ParallelCondition implements Callable { private String requestId; + private CountDownLatch latch; - public ParallelCondition(Executable executableItem, Integer slotIndex, String requestId, CountDownLatch latch) { + public ParallelCallable(Executable executableItem, Integer slotIndex, String requestId, CountDownLatch latch) { this.executableItem = executableItem; this.slotIndex = slotIndex; this.requestId = requestId; @@ -33,12 +34,14 @@ public class ParallelCondition implements Callable { public Boolean call() throws Exception { try { executableItem.execute(slotIndex); + + return true; }catch(Exception e){ - LOG.error("requestId [{}], item [{}] execute cause error", requestId, executableItem.getExecuteName(), e); + LOG.error("requestId [{}], item [{}] execute error", requestId, executableItem.getExecuteName()); + + return false; } finally { latch.countDown(); } - - return true; } } diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/entity/flow/WhenCondition.java b/liteflow-core/src/main/java/com/yomahub/liteflow/entity/flow/WhenCondition.java index b2ccd929c..13a202537 100644 --- a/liteflow-core/src/main/java/com/yomahub/liteflow/entity/flow/WhenCondition.java +++ b/liteflow-core/src/main/java/com/yomahub/liteflow/entity/flow/WhenCondition.java @@ -14,8 +14,20 @@ import java.util.List; * @author Bryan.Zhang */ public class WhenCondition extends Condition{ + // 增加errorResume属性,以区分当when调用链调用失败时是否继续往下执行 + private boolean errorResume; public WhenCondition(List nodeList) { super(nodeList); + errorResume = true; + } + + public WhenCondition(List nodeList, boolean errorResume) { + super(nodeList); + this.errorResume = errorResume; + } + + public boolean isErrorResume() { + return errorResume; } } diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/exception/WhenExecuteException.java b/liteflow-core/src/main/java/com/yomahub/liteflow/exception/WhenExecuteException.java new file mode 100644 index 000000000..ebe3f8662 --- /dev/null +++ b/liteflow-core/src/main/java/com/yomahub/liteflow/exception/WhenExecuteException.java @@ -0,0 +1,21 @@ +package com.yomahub.liteflow.exception; + + +public class WhenExecuteException extends RuntimeException { + private static final long serialVersionUID = 1L; + + /** 异常信息 */ + private String message; + + public WhenExecuteException(String message) { + this.message = message; + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } +} diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/parser/XmlFlowParser.java b/liteflow-core/src/main/java/com/yomahub/liteflow/parser/XmlFlowParser.java index 372524838..fba1f8570 100644 --- a/liteflow-core/src/main/java/com/yomahub/liteflow/parser/XmlFlowParser.java +++ b/liteflow-core/src/main/java/com/yomahub/liteflow/parser/XmlFlowParser.java @@ -13,6 +13,7 @@ import com.yomahub.liteflow.exception.ExecutableItemNotFoundException; import com.yomahub.liteflow.exception.ParseException; import com.yomahub.liteflow.util.SpringAware; import org.apache.commons.lang3.StringUtils; +import org.dom4j.Attribute; import org.dom4j.Document; import org.dom4j.DocumentHelper; import org.dom4j.Element; @@ -139,7 +140,12 @@ public abstract class XmlFlowParser { if (condE.getName().equals("then")) { conditionList.add(new ThenCondition(chainNodeList)); } else if (condE.getName().equals("when")) { - conditionList.add(new WhenCondition(chainNodeList)); + Attribute errorResume = condE.attribute("errorResume"); + if (errorResume != null) { + conditionList.add(new WhenCondition(chainNodeList, errorResume.getValue().equals("true"))); + } else { + conditionList.add(new WhenCondition(chainNodeList)); + } } } FlowBus.addChain(chainName, new Chain(chainName,conditionList)); diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/util/ExecutorHelper.java b/liteflow-core/src/main/java/com/yomahub/liteflow/util/ExecutorHelper.java index a381ec7cb..e093869a7 100644 --- a/liteflow-core/src/main/java/com/yomahub/liteflow/util/ExecutorHelper.java +++ b/liteflow-core/src/main/java/com/yomahub/liteflow/util/ExecutorHelper.java @@ -13,7 +13,7 @@ import java.util.concurrent.atomic.AtomicLong; /** * 线程池工具类 - * @author justin.xu + * @author Bryan.Zhang */ public class ExecutorHelper { diff --git a/liteflow-spring-boot-starter/src/main/java/com/yomahub/liteflow/springboot/Shutdown.java b/liteflow-core/src/main/java/com/yomahub/liteflow/util/Shutdown.java similarity index 62% rename from liteflow-spring-boot-starter/src/main/java/com/yomahub/liteflow/springboot/Shutdown.java rename to liteflow-core/src/main/java/com/yomahub/liteflow/util/Shutdown.java index 9450ed6c4..5076944c0 100644 --- a/liteflow-spring-boot-starter/src/main/java/com/yomahub/liteflow/springboot/Shutdown.java +++ b/liteflow-core/src/main/java/com/yomahub/liteflow/util/Shutdown.java @@ -1,34 +1,26 @@ -package com.yomahub.liteflow.springboot; +package com.yomahub.liteflow.util; -import com.yomahub.liteflow.util.ExecutorHelper; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.springframework.core.annotation.Order; -import org.springframework.stereotype.Component; import javax.annotation.PreDestroy; -import javax.annotation.Resource; import java.util.concurrent.ExecutorService; /** * 关闭shutdown类 * 执行清理工作 - * @author justin.xu + * @author Bryan.Zhang */ -@Order(Integer.MIN_VALUE) -@Component public class Shutdown { private static final Logger LOG = LoggerFactory.getLogger(Shutdown.class); - @Resource - private ExecutorService executorService; - @PreDestroy public void destroy() throws Exception { + ExecutorService executorService = SpringAware.getBean("whenExecutors"); + LOG.info("Start closing the liteflow-when-calls..."); ExecutorHelper.shutdownAwaitTermination(executorService); LOG.info("Succeed closing the liteflow-when-calls ok..."); } - } diff --git a/liteflow-spring-boot-starter/src/main/java/com/yomahub/liteflow/springboot/LiteflowExecutorAutoConfiguration.java b/liteflow-spring-boot-starter/src/main/java/com/yomahub/liteflow/springboot/LiteflowExecutorAutoConfiguration.java index 6f6785e3b..ee2d0deaf 100644 --- a/liteflow-spring-boot-starter/src/main/java/com/yomahub/liteflow/springboot/LiteflowExecutorAutoConfiguration.java +++ b/liteflow-spring-boot-starter/src/main/java/com/yomahub/liteflow/springboot/LiteflowExecutorAutoConfiguration.java @@ -2,6 +2,7 @@ package com.yomahub.liteflow.springboot; import com.yomahub.liteflow.property.LiteflowConfig; import com.yomahub.liteflow.util.ExecutorHelper; +import com.yomahub.liteflow.util.Shutdown; import org.springframework.boot.autoconfigure.AutoConfigureAfter; import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; import org.springframework.context.annotation.Bean; @@ -19,7 +20,7 @@ import java.util.concurrent.ExecutorService; @AutoConfigureAfter({LiteflowPropertyAutoConfiguration.class}) public class LiteflowExecutorAutoConfiguration { - @Bean + @Bean("whenExecutors") public ExecutorService executorService(LiteflowConfig liteflowConfig) { int useWorker = liteflowConfig.getWhenMaxWorkers(); int useQueue = liteflowConfig.getWhenQueueLimit(); @@ -33,4 +34,9 @@ public class LiteflowExecutorAutoConfiguration { return ExecutorHelper.buildExecutor(useWorker, useQueue, "liteflow-when-calls", false); } + + @Bean + public Shutdown shutdown() { + return new Shutdown(); + } } diff --git a/liteflow-test-spring/src/main/resources/applicationContext.xml b/liteflow-test-spring/src/main/resources/applicationContext.xml index 57c18aa26..03744237b 100644 --- a/liteflow-test-spring/src/main/resources/applicationContext.xml +++ b/liteflow-test-spring/src/main/resources/applicationContext.xml @@ -37,4 +37,6 @@ + + diff --git a/liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/TestParseFlow.java b/liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/TestParseFlow.java index 00ba958a3..ff647fbfb 100644 --- a/liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/TestParseFlow.java +++ b/liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/TestParseFlow.java @@ -28,22 +28,25 @@ import java.util.List; @SpringBootTest public class TestParseFlow { - private Check caseAsync = new Check("async", Arrays.asList( - ThenCondition.class, - WhenCondition.class, - WhenCondition.class, - WhenCondition.class + private Check caseErrorResume = new Check("test-errorResume", Arrays.asList( + new AbstractMap.SimpleEntry, Boolean>(ThenCondition.class, null), + new AbstractMap.SimpleEntry, Boolean>(WhenCondition.class, true), + new AbstractMap.SimpleEntry, Boolean>(WhenCondition.class, true), + new AbstractMap.SimpleEntry, Boolean>(WhenCondition.class, true) )); - private Check caseConcurrent = new Check("async-concurrent1", Collections.singletonList( - WhenCondition.class + private Check caseErrorBreak = new Check("test-errorBreak", Arrays.asList( + new AbstractMap.SimpleEntry, Boolean>(ThenCondition.class, null), + new AbstractMap.SimpleEntry, Boolean>(WhenCondition.class, true), + new AbstractMap.SimpleEntry, Boolean>(WhenCondition.class, false), + new AbstractMap.SimpleEntry, Boolean>(WhenCondition.class, true) )); @Test public void parseWhen() throws Exception { - assertTrue(caseAsync, FlowBus.getChain(caseAsync.getChainCode())); + assertTrue(caseErrorResume, FlowBus.getChain(caseErrorResume.getChainCode())); - assertTrue(caseConcurrent, FlowBus.getChain(caseConcurrent.getChainCode())); + assertTrue(caseErrorBreak, FlowBus.getChain(caseErrorBreak.getChainCode())); } private void assertTrue(Check check, Chain chain) { @@ -52,28 +55,31 @@ public class TestParseFlow { Assert.assertTrue(null != chain.getConditionList() && !chain.getConditionList().isEmpty()); for (int i = 0; i < chain.getConditionList().size(); i ++) { - Class expected = check.getConditionClazz().get(i); + AbstractMap.SimpleEntry, Boolean> expected = check.getClazzWithFlags().get(i); Condition actual = chain.getConditionList().get(i); - Assert.assertEquals(expected, actual.getClass()); + Assert.assertEquals(expected.getKey(), actual.getClass()); + if (actual.getClass().equals(WhenCondition.class)) { + Assert.assertEquals(expected.getValue(), ((WhenCondition) actual).isErrorResume()); + } } } public static class Check { private String chainCode; - private List> conditionClazz; + private List, Boolean>> clazzWithFlags; - public Check(String chainCode, List> conditionClazz) { + public Check(String chainCode, List, Boolean>> clazzWithFlags) { this.chainCode = chainCode; - this.conditionClazz = conditionClazz; + this.clazzWithFlags = clazzWithFlags; } public String getChainCode() { return chainCode; } - public List> getConditionClazz() { - return conditionClazz; + public List, Boolean>> getClazzWithFlags() { + return clazzWithFlags; } } } diff --git a/liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/TestRunFlow.java b/liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/TestRunFlow.java index bcb90b578..fad9ca62c 100644 --- a/liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/TestRunFlow.java +++ b/liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/TestRunFlow.java @@ -38,16 +38,29 @@ public class TestRunFlow { } @Test - public void mixedRunTest() throws Exception { - String requestId = init(Arrays.asList("s1", "s2", "s3", "s4", "s5", "s6", "p3", "p4", "p5", "p6", "p7", "p8")); + public void mixedRunByErrorResumeTest() throws Exception { + //由于errorResume,即使p5执行失败抛出异常, p7, p8也将会执行 + String requestId = init(Arrays.asList("s1", "s2", "s3", "s4", "s5", "s6", "p3", "p4", "p6", "p7", "p8")); - flowExecutor.execute("async", requestId); + flowExecutor.execute("test-errorResume", requestId); + + caseAssertRandom(requestId); + } + + + @Test + public void mixedRunByErrorBreakTest() throws Exception { + //由于errorBreak,p5执行失败抛出异常, p7, p8将不会执行 + String requestId = init(Arrays.asList("s1", "s2", "s3", "s4", "s5", "s6", "p3", "p4", "p6")); + + flowExecutor.execute("test-errorBreak", requestId); caseAssertRandom(requestId); } @Test public void parallelTest() throws InterruptedException { + //测试2个线程并发时,所执行的序列是正常的,线程安全的(slotIndex在每个执行序列chain中都是不变的) String requestId1 = init(Arrays.asList("c1", "c2", "c3", "c4", "c5")); String requestId2 = init(Arrays.asList("c6", "c7", "c8", "c9", "c10")); diff --git a/liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/mock/component/p/P5Component.java b/liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/mock/component/p/P5Component.java index c222c5876..c4463fc26 100644 --- a/liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/mock/component/p/P5Component.java +++ b/liteflow-test-springboot/src/test/java/com/yomahub/flowtest/concurrent/mock/component/p/P5Component.java @@ -1,6 +1,5 @@ package com.yomahub.flowtest.concurrent.mock.component.p; -import com.yomahub.flowtest.concurrent.ConcurrentCase; import com.yomahub.liteflow.core.NodeComponent; import org.springframework.stereotype.Component; @@ -15,7 +14,6 @@ public class P5Component extends NodeComponent { @Override public void process() throws Exception { - ConcurrentCase.caseAdd((String) getSlot().getRequestData(), new ConcurrentCase.Routers(getSlotIndex(), name)); - System.out.println(String.format("[%s] component executed, index[%d].", name, getSlotIndex())); + throw new RuntimeException(String.format("test mock error [%s]", name)); } } \ No newline at end of file diff --git a/liteflow-test-springboot/src/test/resources/config/flow-test.xml b/liteflow-test-springboot/src/test/resources/config/flow-test.xml index a2e66e396..7bdc30870 100644 --- a/liteflow-test-springboot/src/test/resources/config/flow-test.xml +++ b/liteflow-test-springboot/src/test/resources/config/flow-test.xml @@ -1,12 +1,19 @@ - - + + - - - + + + + + + + + + + From 5e436a254b638a928bd9da826b3b199329c8bdf4 Mon Sep 17 00:00:00 2001 From: bryan31 Date: Sun, 28 Mar 2021 16:42:35 +0800 Subject: [PATCH 08/10] =?UTF-8?q?enhancement=20#I37QVR=20WhenCondition?= =?UTF-8?q?=E6=97=B6=E5=80=99=EF=BC=8C=E5=B9=B6=E5=8F=91=E6=89=A7=E8=A1=8C?= =?UTF-8?q?=E7=9B=AE=E5=89=8D=E4=BC=9A=E6=AF=8F=E6=AC=A1=E6=96=B0=E5=BB=BA?= =?UTF-8?q?=E7=BA=BF=E7=A8=8B=E5=8F=AF=E4=B8=8D=E5=8F=AF=E8=B5=B0=E7=BA=BF?= =?UTF-8?q?=E7=A8=8B=E6=B1=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../yomahub/liteflow/entity/data/DataBus.java | 10 +-- .../yomahub/liteflow/entity/flow/Chain.java | 29 ++++++--- .../yomahub/liteflow/monitor/MonitorBus.java | 30 +-------- .../liteflow/parser/XmlFlowParser.java | 2 +- .../liteflow/property/LiteflowConfig.java | 65 +++++++++++++++---- .../yomahub/liteflow/util/SpringAware.java | 14 +++- .../LiteflowExecutorAutoConfiguration.java | 14 +--- .../META-INF/liteflow-default.properties | 2 +- .../src/main/resources/applicationContext.xml | 6 +- .../java/com/yomahub/flowtest/TestFlow.java | 2 +- .../flowtest/components/EComponent.java | 4 -- 11 files changed, 98 insertions(+), 80 deletions(-) diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/entity/data/DataBus.java b/liteflow-core/src/main/java/com/yomahub/liteflow/entity/data/DataBus.java index 0cd59e561..d376f353c 100644 --- a/liteflow-core/src/main/java/com/yomahub/liteflow/entity/data/DataBus.java +++ b/liteflow-core/src/main/java/com/yomahub/liteflow/entity/data/DataBus.java @@ -10,6 +10,7 @@ package com.yomahub.liteflow.entity.data; import java.util.concurrent.atomic.AtomicInteger; import cn.hutool.core.util.ObjectUtil; +import com.yomahub.liteflow.exception.ConfigErrorException; import com.yomahub.liteflow.property.LiteflowConfig; import com.yomahub.liteflow.util.SpringAware; import org.slf4j.Logger; @@ -29,12 +30,11 @@ public class DataBus { static { LiteflowConfig liteflowConfig = SpringAware.getBean(LiteflowConfig.class); - int slotSize = 1024; - if (ObjectUtil.isNotNull(liteflowConfig)){ - if (ObjectUtil.isNotNull(liteflowConfig.getSlotSize())){ - slotSize = liteflowConfig.getSlotSize(); - } + + if (ObjectUtil.isNull(liteflowConfig)){ + throw new ConfigErrorException("config error, please check liteflow config property"); } + int slotSize = liteflowConfig.getSlotSize(); slots = new Slot[slotSize]; } diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/entity/flow/Chain.java b/liteflow-core/src/main/java/com/yomahub/liteflow/entity/flow/Chain.java index c1e3bf76b..43772bb30 100644 --- a/liteflow-core/src/main/java/com/yomahub/liteflow/entity/flow/Chain.java +++ b/liteflow-core/src/main/java/com/yomahub/liteflow/entity/flow/Chain.java @@ -12,14 +12,17 @@ import cn.hutool.core.util.ObjectUtil; import com.yomahub.liteflow.entity.data.DataBus; import com.yomahub.liteflow.entity.data.Slot; import com.yomahub.liteflow.enums.ExecuteTypeEnum; +import com.yomahub.liteflow.exception.ConfigErrorException; import com.yomahub.liteflow.exception.FlowSystemException; import com.yomahub.liteflow.exception.WhenExecuteException; import com.yomahub.liteflow.property.LiteflowConfig; +import com.yomahub.liteflow.util.ExecutorHelper; import com.yomahub.liteflow.util.SpringAware; import org.apache.commons.collections4.CollectionUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import javax.swing.*; import java.util.List; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; @@ -39,14 +42,24 @@ public class Chain implements Executable { private List conditionList; - private static int whenMaxWaitSeconds; + private static ExecutorService parallelExecutor; + + private static final LiteflowConfig liteflowConfig; static { - LiteflowConfig liteflowConfig = SpringAware.getBean(LiteflowConfig.class); - if (ObjectUtil.isNotNull(liteflowConfig)) { - whenMaxWaitSeconds = liteflowConfig.getWhenMaxWaitSeconds(); - } else { - whenMaxWaitSeconds = 15; + //这里liteflowConfig不可能为null + //如果在springboot环境,由于自动装配,所以不可能为null + //在spring环境,如果xml没配置,在FlowExecutor的init时候就已经报错了 + liteflowConfig = SpringAware.getBean(LiteflowConfig.class); + + //这里为了严谨,还是判断了下 + if (ObjectUtil.isNull(liteflowConfig)){ + throw new ConfigErrorException("config error, please check liteflow config property"); + } + + parallelExecutor = SpringAware.getBean(ExecutorService.class); + if (ObjectUtil.isNull(parallelExecutor)){ + parallelExecutor = ExecutorHelper.buildExecutor(liteflowConfig.getWhenMaxWorkers(), liteflowConfig.getWhenQueueLimit(), "liteflow-when-thread", false); } } @@ -111,8 +124,6 @@ public class Chain implements Executable { // 使用线程池执行when并发流程 private void executeAsyncCondition(WhenCondition condition, Integer slotIndex, String requestId) { - ExecutorService parallelExecutor = SpringAware.getBean("whenExecutors"); - final CountDownLatch latch = new CountDownLatch(condition.getNodeList().size()); final List> futures = new ArrayList<>(condition.getNodeList().size()); @@ -125,7 +136,7 @@ public class Chain implements Executable { boolean interrupted = false; try { - if (!latch.await(whenMaxWaitSeconds, TimeUnit.SECONDS)) { + if (!latch.await(liteflowConfig.getWhenMaxWaitSeconds(), TimeUnit.SECONDS)) { for (Future f : futures) { f.cancel(true); } diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/monitor/MonitorBus.java b/liteflow-core/src/main/java/com/yomahub/liteflow/monitor/MonitorBus.java index d7b6e4242..101760369 100644 --- a/liteflow-core/src/main/java/com/yomahub/liteflow/monitor/MonitorBus.java +++ b/liteflow-core/src/main/java/com/yomahub/liteflow/monitor/MonitorBus.java @@ -38,14 +38,6 @@ public class MonitorBus { private LiteflowConfig liteflowConfig; - private boolean enableLog = false; - - private int queueLimit = 200; - - private long delay = 300000; - - private long preiod = 300000; - private final Logger LOG = LoggerFactory.getLogger(this.getClass()); private final ConcurrentHashMap> statisticsMap = new ConcurrentHashMap<>(); @@ -53,25 +45,9 @@ public class MonitorBus { public MonitorBus(LiteflowConfig liteflowConfig) { this.liteflowConfig = liteflowConfig; - if (ObjectUtil.isNotNull(liteflowConfig.getEnableLog())){ - this.enableLog = liteflowConfig.getEnableLog(); - } - - if (ObjectUtil.isNotNull(liteflowConfig.getQueueLimit())){ - queueLimit = liteflowConfig.getQueueLimit(); - } - - if (ObjectUtil.isNotNull(liteflowConfig.getDelay())){ - delay = liteflowConfig.getDelay(); - } - - if (ObjectUtil.isNotNull(liteflowConfig.getPeriod())){ - preiod = liteflowConfig.getPeriod(); - } - - if(enableLog){ + if(liteflowConfig.getEnableLog()){ Timer timer = new Timer(); - timer.schedule(new MonitorTimeTask(this), delay, preiod); + timer.schedule(new MonitorTimeTask(this), liteflowConfig.getDelay(), liteflowConfig.getPeriod()); } } @@ -79,7 +55,7 @@ public class MonitorBus { if(statisticsMap.containsKey(statistics.getComponentClazzName())){ statisticsMap.get(statistics.getComponentClazzName()).add(statistics); }else{ - BoundedPriorityQueue queue = new BoundedPriorityQueue<>(queueLimit); + BoundedPriorityQueue queue = new BoundedPriorityQueue<>(liteflowConfig.getQueueLimit()); queue.offer(statistics); statisticsMap.put(statistics.getComponentClazzName(), queue); } diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/parser/XmlFlowParser.java b/liteflow-core/src/main/java/com/yomahub/liteflow/parser/XmlFlowParser.java index fba1f8570..6740a9f77 100644 --- a/liteflow-core/src/main/java/com/yomahub/liteflow/parser/XmlFlowParser.java +++ b/liteflow-core/src/main/java/com/yomahub/liteflow/parser/XmlFlowParser.java @@ -142,7 +142,7 @@ public abstract class XmlFlowParser { } else if (condE.getName().equals("when")) { Attribute errorResume = condE.attribute("errorResume"); if (errorResume != null) { - conditionList.add(new WhenCondition(chainNodeList, errorResume.getValue().equals("true"))); + conditionList.add(new WhenCondition(chainNodeList, errorResume.getValue().equals(Boolean.TRUE.toString()))); } else { conditionList.add(new WhenCondition(chainNodeList)); } diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/property/LiteflowConfig.java b/liteflow-core/src/main/java/com/yomahub/liteflow/property/LiteflowConfig.java index 12b62aef3..736d2678d 100644 --- a/liteflow-core/src/main/java/com/yomahub/liteflow/property/LiteflowConfig.java +++ b/liteflow-core/src/main/java/com/yomahub/liteflow/property/LiteflowConfig.java @@ -7,8 +7,13 @@ */ package com.yomahub.liteflow.property; +import cn.hutool.core.util.ObjectUtil; + /** * liteflow的配置实体类 + * 这个类中的属性为什么不用基本类型,而用包装类型呢 + * 是因为这个类是springboot和spring的最终参数获取器,考虑到spring的场景,有些参数不是必须配置。基本类型就会出现默认值的情况。 + * 所以为了要有null值出现,这里采用包装类型 * @author Bryan.Zhang */ public class LiteflowConfig { @@ -35,10 +40,10 @@ public class LiteflowConfig { private Long period; //异步线程池最大线程数 - private int whenMaxWorkers; + private Integer whenMaxWorkers; //异步线程池最大队列数量 - private int whenQueueLimit; + private Integer whenQueueLimit; public String getRuleSource() { return ruleSource; @@ -49,7 +54,11 @@ public class LiteflowConfig { } public Integer getSlotSize() { - return slotSize; + if (ObjectUtil.isNull(slotSize)){ + return 1024; + }else{ + return slotSize; + } } public void setSlotSize(Integer slotSize) { @@ -57,7 +66,11 @@ public class LiteflowConfig { } public Integer getWhenMaxWaitSeconds() { - return whenMaxWaitSeconds; + if (ObjectUtil.isNull(whenMaxWaitSeconds)){ + return 15; + }else{ + return whenMaxWaitSeconds; + } } public void setWhenMaxWaitSeconds(Integer whenMaxWaitSeconds) { @@ -65,7 +78,11 @@ public class LiteflowConfig { } public Integer getQueueLimit() { - return queueLimit; + if (ObjectUtil.isNull(queueLimit)){ + return 200; + }else{ + return queueLimit; + } } public void setQueueLimit(Integer queueLimit) { @@ -73,7 +90,11 @@ public class LiteflowConfig { } public Long getDelay() { - return delay; + if (ObjectUtil.isNull(delay)){ + return 300000L; + }else{ + return delay; + } } public void setDelay(Long delay) { @@ -81,7 +102,11 @@ public class LiteflowConfig { } public Long getPeriod() { - return period; + if (ObjectUtil.isNull(period)){ + return 300000L; + }else{ + return period; + } } public void setPeriod(Long period) { @@ -89,26 +114,38 @@ public class LiteflowConfig { } public Boolean getEnableLog() { - return enableLog; + if (ObjectUtil.isNull(enableLog)){ + return false; + }else{ + return enableLog; + } } public void setEnableLog(Boolean enableLog) { this.enableLog = enableLog; } - public int getWhenMaxWorkers() { - return whenMaxWorkers; + public Integer getWhenMaxWorkers() { + if (ObjectUtil.isNull(whenMaxWorkers)){ + return Runtime.getRuntime().availableProcessors() * 2; + }else{ + return whenMaxWorkers; + } } - public void setWhenMaxWorkers(int whenMaxWorkers) { + public void setWhenMaxWorkers(Integer whenMaxWorkers) { this.whenMaxWorkers = whenMaxWorkers; } - public int getWhenQueueLimit() { - return whenQueueLimit; + public Integer getWhenQueueLimit() { + if (ObjectUtil.isNull(whenQueueLimit)){ + return 512; + }else{ + return whenQueueLimit; + } } - public void setWhenQueueLimit(int whenQueueLimit) { + public void setWhenQueueLimit(Integer whenQueueLimit) { this.whenQueueLimit = whenQueueLimit; } } diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/util/SpringAware.java b/liteflow-core/src/main/java/com/yomahub/liteflow/util/SpringAware.java index a0bedede6..36da55664 100644 --- a/liteflow-core/src/main/java/com/yomahub/liteflow/util/SpringAware.java +++ b/liteflow-core/src/main/java/com/yomahub/liteflow/util/SpringAware.java @@ -30,11 +30,21 @@ public class SpringAware implements ApplicationContextAware { } public static T getBean(String name) { - return (T) applicationContext.getBean(name); + try{ + T t = (T) applicationContext.getBean(name); + return t; + }catch (Exception e){ + return null; + } } public static T getBean(Class clazz) { - return applicationContext.getBean(clazz); + try{ + T t = applicationContext.getBean(clazz); + return t; + }catch (Exception e){ + return null; + } } public static T registerBean(Class c) { diff --git a/liteflow-spring-boot-starter/src/main/java/com/yomahub/liteflow/springboot/LiteflowExecutorAutoConfiguration.java b/liteflow-spring-boot-starter/src/main/java/com/yomahub/liteflow/springboot/LiteflowExecutorAutoConfiguration.java index ee2d0deaf..7c81f3cb2 100644 --- a/liteflow-spring-boot-starter/src/main/java/com/yomahub/liteflow/springboot/LiteflowExecutorAutoConfiguration.java +++ b/liteflow-spring-boot-starter/src/main/java/com/yomahub/liteflow/springboot/LiteflowExecutorAutoConfiguration.java @@ -22,17 +22,9 @@ public class LiteflowExecutorAutoConfiguration { @Bean("whenExecutors") public ExecutorService executorService(LiteflowConfig liteflowConfig) { - int useWorker = liteflowConfig.getWhenMaxWorkers(); - int useQueue = liteflowConfig.getWhenQueueLimit(); - if (useWorker == 0) { - useWorker = Runtime.getRuntime().availableProcessors() + 1; - } - - if (useQueue < 512) { - useQueue = 512; - } - - return ExecutorHelper.buildExecutor(useWorker, useQueue, "liteflow-when-calls", false); + Integer useWorker = liteflowConfig.getWhenMaxWorkers(); + Integer useQueue = liteflowConfig.getWhenQueueLimit(); + return ExecutorHelper.buildExecutor(useWorker, useQueue, "liteflow-when-thead", false); } @Bean diff --git a/liteflow-spring-boot-starter/src/main/resources/META-INF/liteflow-default.properties b/liteflow-spring-boot-starter/src/main/resources/META-INF/liteflow-default.properties index f85c10dbc..60ac4ce71 100644 --- a/liteflow-spring-boot-starter/src/main/resources/META-INF/liteflow-default.properties +++ b/liteflow-spring-boot-starter/src/main/resources/META-INF/liteflow-default.properties @@ -1,7 +1,7 @@ liteflow.rule-source=config/flow.xml liteflow.slot-size=1024 liteflow.when-max-wait-second=15 -liteflow.when-max-workers=3 +liteflow.when-max-workers=4 liteflow.when-queue-limit=512 liteflow.monitor.enable-log=false liteflow.monitor.queue-limit=200 diff --git a/liteflow-test-spring/src/main/resources/applicationContext.xml b/liteflow-test-spring/src/main/resources/applicationContext.xml index 03744237b..6c9fb5111 100644 --- a/liteflow-test-spring/src/main/resources/applicationContext.xml +++ b/liteflow-test-spring/src/main/resources/applicationContext.xml @@ -16,7 +16,7 @@ - + @@ -33,10 +33,6 @@ - - - - diff --git a/liteflow-test-springboot/src/main/java/com/yomahub/flowtest/TestFlow.java b/liteflow-test-springboot/src/main/java/com/yomahub/flowtest/TestFlow.java index ba6286bf4..1e32a2726 100644 --- a/liteflow-test-springboot/src/main/java/com/yomahub/flowtest/TestFlow.java +++ b/liteflow-test-springboot/src/main/java/com/yomahub/flowtest/TestFlow.java @@ -17,7 +17,7 @@ public class TestFlow implements CommandLineRunner { @Override public void run(String... args) throws Exception { - Slot slot = flowExecutor.execute("chain2", "it's a request"); + Slot slot = flowExecutor.execute("chain1", "it's a request"); System.out.println(slot); } } diff --git a/liteflow-test-springboot/src/main/java/com/yomahub/flowtest/components/EComponent.java b/liteflow-test-springboot/src/main/java/com/yomahub/flowtest/components/EComponent.java index 62b9e2af3..8e87c67ac 100644 --- a/liteflow-test-springboot/src/main/java/com/yomahub/flowtest/components/EComponent.java +++ b/liteflow-test-springboot/src/main/java/com/yomahub/flowtest/components/EComponent.java @@ -17,13 +17,9 @@ public class EComponent extends NodeComponent { public void process() { try { Thread.sleep(120L); - System.out.println("E:" + this.getSlot().getOutput("a")); - this.getSlot().setOutput(this.getNodeId(), "E component output"); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("Eomponent executed!"); - } - } From 8eac32a78f0a4babc106fec16d444e462baa27d9 Mon Sep 17 00:00:00 2001 From: bryan31 Date: Sun, 28 Mar 2021 16:51:41 +0800 Subject: [PATCH 09/10] =?UTF-8?q?enhancement=20#I37QVR=20WhenCondition?= =?UTF-8?q?=E6=97=B6=E5=80=99=EF=BC=8C=E5=B9=B6=E5=8F=91=E6=89=A7=E8=A1=8C?= =?UTF-8?q?=E7=9B=AE=E5=89=8D=E4=BC=9A=E6=AF=8F=E6=AC=A1=E6=96=B0=E5=BB=BA?= =?UTF-8?q?=E7=BA=BF=E7=A8=8B=E5=8F=AF=E4=B8=8D=E5=8F=AF=E8=B5=B0=E7=BA=BF?= =?UTF-8?q?=E7=A8=8B=E6=B1=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/yomahub/liteflow/entity/flow/Chain.java | 9 ++++++--- .../com/yomahub/liteflow/parser/XmlFlowParser.java | 2 +- .../springboot/LiteflowMainAutoConfiguration.java | 10 ---------- .../src/main/java/com/yomahub/flowtest/TestFlow.java | 2 +- 4 files changed, 8 insertions(+), 15 deletions(-) diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/entity/flow/Chain.java b/liteflow-core/src/main/java/com/yomahub/liteflow/entity/flow/Chain.java index 74d2a820e..75b4e642f 100644 --- a/liteflow-core/src/main/java/com/yomahub/liteflow/entity/flow/Chain.java +++ b/liteflow-core/src/main/java/com/yomahub/liteflow/entity/flow/Chain.java @@ -8,20 +8,23 @@ */ package com.yomahub.liteflow.entity.flow; +import cn.hutool.core.collection.CollUtil; import cn.hutool.core.util.ObjectUtil; import com.yomahub.liteflow.entity.data.DataBus; import com.yomahub.liteflow.entity.data.Slot; import com.yomahub.liteflow.enums.ExecuteTypeEnum; +import com.yomahub.liteflow.exception.ConfigErrorException; import com.yomahub.liteflow.exception.FlowSystemException; +import com.yomahub.liteflow.exception.WhenExecuteException; import com.yomahub.liteflow.property.LiteflowConfig; +import com.yomahub.liteflow.util.ExecutorHelper; import com.yomahub.liteflow.util.SpringAware; -import org.apache.commons.collections4.CollectionUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.util.ArrayList; import java.util.List; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.TimeUnit; +import java.util.concurrent.*; /** * chain对象,实现可执行器 diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/parser/XmlFlowParser.java b/liteflow-core/src/main/java/com/yomahub/liteflow/parser/XmlFlowParser.java index 9ef59c8fa..45c5678d5 100644 --- a/liteflow-core/src/main/java/com/yomahub/liteflow/parser/XmlFlowParser.java +++ b/liteflow-core/src/main/java/com/yomahub/liteflow/parser/XmlFlowParser.java @@ -12,7 +12,7 @@ import com.yomahub.liteflow.entity.flow.*; import com.yomahub.liteflow.exception.ExecutableItemNotFoundException; import com.yomahub.liteflow.exception.ParseException; import com.yomahub.liteflow.util.SpringAware; -import org.apache.commons.lang3.StringUtils; +import org.dom4j.Attribute; import org.dom4j.Document; import org.dom4j.DocumentHelper; import org.dom4j.Element; diff --git a/liteflow-spring-boot-starter/src/main/java/com/yomahub/liteflow/springboot/LiteflowMainAutoConfiguration.java b/liteflow-spring-boot-starter/src/main/java/com/yomahub/liteflow/springboot/LiteflowMainAutoConfiguration.java index 8662dc075..0877f73d3 100644 --- a/liteflow-spring-boot-starter/src/main/java/com/yomahub/liteflow/springboot/LiteflowMainAutoConfiguration.java +++ b/liteflow-spring-boot-starter/src/main/java/com/yomahub/liteflow/springboot/LiteflowMainAutoConfiguration.java @@ -1,25 +1,15 @@ package com.yomahub.liteflow.springboot; import cn.hutool.core.util.StrUtil; -import com.google.common.collect.Lists; import com.yomahub.liteflow.core.FlowExecutor; -import com.yomahub.liteflow.entity.data.DataBus; import com.yomahub.liteflow.monitor.MonitorBus; import com.yomahub.liteflow.property.LiteflowConfig; -import com.yomahub.liteflow.spring.ComponentScaner; import com.yomahub.liteflow.util.SpringAware; -import org.apache.commons.lang3.StringUtils; import org.springframework.boot.autoconfigure.AutoConfigureAfter; import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; -import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; -import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; -import org.springframework.context.annotation.PropertySource; - -import javax.swing.*; -import java.util.List; /** * 主要的业务装配器 diff --git a/liteflow-test-springboot/src/main/java/com/yomahub/flowtest/TestFlow.java b/liteflow-test-springboot/src/main/java/com/yomahub/flowtest/TestFlow.java index 1e32a2726..ba6286bf4 100644 --- a/liteflow-test-springboot/src/main/java/com/yomahub/flowtest/TestFlow.java +++ b/liteflow-test-springboot/src/main/java/com/yomahub/flowtest/TestFlow.java @@ -17,7 +17,7 @@ public class TestFlow implements CommandLineRunner { @Override public void run(String... args) throws Exception { - Slot slot = flowExecutor.execute("chain1", "it's a request"); + Slot slot = flowExecutor.execute("chain2", "it's a request"); System.out.println(slot); } } From b980e1ce09000b8040ef2f91eb0dbd6494578442 Mon Sep 17 00:00:00 2001 From: zendwang Date: Mon, 29 Mar 2021 12:54:41 +0800 Subject: [PATCH 10/10] =?UTF-8?q?enhancement=20#I3DMX4=20FlowExecutor?= =?UTF-8?q?=E8=AE=B0=E5=BD=95=E4=B8=9A=E5=8A=A1=E5=BC=82=E5=B8=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../yomahub/liteflow/core/FlowExecutor.java | 46 +++++++-------- .../yomahub/liteflow/entity/data/AbsSlot.java | 44 ++++---------- .../entity/data/LiteflowResponse.java | 58 +++++++++++++++++++ .../yomahub/liteflow/entity/data/Slot.java | 8 --- .../java/com/yomahub/flowtest/Runner.java | 6 +- .../java/com/yomahub/flowtest/TestFlow.java | 8 +-- 6 files changed, 99 insertions(+), 71 deletions(-) create mode 100644 liteflow-core/src/main/java/com/yomahub/liteflow/entity/data/LiteflowResponse.java 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 2a88da0b5..84b20153b 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 @@ -7,20 +7,15 @@ */ package com.yomahub.liteflow.core; -import java.text.MessageFormat; -import java.util.List; - import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.ReUtil; import cn.hutool.core.util.StrUtil; import com.google.common.collect.Lists; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.yomahub.liteflow.entity.flow.Chain; import com.yomahub.liteflow.entity.data.DataBus; import com.yomahub.liteflow.entity.data.DefaultSlot; +import com.yomahub.liteflow.entity.data.LiteflowResponse; import com.yomahub.liteflow.entity.data.Slot; +import com.yomahub.liteflow.entity.flow.Chain; import com.yomahub.liteflow.exception.ChainNotFoundException; import com.yomahub.liteflow.exception.ConfigErrorException; import com.yomahub.liteflow.exception.FlowExecutorNotInitException; @@ -30,8 +25,11 @@ import com.yomahub.liteflow.parser.LocalXmlFlowParser; import com.yomahub.liteflow.parser.XmlFlowParser; import com.yomahub.liteflow.parser.ZookeeperXmlFlowParser; import com.yomahub.liteflow.property.LiteflowConfig; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; -import java.util.concurrent.ExecutorService; +import java.text.MessageFormat; +import java.util.List; /** * 流程规则主要执行器类 @@ -98,23 +96,24 @@ public class FlowExecutor { public void reloadRule(){ init(); } - - public T execute(String chainId,Object param) throws Exception{ - return execute(chainId, param, DefaultSlot.class,null,false); + + public void invoke(String chainId, Object param, Class slotClazz, Integer slotIndex) throws Exception { + execute(chainId, param, slotClazz, slotIndex,true); + } + + public LiteflowResponse execute(String chainId, Object param) throws Exception { + return execute(chainId, param, DefaultSlot.class, null, false); } - public T execute(String chainId,Object param,Class slotClazz) throws Exception{ + public LiteflowResponse execute(String chainId, Object param, Class slotClazz) throws Exception { return execute(chainId, param, slotClazz,null,false); } - - public void invoke(String chainId,Object param,Class slotClazz,Integer slotIndex) throws Exception{ - execute(chainId, param, slotClazz,slotIndex,true); - } - - public T execute(String chainId,Object param,Class slotClazz,Integer slotIndex,boolean isInnerChain) throws Exception{ + + public LiteflowResponse execute(String chainId, Object param, Class slotClazz, Integer slotIndex, + boolean isInnerChain) throws Exception { Slot slot = null; - if(FlowBus.needInit()) { + if (FlowBus.needInit()) { init(); } @@ -150,21 +149,22 @@ public class FlowExecutor { } else { slot.setChainReqData(chainId, param); } - + LiteflowResponse response = new LiteflowResponse<>(slot); try { // 执行chain chain.execute(slotIndex); } catch (Exception e) { + response.setSuccess(false); + response.setMessage(e.getMessage()); + response.setCause(e.getCause()); LOG.error("[{}]:chain[{}] execute error on slot[{}]", slot.getRequestId(), chain.getChainName(), slotIndex); - slot.setSuccess(false); - slot.setErrorMsg(e.getMessage()); } finally { if (!isInnerChain) { slot.printStep(); DataBus.releaseSlot(slotIndex); } } - return (T)slot; + return response; } public String getZkNode() { diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/entity/data/AbsSlot.java b/liteflow-core/src/main/java/com/yomahub/liteflow/entity/data/AbsSlot.java index 52bff7d0b..9d07a6e0a 100644 --- a/liteflow-core/src/main/java/com/yomahub/liteflow/entity/data/AbsSlot.java +++ b/liteflow-core/src/main/java/com/yomahub/liteflow/entity/data/AbsSlot.java @@ -7,42 +7,38 @@ */ package com.yomahub.liteflow.entity.data; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import java.util.ArrayDeque; import java.util.Deque; import java.util.Iterator; import java.util.concurrent.ConcurrentHashMap; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - /** * Slot的抽象类实现 * @author Bryan.Zhang */ @SuppressWarnings("unchecked") -public abstract class AbsSlot implements Slot{ +public abstract class AbsSlot implements Slot { private static final Logger LOG = LoggerFactory.getLogger(Slot.class); - private final String REQUEST = "request"; + private static final String REQUEST = "request"; - private final String RESPONSE = "response"; + private static final String RESPONSE = "response"; - private final String CHAINNAME = "chain_name"; + private static final String CHAINNAME = "chain_name"; - private final String COND_NODE_PREFIX = "cond_"; + private static final String COND_NODE_PREFIX = "cond_"; - private final String NODE_INPUT_PREFIX = "input_"; + private static final String NODE_INPUT_PREFIX = "input_"; - private final String NODE_OUTPUT_PREFIX = "output_"; + private static final String NODE_OUTPUT_PREFIX = "output_"; - private final String CHAIN_REQ_PREFIX = "chain_req_"; + private static final String CHAIN_REQ_PREFIX = "chain_req_"; - private final String REQUEST_ID = "req_id"; - - private boolean isSuccess = true; - - private String errorMsg; + private static final String REQUEST_ID = "req_id"; private Deque executeSteps = new ArrayDeque(); @@ -142,20 +138,4 @@ public abstract class AbsSlot implements Slot{ public Deque getExecuteSteps() { return executeSteps; } - - public boolean isSuccess() { - return isSuccess; - } - - public void setSuccess(boolean success) { - isSuccess = success; - } - - public String getErrorMsg() { - return errorMsg; - } - - public void setErrorMsg(String errorMsg) { - this.errorMsg = errorMsg; - } } diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/entity/data/LiteflowResponse.java b/liteflow-core/src/main/java/com/yomahub/liteflow/entity/data/LiteflowResponse.java new file mode 100644 index 000000000..4d46a0d40 --- /dev/null +++ b/liteflow-core/src/main/java/com/yomahub/liteflow/entity/data/LiteflowResponse.java @@ -0,0 +1,58 @@ +package com.yomahub.liteflow.entity.data; + +import java.io.Serializable; + +/** + * 执行结果封装类 + * @author zend.wang + */ +public class LiteflowResponse implements Serializable { + + private static final long serialVersionUID = -2792556188993845048L; + + private boolean success; + + private String message; + + private Throwable cause; + + private T data; + + public LiteflowResponse(T data) { + this.success = true; + this.message = ""; + this.data = data; + } + + public boolean isSuccess() { + return success; + } + + public void setSuccess(final boolean success) { + this.success = success; + } + + public String getMessage() { + return message; + } + + public void setMessage(final String message) { + this.message = message; + } + + public Throwable getCause() { + return cause; + } + + public void setCause(final Throwable cause) { + this.cause = cause; + } + + public T getData() { + return data; + } + + public void setData(final T data) { + this.data = data; + } +} diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/entity/data/Slot.java b/liteflow-core/src/main/java/com/yomahub/liteflow/entity/data/Slot.java index 4ba30a028..ab917ecf7 100644 --- a/liteflow-core/src/main/java/com/yomahub/liteflow/entity/data/Slot.java +++ b/liteflow-core/src/main/java/com/yomahub/liteflow/entity/data/Slot.java @@ -51,12 +51,4 @@ public interface Slot { public void setChainName(String chainName); public String getChainName(); - - public boolean isSuccess(); - - public void setSuccess(boolean success); - - public String getErrorMsg(); - - public void setErrorMsg(String errorMsg); } diff --git a/liteflow-test-spring/src/main/java/com/yomahub/flowtest/Runner.java b/liteflow-test-spring/src/main/java/com/yomahub/flowtest/Runner.java index 31becd387..c465152d9 100644 --- a/liteflow-test-spring/src/main/java/com/yomahub/flowtest/Runner.java +++ b/liteflow-test-spring/src/main/java/com/yomahub/flowtest/Runner.java @@ -1,7 +1,7 @@ package com.yomahub.flowtest; import com.yomahub.liteflow.core.FlowExecutor; -import com.yomahub.liteflow.entity.data.Slot; +import com.yomahub.liteflow.entity.data.LiteflowResponse; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.context.support.ClassPathXmlApplicationContext; @@ -16,8 +16,8 @@ public class Runner { context.start(); log.info("启动成功"); FlowExecutor flowExecutor = context.getBean(FlowExecutor.class); - Slot slot = flowExecutor.execute("chain3", "it's a request"); - System.out.println(slot); + LiteflowResponse response = flowExecutor.execute("chain3", "it's a request"); + System.out.println(response); while (true){ Thread.sleep(60000); diff --git a/liteflow-test-springboot/src/main/java/com/yomahub/flowtest/TestFlow.java b/liteflow-test-springboot/src/main/java/com/yomahub/flowtest/TestFlow.java index ba6286bf4..5e072cd98 100644 --- a/liteflow-test-springboot/src/main/java/com/yomahub/flowtest/TestFlow.java +++ b/liteflow-test-springboot/src/main/java/com/yomahub/flowtest/TestFlow.java @@ -1,9 +1,7 @@ package com.yomahub.flowtest; import com.yomahub.liteflow.core.FlowExecutor; -import com.yomahub.liteflow.entity.data.Slot; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +import com.yomahub.liteflow.entity.data.LiteflowResponse; import org.springframework.boot.CommandLineRunner; import org.springframework.stereotype.Component; @@ -17,7 +15,7 @@ public class TestFlow implements CommandLineRunner { @Override public void run(String... args) throws Exception { - Slot slot = flowExecutor.execute("chain2", "it's a request"); - System.out.println(slot); + LiteflowResponse response= flowExecutor.execute("chain2", "it's a request"); + System.out.println(response); } }