mirror of
https://gitee.com/dromara/liteFlow.git
synced 2026-05-15 04:22:09 +08:00
Merge remote-tracking branch 'origin/master' into v2.6.9
This commit is contained in:
@@ -1,7 +1,6 @@
|
||||
package com.yomahub.liteflow.annotation;
|
||||
|
||||
import org.springframework.core.annotation.AliasFor;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.yomahub.liteflow.annotation.LiteflowComponent;
|
||||
import com.yomahub.liteflow.annotation.LiteflowRetry;
|
||||
import com.yomahub.liteflow.entity.executor.NodeExecutor;
|
||||
import com.yomahub.liteflow.enums.NodeTypeEnum;
|
||||
import com.yomahub.liteflow.property.LiteflowConfig;
|
||||
import com.yomahub.liteflow.property.LiteflowConfigGetter;
|
||||
@@ -47,14 +48,25 @@ public class ComponentInitializer {
|
||||
//先从组件上取@RetryCount标注,如果没有,则看全局配置,全局配置如果不配置的话,默认是0
|
||||
//默认retryForExceptions为Exception.class
|
||||
LiteflowRetry liteflowRetryAnnotation = AnnotationUtils.getAnnotation(nodeComponent.getClass(), LiteflowRetry.class);
|
||||
LiteflowConfig liteflowConfig = LiteflowConfigGetter.get();
|
||||
if (ObjectUtil.isNotNull(liteflowRetryAnnotation)) {
|
||||
nodeComponent.setRetryCount(liteflowRetryAnnotation.retry());
|
||||
nodeComponent.setRetryForExceptions(liteflowRetryAnnotation.forExceptions());
|
||||
} else {
|
||||
LiteflowConfig liteflowConfig = LiteflowConfigGetter.get();
|
||||
nodeComponent.setRetryCount(liteflowConfig.getRetryCount());
|
||||
}
|
||||
nodeComponent.setNodeExecutorClass(buildNodeExecutorClass(liteflowConfig));
|
||||
|
||||
return nodeComponent;
|
||||
}
|
||||
|
||||
private Class<? extends NodeExecutor> buildNodeExecutorClass(LiteflowConfig liteflowConfig) {
|
||||
Class<?> nodeExecutorClass;
|
||||
try {
|
||||
nodeExecutorClass = Class.forName(liteflowConfig.getNodeExecutorClass());
|
||||
} catch (ClassNotFoundException e) {
|
||||
throw new RuntimeException(e.getMessage());
|
||||
}
|
||||
return (Class<? extends NodeExecutor>) nodeExecutorClass;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,6 +11,8 @@ import cn.hutool.core.date.StopWatch;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.alibaba.ttl.TransmittableThreadLocal;
|
||||
import com.yomahub.liteflow.entity.executor.NodeExecutor;
|
||||
import com.yomahub.liteflow.entity.executor.DefaultNodeExecutor;
|
||||
import com.yomahub.liteflow.enums.NodeTypeEnum;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
@@ -21,13 +23,10 @@ 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 com.yomahub.liteflow.spring.ComponentScanner;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
@@ -63,6 +62,10 @@ public abstract class NodeComponent{
|
||||
//在目标异常抛出时才重试
|
||||
private Class<? extends Exception>[] retryForExceptions = new Class[]{Exception.class};
|
||||
|
||||
/** 节点执行器的类全名 */
|
||||
private Class<? extends NodeExecutor> nodeExecutorClass = DefaultNodeExecutor.class;
|
||||
|
||||
|
||||
//是否结束整个流程,这个只对串行流程有效,并行流程无效
|
||||
private final TransmittableThreadLocal<Boolean> isEndTL = new TransmittableThreadLocal<>();
|
||||
|
||||
@@ -231,6 +234,14 @@ public abstract class NodeComponent{
|
||||
this.retryForExceptions = retryForExceptions;
|
||||
}
|
||||
|
||||
public Class<? extends NodeExecutor> getNodeExecutorClass() {
|
||||
return nodeExecutorClass;
|
||||
}
|
||||
|
||||
public void setNodeExecutorClass(Class<? extends NodeExecutor> nodeExecutorClass) {
|
||||
this.nodeExecutorClass = nodeExecutorClass;
|
||||
}
|
||||
|
||||
public void setTag(String tag){
|
||||
this.tagTL.set(tag);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
package com.yomahub.liteflow.entity.executor;
|
||||
|
||||
import com.yomahub.liteflow.core.NodeComponent;
|
||||
import com.yomahub.liteflow.entity.data.DataBus;
|
||||
import com.yomahub.liteflow.entity.data.Slot;
|
||||
|
||||
/**
|
||||
* 默认的节点执行器
|
||||
*
|
||||
* @author sikadai
|
||||
* @date 2022/1/24 17:00
|
||||
*/
|
||||
public class DefaultNodeExecutor extends NodeExecutor {
|
||||
@Override
|
||||
public void execute(NodeComponent instance) throws Exception {
|
||||
super.execute(instance);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
package com.yomahub.liteflow.entity.executor;
|
||||
|
||||
import com.yomahub.liteflow.core.NodeComponent;
|
||||
import com.yomahub.liteflow.entity.data.DataBus;
|
||||
import com.yomahub.liteflow.entity.data.Slot;
|
||||
import com.yomahub.liteflow.exception.ChainEndException;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 节点执行器 - 自定的执行策略需要实现该类
|
||||
*
|
||||
* @author sikadai
|
||||
* @date 2022/1/24 17:00
|
||||
*/
|
||||
public abstract class NodeExecutor {
|
||||
protected final Logger LOG = LoggerFactory.getLogger(this.getClass());
|
||||
|
||||
/**
|
||||
* 执行器执行入口-若需要更大维度的执行方式可以重写该方法
|
||||
*
|
||||
* @param instance : 执行的节点实例
|
||||
* @throws Exception
|
||||
*/
|
||||
public void execute(NodeComponent instance) throws Exception {
|
||||
int retryCount = instance.getRetryCount();
|
||||
List<Class<? extends Exception>> forExceptions = Arrays.asList(instance.getRetryForExceptions());
|
||||
for (int i = 0; i <= retryCount; i++) {
|
||||
try {
|
||||
// 先执行一次
|
||||
if (i == 0) {
|
||||
instance.execute();
|
||||
} else {
|
||||
// 进入重试逻辑
|
||||
retry(instance, i);
|
||||
}
|
||||
break;
|
||||
} catch (ChainEndException e) {
|
||||
//如果是ChainEndException,则无需重试
|
||||
throw e;
|
||||
} catch (Exception e) {
|
||||
//判断抛出的异常是不是指定异常的子类
|
||||
boolean flag = forExceptions.stream().anyMatch(clazz -> clazz.isAssignableFrom(e.getClass()));
|
||||
//两种情况不重试,1)抛出异常不在指定异常范围内 2)已经重试次数大于等于配置次数
|
||||
if (!flag || i >= retryCount) {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行重试逻辑 - 子类通过实现该方法进行重试逻辑的控制
|
||||
*
|
||||
* @param instance : 执行的节点实例
|
||||
* @param currentRetryCount : 当前重试的次数
|
||||
* @throws Exception
|
||||
*/
|
||||
|
||||
protected void retry(NodeComponent instance, int currentRetryCount) throws Exception {
|
||||
Slot slot = DataBus.getSlot(instance.getSlotIndex());
|
||||
LOG.info("[{}]:component[{}] performs {} retry", slot.getRequestId(), instance.getNodeId(), currentRetryCount + 1);
|
||||
//执行业务逻辑的主要入口
|
||||
instance.execute();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
package com.yomahub.liteflow.entity.executor;
|
||||
|
||||
import cn.hutool.core.util.ReflectUtil;
|
||||
import com.google.common.collect.Maps;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 节点执行器帮助器
|
||||
*
|
||||
* @author sikadai
|
||||
* @date 2022/1/24 19:00
|
||||
*/
|
||||
public class NodeExecutorHelper {
|
||||
/**
|
||||
* 此处使用Map缓存线程池信息
|
||||
* key - 节点执行器类Class全名
|
||||
* value - 节点执行器对象
|
||||
*/
|
||||
private final Map<Class<? extends NodeExecutor>, NodeExecutor> nodeExecutorMap;
|
||||
|
||||
private NodeExecutorHelper() {
|
||||
nodeExecutorMap = Maps.newConcurrentMap();
|
||||
}
|
||||
|
||||
/**
|
||||
* 使用静态内部类实现单例模式
|
||||
*/
|
||||
private static class Holder {
|
||||
static final NodeExecutorHelper INSTANCE = new NodeExecutorHelper();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取帮助者的实例
|
||||
*/
|
||||
public static NodeExecutorHelper loadInstance() {
|
||||
// 外围类能直接访问内部类(不管是否是静态的)的私有变量
|
||||
return Holder.INSTANCE;
|
||||
}
|
||||
|
||||
/**
|
||||
* 单例模式驱动-通过调用该方法构建节点执行器
|
||||
*/
|
||||
/**
|
||||
* 单例模式驱动-通过调用该方法构建节点执行器
|
||||
* 若nodeExecutorClass为空,则会使用默认的节点执行器
|
||||
*
|
||||
* @param nodeExecutorClass : 节点执行器的Class
|
||||
* @return
|
||||
*/
|
||||
public NodeExecutor buildNodeExecutor(Class<? extends NodeExecutor> nodeExecutorClass) {
|
||||
// 高频操作-采取apache判空操作-效率高于hotool的isBlank将近3倍
|
||||
if (nodeExecutorClass == null) {
|
||||
// 此处使用默认的节点执行器进行执行
|
||||
nodeExecutorClass = DefaultNodeExecutor.class;
|
||||
}
|
||||
NodeExecutor nodeExecutor = nodeExecutorMap.get(nodeExecutorClass);
|
||||
// 此处无需使用同步锁进行同步-因为即使同时创建了两个实例,但是添加到缓存中的只会存在一个且不会存在并发问题-具体是由ConcurrentMap保证
|
||||
if (nodeExecutor == null) {
|
||||
// 获取重试执行器实例
|
||||
nodeExecutor = ReflectUtil.newInstance(nodeExecutorClass);
|
||||
// 缓存
|
||||
nodeExecutorMap.put(nodeExecutorClass, nodeExecutor);
|
||||
}
|
||||
return nodeExecutorMap.get(nodeExecutorClass);
|
||||
}
|
||||
}
|
||||
@@ -8,9 +8,7 @@
|
||||
package com.yomahub.liteflow.entity.flow;
|
||||
|
||||
import java.text.MessageFormat;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
@@ -18,6 +16,8 @@ import cn.hutool.core.util.StrUtil;
|
||||
import com.yomahub.liteflow.core.NodeComponent;
|
||||
import com.yomahub.liteflow.entity.data.DataBus;
|
||||
import com.yomahub.liteflow.entity.data.Slot;
|
||||
import com.yomahub.liteflow.entity.executor.NodeExecutor;
|
||||
import com.yomahub.liteflow.entity.executor.NodeExecutorHelper;
|
||||
import com.yomahub.liteflow.enums.ExecuteTypeEnum;
|
||||
import com.yomahub.liteflow.enums.NodeTypeEnum;
|
||||
import com.yomahub.liteflow.exception.ChainEndException;
|
||||
@@ -121,31 +121,9 @@ public class Node implements Executable,Cloneable{
|
||||
//判断是否可执行,所以isAccess经常作为一个组件进入的实际判断要素,用作检查slot里的参数的完备性
|
||||
if (instance.isAccess()) {
|
||||
//这里开始进行重试的逻辑和主逻辑的运行
|
||||
int retryCount = instance.getRetryCount();
|
||||
List<Class<? extends Exception>> forExceptions = Arrays.asList(instance.getRetryForExceptions());
|
||||
for (int i = 0; i <= retryCount; i++) {
|
||||
try {
|
||||
if (i > 0) {
|
||||
LOG.info("[{}]:component[{}] performs {} retry", slot.getRequestId(), id, i + 1);
|
||||
}
|
||||
//执行业务逻辑的主要入口
|
||||
instance.execute();
|
||||
break;
|
||||
} catch (ChainEndException e) {
|
||||
//如果是ChainEndException,则无需重试
|
||||
throw e;
|
||||
} catch (Exception e) {
|
||||
//判断抛出的异常是不是指定异常的子类
|
||||
boolean flag = forExceptions.stream().anyMatch(clazz -> clazz.isAssignableFrom(e.getClass()));
|
||||
|
||||
//两种情况不重试,1)抛出异常不在指定异常范围内 2)已经重试次数大于等于配置次数
|
||||
if (!flag || i >= retryCount) {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
NodeExecutor nodeExecutor = NodeExecutorHelper.loadInstance().buildNodeExecutor(instance.getNodeExecutorClass());
|
||||
// 调用节点执行器进行执行
|
||||
nodeExecutor.execute(instance);
|
||||
//如果组件覆盖了isEnd方法,或者在在逻辑中主要调用了setEnd(true)的话,流程就会立马结束
|
||||
if (instance.isEnd()) {
|
||||
String errorInfo = StrUtil.format("[{}]:component[{}] lead the chain to end", slot.getRequestId(), instance.getClass().getSimpleName());
|
||||
|
||||
@@ -70,6 +70,8 @@ public class LiteflowConfig {
|
||||
|
||||
//重试次数
|
||||
private Integer retryCount;
|
||||
// 节点执行器的类全名
|
||||
private String nodeExecutorClass;
|
||||
|
||||
//是否打印liteflow banner
|
||||
private Boolean printBanner;
|
||||
@@ -261,4 +263,12 @@ public class LiteflowConfig {
|
||||
public void setThreadExecutorClass(String threadExecutorClass) {
|
||||
this.threadExecutorClass = threadExecutorClass;
|
||||
}
|
||||
|
||||
public String getNodeExecutorClass() {
|
||||
return nodeExecutorClass;
|
||||
}
|
||||
|
||||
public void setNodeExecutorClass(String nodeExecutorClass) {
|
||||
this.nodeExecutorClass = nodeExecutorClass;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,7 +9,6 @@
|
||||
package com.yomahub.liteflow.thread;
|
||||
|
||||
import cn.hutool.core.map.MapUtil;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.google.common.collect.Maps;
|
||||
import com.yomahub.liteflow.exception.ThreadExecutorServiceCreateException;
|
||||
@@ -31,8 +30,6 @@ public class ExecutorHelper {
|
||||
|
||||
private final Logger LOG = LoggerFactory.getLogger(ExecutorHelper.class);
|
||||
|
||||
private static ExecutorHelper executorHelper;
|
||||
|
||||
/**
|
||||
* 此处使用Map缓存线程池信息
|
||||
* key - 线程池构建者的Class全类名
|
||||
@@ -44,11 +41,15 @@ public class ExecutorHelper {
|
||||
executorServiceMap = Maps.newConcurrentMap();
|
||||
}
|
||||
|
||||
/**
|
||||
* 使用静态内部类实现单例模式
|
||||
*/
|
||||
private static class Holder {
|
||||
static final ExecutorHelper INSTANCE = new ExecutorHelper();
|
||||
}
|
||||
|
||||
public static ExecutorHelper loadInstance() {
|
||||
if (ObjectUtil.isNull(executorHelper)) {
|
||||
executorHelper = new ExecutorHelper();
|
||||
}
|
||||
return executorHelper;
|
||||
return Holder.INSTANCE;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -47,6 +47,9 @@ public class LiteflowProperty {
|
||||
//是否打印liteflow banner
|
||||
private boolean printBanner;
|
||||
|
||||
// 节点执行器class全名
|
||||
private String nodeExecutorClass;
|
||||
|
||||
public boolean isEnable() {
|
||||
return enable;
|
||||
}
|
||||
@@ -142,4 +145,12 @@ public class LiteflowProperty {
|
||||
public void setThreadExecutorClass(String threadExecutorClass) {
|
||||
this.threadExecutorClass = threadExecutorClass;
|
||||
}
|
||||
|
||||
public String getNodeExecutorClass() {
|
||||
return nodeExecutorClass;
|
||||
}
|
||||
|
||||
public void setNodeExecutorClass(String nodeExecutorClass) {
|
||||
this.nodeExecutorClass = nodeExecutorClass;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,6 +41,7 @@ public class LiteflowPropertyAutoConfiguration {
|
||||
liteflowConfig.setRetryCount(property.getRetryCount());
|
||||
liteflowConfig.setZkNode(property.getZkNode());
|
||||
liteflowConfig.setPrintBanner(property.isPrintBanner());
|
||||
liteflowConfig.setNodeExecutorClass(property.getNodeExecutorClass());
|
||||
return liteflowConfig;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,4 +12,5 @@ liteflow.support-multiple-type=false
|
||||
liteflow.monitor.enable-log=false
|
||||
liteflow.monitor.queue-limit=200
|
||||
liteflow.monitor.delay=300000
|
||||
liteflow.monitor.period=300000
|
||||
liteflow.monitor.period=300000
|
||||
liteflow.node-executor-class=com.yomahub.liteflow.entity.executor.DefaultNodeExecutor
|
||||
@@ -7,7 +7,6 @@ import com.yomahub.liteflow.test.BaseTest;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.context.annotation.ComponentScan;
|
||||
@@ -18,7 +17,7 @@ import javax.annotation.Resource;
|
||||
|
||||
|
||||
/**
|
||||
* 测试springboot下的组件重试
|
||||
* 测试springboot下的节点执行器
|
||||
* @author Bryan.Zhang
|
||||
* @since 2.5.10
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
package com.yomahub.liteflow.test.nodeExecutor;
|
||||
|
||||
import com.yomahub.liteflow.core.NodeComponent;
|
||||
import com.yomahub.liteflow.entity.data.DataBus;
|
||||
import com.yomahub.liteflow.entity.data.Slot;
|
||||
import com.yomahub.liteflow.entity.executor.NodeExecutor;
|
||||
|
||||
/**
|
||||
* 自定义默认的节点执行器
|
||||
*/
|
||||
public class CustomerDefaultNodeExecutor extends NodeExecutor {
|
||||
@Override
|
||||
public void execute(NodeComponent instance) throws Exception {
|
||||
Slot slot = DataBus.getSlot(instance.getSlotIndex());
|
||||
LOG.info("使用customerDefaultNodeExecutor进行执行");
|
||||
slot.setData("customerDefaultNodeExecutor", this.getClass());
|
||||
super.execute(instance);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package com.yomahub.liteflow.test.nodeExecutor;
|
||||
|
||||
import com.yomahub.liteflow.core.NodeComponent;
|
||||
import com.yomahub.liteflow.entity.data.DataBus;
|
||||
import com.yomahub.liteflow.entity.data.Slot;
|
||||
import com.yomahub.liteflow.entity.executor.NodeExecutor;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* 自定义节点执行器
|
||||
*/
|
||||
public class CustomerNodeExecutor extends NodeExecutor {
|
||||
@Override
|
||||
public void execute(NodeComponent instance) throws Exception {
|
||||
Slot slot = DataBus.getSlot(instance.getSlotIndex());
|
||||
LOG.info("使用customerNodeExecutor进行执行");
|
||||
slot.setData("customerNodeExecutor", this.getClass());
|
||||
super.execute(instance);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package com.yomahub.liteflow.test.nodeExecutor;
|
||||
|
||||
import com.yomahub.liteflow.core.NodeComponent;
|
||||
import com.yomahub.liteflow.entity.data.DataBus;
|
||||
import com.yomahub.liteflow.entity.data.Slot;
|
||||
import com.yomahub.liteflow.entity.executor.NodeExecutor;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* 自定义节点执行器
|
||||
*/
|
||||
public class CustomerNodeExecutorAndCustomRetry extends NodeExecutor {
|
||||
@Override
|
||||
public void execute(NodeComponent instance) throws Exception {
|
||||
Slot slot = DataBus.getSlot(instance.getSlotIndex());
|
||||
LOG.info("使用customerNodeExecutorAndCustomRetry进行执行");
|
||||
slot.setData("customerNodeExecutorAndCustomRetry", this.getClass());
|
||||
super.execute(instance);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void retry(NodeComponent instance, int currentRetryCount) throws Exception {
|
||||
TimeUnit.MICROSECONDS.sleep(20L);
|
||||
Slot slot = DataBus.getSlot(instance.getSlotIndex());
|
||||
slot.setData("retryLogic", this.getClass());
|
||||
super.retry(instance, currentRetryCount);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
package com.yomahub.liteflow.test.nodeExecutor;
|
||||
|
||||
import com.yomahub.liteflow.core.FlowExecutor;
|
||||
import com.yomahub.liteflow.entity.data.DefaultSlot;
|
||||
import com.yomahub.liteflow.entity.data.LiteflowResponse;
|
||||
import com.yomahub.liteflow.entity.executor.DefaultNodeExecutor;
|
||||
import com.yomahub.liteflow.test.BaseTest;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.context.annotation.ComponentScan;
|
||||
import org.springframework.test.context.TestPropertySource;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
|
||||
/**
|
||||
* 测试springboot下的组件重试
|
||||
*
|
||||
* @author Bryan.Zhang
|
||||
* @since 2.5.10
|
||||
*/
|
||||
@RunWith(SpringRunner.class)
|
||||
@TestPropertySource(value = "classpath:/nodeExecutor/application.properties")
|
||||
@SpringBootTest(classes = LiteflowNodeExecutorSpringbootTest.class)
|
||||
@EnableAutoConfiguration
|
||||
@ComponentScan({"com.yomahub.liteflow.test.nodeExecutor.cmp"})
|
||||
public class LiteflowNodeExecutorSpringbootTest extends BaseTest {
|
||||
|
||||
@Resource
|
||||
private FlowExecutor flowExecutor;
|
||||
|
||||
// 默认执行器测试
|
||||
@Test
|
||||
public void testCustomerDefaultNodeExecutor() {
|
||||
LiteflowResponse<DefaultSlot> response = flowExecutor.execute2Resp("chain1", "arg");
|
||||
Assert.assertTrue(response.isSuccess());
|
||||
Assert.assertEquals(CustomerDefaultNodeExecutor.class, response.getSlot().getData("customerDefaultNodeExecutor"));
|
||||
Assert.assertEquals("a", response.getSlot().getExecuteStepStr());
|
||||
}
|
||||
|
||||
//默认执行器测试+全局重试配置测试
|
||||
@Test
|
||||
public void testDefaultExecutorForRetry() {
|
||||
LiteflowResponse<DefaultSlot> response = flowExecutor.execute2Resp("chain2", "arg");
|
||||
Assert.assertTrue(response.isSuccess());
|
||||
Assert.assertEquals(CustomerDefaultNodeExecutor.class, response.getSlot().getData("customerDefaultNodeExecutor"));
|
||||
Assert.assertEquals("b==>b==>b", response.getSlot().getExecuteStepStr());
|
||||
}
|
||||
|
||||
//自定义执行器测试
|
||||
@Test
|
||||
public void testCustomerExecutor() {
|
||||
LiteflowResponse<DefaultSlot> response = flowExecutor.execute2Resp("chain3", "arg");
|
||||
Assert.assertTrue(response.isSuccess());
|
||||
Assert.assertEquals("c", response.getSlot().getExecuteStepStr());
|
||||
}
|
||||
|
||||
//自定义执行器测试+全局重试配置测试
|
||||
@Test
|
||||
public void testCustomExecutorForRetry() {
|
||||
LiteflowResponse<DefaultSlot> response = flowExecutor.execute2Resp("chain4", "arg");
|
||||
Assert.assertFalse(response.isSuccess());
|
||||
Assert.assertEquals(CustomerNodeExecutorAndCustomRetry.class, response.getSlot().getData("retryLogic"));
|
||||
Assert.assertEquals("d==>d==>d==>d==>d==>d", response.getSlot().getExecuteStepStr());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
/**
|
||||
* <p>Title: liteflow</p>
|
||||
* <p>Description: 轻量级的组件式流程框架</p>
|
||||
*
|
||||
* @author Bryan.Zhang
|
||||
* @email weenyc31@163.com
|
||||
* @Date 2020/4/1
|
||||
*/
|
||||
package com.yomahub.liteflow.test.nodeExecutor.cmp;
|
||||
|
||||
import com.yomahub.liteflow.annotation.LiteflowComponent;
|
||||
import com.yomahub.liteflow.core.NodeComponent;
|
||||
|
||||
@LiteflowComponent("a")
|
||||
public class ACmp extends NodeComponent {
|
||||
|
||||
@Override
|
||||
public void process() {
|
||||
System.out.println("ACmp executed!");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
/**
|
||||
* <p>Title: liteflow</p>
|
||||
* <p>Description: 轻量级的组件式流程框架</p>
|
||||
* @author Bryan.Zhang
|
||||
* @email weenyc31@163.com
|
||||
* @Date 2020/4/1
|
||||
*/
|
||||
package com.yomahub.liteflow.test.nodeExecutor.cmp;
|
||||
|
||||
import com.yomahub.liteflow.annotation.LiteflowComponent;
|
||||
import com.yomahub.liteflow.core.NodeComponent;
|
||||
|
||||
@LiteflowComponent("b")
|
||||
public class BCmp extends NodeComponent {
|
||||
|
||||
private int flag = 0;
|
||||
|
||||
@Override
|
||||
public void process() {
|
||||
System.out.println("BCmp executed!");
|
||||
if (flag < 2){
|
||||
flag++;
|
||||
throw new RuntimeException("demo exception");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
/**
|
||||
* <p>Title: liteflow</p>
|
||||
* <p>Description: 轻量级的组件式流程框架</p>
|
||||
* @author Bryan.Zhang
|
||||
* @email weenyc31@163.com
|
||||
* @Date 2020/4/1
|
||||
*/
|
||||
package com.yomahub.liteflow.test.nodeExecutor.cmp;
|
||||
|
||||
import com.yomahub.liteflow.annotation.LiteflowComponent;
|
||||
import com.yomahub.liteflow.annotation.LiteflowRetry;
|
||||
import com.yomahub.liteflow.core.NodeComponent;
|
||||
import com.yomahub.liteflow.entity.executor.NodeExecutor;
|
||||
import com.yomahub.liteflow.test.nodeExecutor.CustomerNodeExecutor;
|
||||
|
||||
@LiteflowComponent("c")
|
||||
@LiteflowRetry(5)
|
||||
public class CCmp extends NodeComponent {
|
||||
|
||||
@Override
|
||||
public void process() {
|
||||
System.out.println("CCmp executed!");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<? extends NodeExecutor> getNodeExecutorClass() {
|
||||
return CustomerNodeExecutor.class;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
/**
|
||||
* <p>Title: liteflow</p>
|
||||
* <p>Description: 轻量级的组件式流程框架</p>
|
||||
*
|
||||
* @author Bryan.Zhang
|
||||
* @email weenyc31@163.com
|
||||
* @Date 2020/4/1
|
||||
*/
|
||||
package com.yomahub.liteflow.test.nodeExecutor.cmp;
|
||||
|
||||
import com.yomahub.liteflow.annotation.LiteflowComponent;
|
||||
import com.yomahub.liteflow.annotation.LiteflowRetry;
|
||||
import com.yomahub.liteflow.core.NodeComponent;
|
||||
import com.yomahub.liteflow.entity.executor.NodeExecutor;
|
||||
import com.yomahub.liteflow.test.nodeExecutor.CustomerNodeExecutorAndCustomRetry;
|
||||
|
||||
@LiteflowComponent("d")
|
||||
@LiteflowRetry(retry = 5, forExceptions = {NullPointerException.class})
|
||||
public class DCmp extends NodeComponent {
|
||||
|
||||
@Override
|
||||
public void process() {
|
||||
System.out.println("DCmp executed!");
|
||||
throw new NullPointerException("demo exception");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<? extends NodeExecutor> getNodeExecutorClass() {
|
||||
return CustomerNodeExecutorAndCustomRetry.class;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
liteflow.rule-source=nodeExecutor/flow.xml
|
||||
liteflow.retry-count=3
|
||||
liteflow.slot-size=512
|
||||
liteflow.node-executor-class=com.yomahub.liteflow.test.nodeExecutor.CustomerDefaultNodeExecutor
|
||||
@@ -0,0 +1,18 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<flow>
|
||||
<chain name="chain1">
|
||||
<then value="a"/>
|
||||
</chain>
|
||||
|
||||
<chain name="chain2">
|
||||
<then value="b"/>
|
||||
</chain>
|
||||
|
||||
<chain name="chain3">
|
||||
<then value="c"/>
|
||||
</chain>
|
||||
|
||||
<chain name="chain4">
|
||||
<then value="d"/>
|
||||
</chain>
|
||||
</flow>
|
||||
Reference in New Issue
Block a user