Merge remote-tracking branch 'upstream/dev' into dev

This commit is contained in:
zy
2023-07-23 22:09:43 +08:00
64 changed files with 1433 additions and 1015 deletions

View File

@@ -18,10 +18,16 @@ public @interface LiteflowMethod {
/**
* 节点ID用于区分节点 默认为空 则按照Spring模式下BeanName为准。
* @return
* @return nodeId
*/
String nodeId() default "";
/**
* 节点Name
* @return nodeName
*/
String nodeName() default "";
/**
* CMP类型定义
* @return AnnotationNodeTypeEnum

View File

@@ -126,7 +126,7 @@ public abstract class NodeComponent {
stopWatch.stop();
final long timeSpent = stopWatch.getTotalTimeMillis();
LOG.debug("component[{}] finished in {} milliseconds", this.getDisplayName(), timeSpent);
LOG.info("component[{}] finished in {} milliseconds", this.getDisplayName(), timeSpent);
// 往CmpStep中放入时间消耗信息
cmpStep.setTimeSpent(timeSpent);

View File

@@ -10,8 +10,10 @@ import com.yomahub.liteflow.enums.LiteFlowMethodEnum;
import com.yomahub.liteflow.enums.NodeTypeEnum;
import com.yomahub.liteflow.exception.ComponentMethodDefineErrorException;
import com.yomahub.liteflow.exception.LiteFlowException;
import com.yomahub.liteflow.exception.ProxyException;
import com.yomahub.liteflow.log.LFLog;
import com.yomahub.liteflow.log.LFLoggerManager;
import com.yomahub.liteflow.spi.holder.LiteflowComponentSupportHolder;
import com.yomahub.liteflow.util.LiteFlowProxyUtil;
import com.yomahub.liteflow.util.SerialsUtil;
import net.bytebuddy.ByteBuddy;
@@ -27,6 +29,7 @@ import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Predicate;
import java.util.stream.Collectors;
/**
@@ -93,8 +96,23 @@ public class ComponentProxy {
boolean legal = classes.size() == 1;
if (!legal) {
throw new LiteFlowException("The cmpClass of the same nodeId must be the same,you declared nodeId:"
+ activeNodeId + ",cmpClass:" + classes);
+ activeNodeId + ",cmpClass:" + clazz);
}
String activeNodeName;
if (isMethodCreate){
// 获取process上的LiteflowMethod
LiteflowMethod mainliteflowMethod = methodList.stream().filter(liteflowMethod -> liteflowMethod.value().isMainMethod()).findFirst().orElse(null);
if (mainliteflowMethod == null){
String errMsg = StrUtil.format("you have not defined @LiteFlowMethod on the processXXX method in class {}", clazz.getName());
throw new LiteFlowException(errMsg);
}
activeNodeName = mainliteflowMethod.nodeName();
}else{
activeNodeName = LiteflowComponentSupportHolder.loadLiteflowComponentSupport().getCmpName(bean);
}
// 当前节点实际LiteflowRetry注解
AtomicReference<LiteflowRetry> liteflowRetryAtomicReference = new AtomicReference<>(null);
// 相同nodeId只能有一个LiteflowRetry定义方法,且必须再Process方法上
@@ -150,10 +168,12 @@ public class ComponentProxy {
NodeComponent nodeComponent = (NodeComponent) instance;
// 重设nodeId
nodeComponent.setNodeId(activeNodeId);
// 重设nodeName
nodeComponent.setName(activeNodeName);
return nodeComponent;
}
catch (Exception e) {
throw new LiteFlowException(e);
throw new ProxyException(e);
}
}).collect(Collectors.toList());
}

View File

@@ -2,14 +2,19 @@ package com.yomahub.liteflow.enums;
public enum LiteFlowMethodEnum {
PROCESS("process", true), PROCESS_SWITCH("processSwitch", true), PROCESS_IF("processIf", true),
PROCESS_FOR("processFor", true), PROCESS_WHILE("processWhile", true), PROCESS_BREAK("processBreak", true),
PROCESS("process", true),
PROCESS_SWITCH("processSwitch", true),
PROCESS_IF("processIf", true),
PROCESS_FOR("processFor", true),
PROCESS_WHILE("processWhile", true),
PROCESS_BREAK("processBreak", true),
PROCESS_ITERATOR("processIterator", true),
IS_ACCESS("isAccess", false),
IS_END("isEnd", false), IS_CONTINUE_ON_ERROR("isContinueOnError", false),
IS_END("isEnd", false),
IS_CONTINUE_ON_ERROR("isContinueOnError", false),
GET_NODE_EXECUTOR_CLASS("getNodeExecutorClass", false),
@@ -19,7 +24,10 @@ public enum LiteFlowMethodEnum {
BEFORE_PROCESS("beforeProcess", false),
AFTER_PROCESS("afterProcess", false);
AFTER_PROCESS("afterProcess", false),
GET_DISPLAY_NAME("getDisplayName", false)
;
private String methodName;

View File

@@ -0,0 +1,31 @@
package com.yomahub.liteflow.exception;
/**
* @author Bryan.Zhang
*/
public class ProxyException extends RuntimeException {
private static final long serialVersionUID = 1L;
/** 异常信息 */
private String message;
public ProxyException(String message) {
this.message = message;
}
public ProxyException(Throwable cause) {
super(cause);
}
@Override
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}

View File

@@ -93,7 +93,7 @@ public class FlowBus {
}
nodeMap.put(nodeId,
new Node(ComponentInitializer.loadInstance().initComponent(nodeComponent, type, null, nodeId)));
new Node(ComponentInitializer.loadInstance().initComponent(nodeComponent, type, nodeComponent.getName(), nodeId)));
}
/**

View File

@@ -1,7 +1,6 @@
package com.yomahub.liteflow.flow.element.condition;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.BooleanUtil;
import cn.hutool.core.util.StrUtil;
import com.yomahub.liteflow.enums.ConditionTypeEnum;
import com.yomahub.liteflow.exception.AndOrConditionException;
@@ -11,7 +10,9 @@ import com.yomahub.liteflow.log.LFLog;
import com.yomahub.liteflow.log.LFLoggerManager;
import com.yomahub.liteflow.slot.DataBus;
import com.yomahub.liteflow.slot.Slot;
import java.util.List;
import java.util.function.Predicate;
public class AndOrCondition extends Condition {
@@ -23,21 +24,10 @@ public class AndOrCondition extends Condition {
public void executeCondition(Integer slotIndex) throws Exception {
List<Executable> itemList = this.getItem();
if (CollUtil.isEmpty(itemList)){
throw new AndOrConditionException("boolean item list is null");
}
boolean[] booleanArray = new boolean[itemList.size()];
for (int i = 0; i < itemList.size(); i++) {
Executable item = itemList.get(i);
item.setCurrChainId(this.getCurrChainId());
item.execute(slotIndex);
booleanArray[i] = item.getItemResultMetaValue(slotIndex);
LOG.info("the result of boolean component [{}] is [{}]", item.getId(), booleanArray[i]);
}
BooleanConditionTypeEnum booleanConditionType = this.getBooleanConditionType();
Slot slot = DataBus.getSlot(slotIndex);
@@ -45,16 +35,37 @@ public class AndOrCondition extends Condition {
String resultKey = StrUtil.format("{}_{}",this.getClass().getName(),this.hashCode());
switch (booleanConditionType) {
case AND:
slot.setAndOrResult(resultKey, BooleanUtil.and(booleanArray));
slot.setAndOrResult(resultKey, itemList.stream().allMatch(new AndOrConditionPredicate(slotIndex)));
break;
case OR:
slot.setAndOrResult(resultKey, BooleanUtil.or(booleanArray));
slot.setAndOrResult(resultKey, itemList.stream().anyMatch(new AndOrConditionPredicate(slotIndex)));
break;
default:
throw new AndOrConditionException("condition type must be 'AND' or 'OR'");
}
}
private class AndOrConditionPredicate implements Predicate<Executable> {
private final Integer slotIndex;
public AndOrConditionPredicate(Integer slotIndex) {
this.slotIndex = slotIndex;
}
@Override
public boolean test(Executable condition) {
try {
condition.setCurrChainId(getCurrChainId());
condition.execute(slotIndex);
return condition.getItemResultMetaValue(slotIndex);
} catch (Exception e) {
throw new AndOrConditionException(e.getMessage());
}
}
}
@Override
@SuppressWarnings("unchecked")

View File

@@ -63,13 +63,21 @@ public class MonitorFile {
@Override
public void onFileChange(File file) {
LOG.info("file modify,filePath={}", file.getAbsolutePath());
FlowExecutorHolder.loadInstance().reloadRule();
this.reloadRule();
}
@Override
public void onFileDelete(File file) {
LOG.info("file delete,filePath={}", file.getAbsolutePath());
FlowExecutorHolder.loadInstance().reloadRule();
this.reloadRule();
}
private void reloadRule() {
try {
FlowExecutorHolder.loadInstance().reloadRule();
} catch (Exception e) {
LOG.error("reload rule error", e);
}
}
});
// 创建文件变化监听器

View File

@@ -140,6 +140,8 @@ public class ParserHelper {
// 校验加载的 chainName 是否有重复的
// TODO 这里是否有个问题当混合格式加载的时候2个同名的Chain在不同的文件里就不行了
String chainName = Optional.ofNullable(e.attributeValue(ID)).orElse(e.attributeValue(NAME));
// 检查 chainName
checkChainId(chainName, e.getText());
if (!chainNameSet.add(chainName)) {
throw new ChainDuplicateException(String.format("[chain name duplicate] chainName=%s", chainName));
}
@@ -202,9 +204,11 @@ public class ParserHelper {
JsonNode innerJsonObject = iterator.next();
// 校验加载的 chainName 是否有重复的
// TODO 这里是否有个问题当混合格式加载的时候2个同名的Chain在不同的文件里就不行了
String chainName = Optional.ofNullable(innerJsonObject.get(ID))
.orElse(innerJsonObject.get(NAME))
.textValue();
JsonNode chainNameJsonNode = Optional.ofNullable(innerJsonObject.get(ID))
.orElse(innerJsonObject.get(NAME));
String chainName = Optional.ofNullable(chainNameJsonNode).map(JsonNode::textValue).orElse(null);
// 检查 chainName
checkChainId(chainName, innerJsonObject.toPrettyString());
if (!chainNameSet.add(chainName)) {
throw new ChainDuplicateException(String.format("[chain name duplicate] chainName=%s", chainName));
}
@@ -250,6 +254,17 @@ public class ParserHelper {
chainELBuilder.setEL(el).build();
}
/**
* 检查 chainId
* @param chainId chainId
* @param elData elData
*/
private static void checkChainId(String chainId, String elData) {
if (StrUtil.isBlank(chainId)) {
throw new ParseException("missing chain id in expression \r\n" + elData);
}
}
private static class RegexUtil {
// java 注释的正则表达式

View File

@@ -3,6 +3,7 @@ package com.yomahub.liteflow.script.proxy;
import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.util.*;
import com.yomahub.liteflow.exception.LiteFlowException;
import com.yomahub.liteflow.exception.ProxyException;
import com.yomahub.liteflow.exception.ScriptBeanMethodInvokeException;
import com.yomahub.liteflow.log.LFLog;
import com.yomahub.liteflow.log.LFLoggerManager;
@@ -10,8 +11,18 @@ import com.yomahub.liteflow.script.annotation.ScriptBean;
import com.yomahub.liteflow.util.LiteFlowProxyUtil;
import com.yomahub.liteflow.util.SerialsUtil;
import net.bytebuddy.ByteBuddy;
import net.bytebuddy.description.method.ParameterDescription;
import net.bytebuddy.description.modifier.Visibility;
import net.bytebuddy.dynamic.DynamicType;
import net.bytebuddy.dynamic.scaffold.subclass.ConstructorStrategy;
import net.bytebuddy.implementation.FixedValue;
import net.bytebuddy.implementation.InvocationHandlerAdapter;
import net.bytebuddy.implementation.MethodCall;
import net.bytebuddy.implementation.MethodDelegation;
import net.bytebuddy.implementation.bytecode.constant.DefaultValue;
import net.bytebuddy.matcher.ElementMatchers;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.util.Arrays;
@@ -56,19 +67,18 @@ public class ScriptBeanProxy {
}
try {
return new ByteBuddy().subclass(orignalClass)
.name(StrUtil.format("{}.ByteBuddy${}", ClassUtil.getPackage(orignalClass),
SerialsUtil.generateShortUUID()))
Class<?> c = new ByteBuddy().subclass(orignalClass).name(StrUtil.format("{}.ByteBuddy${}", ClassUtil.getPackage(orignalClass),SerialsUtil.generateShortUUID()))
.method(ElementMatchers.any())
.intercept(InvocationHandlerAdapter.of(new AopInvocationHandler(bean, methodNameList)))
.annotateType(orignalClass.getAnnotations())
.make()
.load(ScriptBeanProxy.class.getClassLoader())
.getLoaded()
.newInstance();
.getLoaded();
return ReflectUtil.newInstanceIfPossible(c);
}
catch (Exception e) {
throw new LiteFlowException(e);
throw new ProxyException(e);
}
}

View File

@@ -1,5 +1,7 @@
package com.yomahub.liteflow.spi;
import java.util.Map;
/**
* 环境容器SPI接口
*
@@ -8,18 +10,27 @@ package com.yomahub.liteflow.spi;
*/
public interface ContextAware extends SpiPriority {
<T> T getBean(String name);
<T> T getBean(String name);
<T> T getBean(Class<T> clazz);
<T> T getBean(Class<T> clazz);
<T> T registerBean(String beanName, Class<T> clazz);
<T> T registerBean(String beanName, Class<T> clazz);
<T> T registerBean(Class<T> clazz);
<T> T registerBean(Class<T> clazz);
<T> T registerBean(String beanName, Object bean);
<T> T registerBean(String beanName, Object bean);
<T> T registerOrGet(String beanName, Class<T> clazz);
<T> T registerOrGet(String beanName, Class<T> clazz);
boolean hasBean(String beanName);
/**
* 获取指定类型对应的所有Bean包括子类
*
* @param <T> Bean类型
* @param type 类、接口null表示获取所有bean
* @return 类型对应的beankey是bean注册的namevalue是Bean
*/
<T> Map<String, T> getBeansOfType(Class<T> type);
boolean hasBean(String beanName);
}

View File

@@ -10,6 +10,6 @@ import com.yomahub.liteflow.core.NodeComponent;
*/
public interface LiteflowComponentSupport extends SpiPriority {
String getCmpName(NodeComponent nodeComponent);
String getCmpName(Object nodeComponent);
}

View File

@@ -3,6 +3,8 @@ package com.yomahub.liteflow.spi.local;
import cn.hutool.core.util.ReflectUtil;
import com.yomahub.liteflow.spi.ContextAware;
import java.util.Map;
/**
* 非Spring环境容器实现 其实非Spring没有环境容器所以这是个空实现
*
@@ -11,44 +13,49 @@ import com.yomahub.liteflow.spi.ContextAware;
*/
public class LocalContextAware implements ContextAware {
@Override
public <T> T getBean(String name) {
return null;
}
@Override
public <T> T getBean(String name) {
return null;
}
@Override
public <T> T getBean(Class<T> clazz) {
return null;
}
@Override
public <T> T getBean(Class<T> clazz) {
return null;
}
@Override
public <T> T registerBean(String beanName, Class<T> clazz) {
return ReflectUtil.newInstance(clazz);
}
@Override
public <T> T registerBean(String beanName, Class<T> clazz) {
return ReflectUtil.newInstance(clazz);
}
@Override
public <T> T registerBean(Class<T> clazz) {
return registerBean(null, clazz);
}
@Override
public <T> T registerBean(Class<T> clazz) {
return registerBean(null, clazz);
}
@Override
public <T> T registerBean(String beanName, Object bean) {
return (T) bean;
}
@Override
public <T> T registerBean(String beanName, Object bean) {
return (T) bean;
}
@Override
public <T> T registerOrGet(String beanName, Class<T> clazz) {
return registerBean(beanName, clazz);
}
@Override
public <T> T registerOrGet(String beanName, Class<T> clazz) {
return registerBean(beanName, clazz);
}
@Override
public boolean hasBean(String beanName) {
return false;
}
@Override
public <T> Map<String, T> getBeansOfType(Class<T> type) {
return null;
}
@Override
public int priority() {
return 2;
}
@Override
public boolean hasBean(String beanName) {
return false;
}
@Override
public int priority() {
return 2;
}
}

View File

@@ -12,7 +12,7 @@ import com.yomahub.liteflow.spi.LiteflowComponentSupport;
public class LocalLiteflowComponentSupport implements LiteflowComponentSupport {
@Override
public String getCmpName(NodeComponent nodeComponent) {
public String getCmpName(Object nodeComponent) {
return null;
}