mirror of
https://gitee.com/dromara/liteFlow.git
synced 2026-05-14 04:02:09 +08:00
enhancement #IBJO4X 建立统一元数据操作类,所有元数据的操作的入口
This commit is contained in:
@@ -273,9 +273,7 @@ public class FlowBus {
|
||||
throw new ScriptLoadException(errorMsg);
|
||||
}
|
||||
}
|
||||
|
||||
String activeNodeId = StrUtil.isEmpty(cmpInstance.getNodeId()) ? nodeId : cmpInstance.getNodeId();
|
||||
node.setCompiled(true);
|
||||
put2NodeMap(activeNodeId, node);
|
||||
addFallbackNode(node);
|
||||
}
|
||||
|
||||
@@ -185,6 +185,12 @@ public class Node implements Executable, Cloneable, Rollbackable{
|
||||
.buildNodeExecutor(instance.getNodeExecutorClass());
|
||||
// 调用节点执行器进行执行
|
||||
nodeExecutor.execute(instance);
|
||||
|
||||
// 如果是脚本节点,并且是后置编译的,那么在成功执行好脚本节点后把编译flag置为true
|
||||
// 这个只能在成功执行好之后设置,如果在编译好之后设置,那么设置的只有FlowBus中的nodeMap中的
|
||||
if (this.type.isScript() && !this.isCompiled){
|
||||
this.setCompiled(true);
|
||||
}
|
||||
} else {
|
||||
LOG.info("[X]skip component[{}] execution", instance.getDisplayName());
|
||||
}
|
||||
|
||||
@@ -5,14 +5,11 @@ import cn.hutool.crypto.digest.MD5;
|
||||
import com.yomahub.liteflow.flow.FlowBus;
|
||||
import com.yomahub.liteflow.flow.element.Chain;
|
||||
import com.yomahub.liteflow.flow.element.Condition;
|
||||
import com.yomahub.liteflow.flow.element.Executable;
|
||||
import com.yomahub.liteflow.flow.element.Node;
|
||||
import com.yomahub.liteflow.flow.entity.InstanceInfoDto;
|
||||
import com.yomahub.liteflow.util.JsonUtil;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import static com.yomahub.liteflow.util.JsonUtil.*;
|
||||
import static com.yomahub.liteflow.util.SerialsUtil.generateShortUUID;
|
||||
|
||||
/**
|
||||
@@ -73,7 +70,7 @@ public abstract class BaseNodeInstanceIdManageSpi implements NodeInstanceIdManag
|
||||
|
||||
List<String> instanceIds = new ArrayList<>();
|
||||
for (int i = 1; i < instanceIdFile.size(); i++) {
|
||||
List<InstanceInfoDto> instanceInfos = parseList(instanceIdFile.get(i), InstanceInfoDto.class);
|
||||
List<InstanceInfoDto> instanceInfos = JsonUtil.parseList(instanceIdFile.get(i), InstanceInfoDto.class);
|
||||
|
||||
for (InstanceInfoDto dto : instanceInfos) {
|
||||
if (Objects.equals(dto.getNodeId(), nodeId)) {
|
||||
@@ -133,24 +130,23 @@ public abstract class BaseNodeInstanceIdManageSpi implements NodeInstanceIdManag
|
||||
* 根据实例id获取 节点实例定位
|
||||
*/
|
||||
@Override
|
||||
public String getNodeLocationById(String chainId, String instanceId) {
|
||||
public int getNodeLocationById(String chainId, String instanceId) {
|
||||
if (StringUtils.isBlank(chainId) || StringUtils.isBlank(instanceId)) {
|
||||
return "";
|
||||
return -1;
|
||||
}
|
||||
// 第一行为elMd5 第二行为实例id json格式信息
|
||||
List<String> instanceIdFile = readInstanceIdFile(chainId);
|
||||
|
||||
for (int i = 1; i < instanceIdFile.size(); i++) {
|
||||
List<InstanceInfoDto> instanceInfos = parseList(instanceIdFile.get(i), InstanceInfoDto.class);
|
||||
List<InstanceInfoDto> instanceInfos = JsonUtil.parseList(instanceIdFile.get(i), InstanceInfoDto.class);
|
||||
|
||||
for (InstanceInfoDto dto : instanceInfos) {
|
||||
if (Objects.equals(dto.getInstanceId(), instanceId)) {
|
||||
return dto.getNodeId() + "(" + dto.getIndex() + ")";
|
||||
return dto.getIndex();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return "";
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -171,7 +167,7 @@ public abstract class BaseNodeInstanceIdManageSpi implements NodeInstanceIdManag
|
||||
// 文件存在,则直接读取
|
||||
List<InstanceInfoDto> instanceInfos = new ArrayList<>();
|
||||
for (int i = 1; i < instanceIdFile.size(); i++) {
|
||||
instanceInfos = parseList(instanceIdFile.get(i), InstanceInfoDto.class);
|
||||
instanceInfos = JsonUtil.parseList(instanceIdFile.get(i), InstanceInfoDto.class);
|
||||
}
|
||||
List<InstanceInfoDto> finalInstanceInfos = instanceInfos;
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@ public interface NodeInstanceIdManageSpi {
|
||||
void writeInstanceIdFile(List<InstanceInfoDto> instanceIdList, String elMd5, String chainId);
|
||||
|
||||
// 根据实例id获取 节点实例定位
|
||||
String getNodeLocationById(String chainId, String instanceId);
|
||||
int getNodeLocationById(String chainId, String instanceId);
|
||||
|
||||
// 根据chainId instanceId返回Node节点信息
|
||||
Node getNodeByIdAndInstanceId(String chainId, String instanceId);
|
||||
|
||||
@@ -0,0 +1,158 @@
|
||||
package com.yomahub.liteflow.meta;
|
||||
|
||||
import com.yomahub.liteflow.core.FlowExecutorHolder;
|
||||
import com.yomahub.liteflow.flow.FlowBus;
|
||||
import com.yomahub.liteflow.flow.element.Chain;
|
||||
import com.yomahub.liteflow.flow.element.Condition;
|
||||
import com.yomahub.liteflow.flow.element.Node;
|
||||
import com.yomahub.liteflow.flow.instanceId.NodeInstanceIdManageSpiHolder;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
/**
|
||||
* LiteFlow元数据统一操作类
|
||||
* @since 2.13.0
|
||||
* @author Bryan.Zhang
|
||||
*/
|
||||
public class LiteflowMetaOperator {
|
||||
|
||||
//--------------------------------------------Chain相关---------------------------------------------
|
||||
|
||||
/**
|
||||
* 通过chainId获得Chain对象
|
||||
* @param chainId Chain的Id
|
||||
* @return Chain Chain对象
|
||||
*/
|
||||
public static Chain getChain(String chainId){
|
||||
return FlowBus.getChain(chainId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 刷新所有的规则
|
||||
* 可以手动重新从ruleSource指定的数据源进行刷新
|
||||
* 此刷新操作将会刷新所有的规则
|
||||
*/
|
||||
public static void reloadAllChain(){
|
||||
FlowExecutorHolder.loadInstance().reloadRule();
|
||||
}
|
||||
|
||||
/**
|
||||
* 刷新某一个规则
|
||||
* @param chainId chain的Id
|
||||
* @param el 规则EL表达式
|
||||
*/
|
||||
public static void reloadOneChain(String chainId, String el){
|
||||
FlowBus.reloadChain(chainId, el);
|
||||
}
|
||||
|
||||
/**
|
||||
* 刷新某一个规则(带决策路由)
|
||||
* @param chainId chain的Id
|
||||
* @param el 规则EL表达式
|
||||
* @param routeEl 决策路由EL表达式
|
||||
*/
|
||||
public static void reloadOneChain(String chainId, String el, String routeEl){
|
||||
FlowBus.reloadChain(chainId, el, routeEl);
|
||||
}
|
||||
|
||||
/**
|
||||
* 从元数据中卸载掉一个Chain
|
||||
* @param chainId 需要卸载的chainId
|
||||
*/
|
||||
public static void removeChain(String chainId){
|
||||
FlowBus.removeChain(chainId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 从元数据中卸载掉多个Chain
|
||||
* @param chainIds 多个chainId
|
||||
*/
|
||||
public static void removeChain(String... chainIds){
|
||||
FlowBus.removeChain(chainIds);
|
||||
}
|
||||
|
||||
//--------------------------------------------Node相关---------------------------------------------
|
||||
|
||||
/**
|
||||
* 通过chainId获得这个chain中所有的Node
|
||||
* @param chainId chain的Id
|
||||
* @return 指定chain中的所有Node
|
||||
*/
|
||||
public static List<Node> getNodes(String chainId){
|
||||
return FlowBus.getNodesByChainId(chainId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过chainId和nodeId获得Node列表
|
||||
* @param chainId chain的Id
|
||||
* @param nodeId 节点Id
|
||||
* @return Node对象列表,一个节点在Chain里有可能出现多次
|
||||
*/
|
||||
public static List<Node> getNodes(String chainId, String nodeId){
|
||||
Chain chain = getChain(chainId);
|
||||
if (chain == null){
|
||||
return null;
|
||||
}
|
||||
return chain.getConditionList().stream().flatMap(
|
||||
(Function<Condition, Stream<Node>>) condition -> condition.getAllNodeInCondition().stream()
|
||||
).filter(
|
||||
node -> node.getId().equals(nodeId)
|
||||
).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过chainId和nodeInstanceId去获得具体的Node节点
|
||||
* 注意nodeInstance只有打开liteflow.enable-node-instance-id=true才会在Node对象中有
|
||||
* @param chainId chain的Id
|
||||
* @param nodeInstanceId Node节点的唯一Id
|
||||
* @return Node节点对象
|
||||
*/
|
||||
public static Node getNode(String chainId, String nodeInstanceId){
|
||||
return NodeInstanceIdManageSpiHolder.getInstance().getNodeInstanceIdManageSpi().getNodeByIdAndInstanceId(chainId, nodeInstanceId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过chainId,nodeId,index去获取具体的Node节点
|
||||
* @param chainId chain的Id
|
||||
* @param nodeId 节点的Id
|
||||
* @param index 节点的序号下标,从0开始
|
||||
* @return Node节点对象
|
||||
*/
|
||||
public static Node getNode(String chainId, String nodeId, int index){
|
||||
return NodeInstanceIdManageSpiHolder.getInstance().getNodeInstanceIdManageSpi().getNodeByIdAndIndex(chainId, nodeId, index);
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过chainId,nodeInstanceId去获取这个nodeInstanceId在Chain中的位置
|
||||
* 注意nodeInstance只有打开liteflow.enable-node-instance-id=true才会在Node对象中有
|
||||
* @param chainId chain的Id
|
||||
* @param nodeInstanceId Node的实例id
|
||||
* @return nodeInstanceId在这个chain中的位置,从0开始
|
||||
*/
|
||||
public static int getNodeIndex(String chainId, String nodeInstanceId){
|
||||
return NodeInstanceIdManageSpiHolder.getInstance().getNodeInstanceIdManageSpi().getNodeLocationById(chainId, nodeInstanceId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过chainId,nodeId去获取这个节点的所有的instanceId
|
||||
* 注意nodeInstance只有打开liteflow.enable-node-instance-id=true才会在Node对象中有
|
||||
* @param chainId chain的Id
|
||||
* @param nodeId Node的实例id
|
||||
* @return 节点的instanceId列表
|
||||
*/
|
||||
public static List<String> getNodeInstanceIds(String chainId, String nodeId){
|
||||
return NodeInstanceIdManageSpiHolder.getInstance().getNodeInstanceIdManageSpi().getNodeInstanceIds(chainId, nodeId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 刷新某一个脚本
|
||||
* @param nodeId 节点Id
|
||||
* @param script 刷新的脚本内容
|
||||
*/
|
||||
public static void reloadScript(String nodeId, String script){
|
||||
FlowBus.reloadScript(nodeId, script);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
package com.yomahub.liteflow.test.script.javaxpro.refresh;
|
||||
|
||||
import cn.hutool.core.io.FileUtil;
|
||||
import com.yomahub.liteflow.builder.LiteFlowNodeBuilder;
|
||||
import com.yomahub.liteflow.core.FlowExecutor;
|
||||
import com.yomahub.liteflow.enums.NodeTypeEnum;
|
||||
import com.yomahub.liteflow.enums.ScriptTypeEnum;
|
||||
import com.yomahub.liteflow.flow.FlowBus;
|
||||
import com.yomahub.liteflow.flow.LiteflowResponse;
|
||||
import com.yomahub.liteflow.slot.DefaultContext;
|
||||
import com.yomahub.liteflow.test.BaseTest;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.context.annotation.ComponentScan;
|
||||
import org.springframework.test.context.TestPropertySource;
|
||||
import org.springframework.test.context.junit.jupiter.SpringExtension;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
@ExtendWith(SpringExtension.class)
|
||||
@TestPropertySource(value = "classpath:/refresh/application.properties")
|
||||
@SpringBootTest(classes = ScriptJavaxProRefreshELTest.class)
|
||||
@EnableAutoConfiguration
|
||||
@ComponentScan({ "com.yomahub.liteflow.test.script.javaxpro.refresh.cmp" })
|
||||
public class ScriptJavaxProRefreshELTest extends BaseTest {
|
||||
|
||||
@Resource
|
||||
private FlowExecutor flowExecutor;
|
||||
|
||||
@Test
|
||||
public void testRefresh1() {
|
||||
String scriptContent = FileUtil.readUtf8String("refresh/s1.java");
|
||||
LiteFlowNodeBuilder.createScriptNode().setId("s1")
|
||||
.setScript(scriptContent)
|
||||
.setLanguage(ScriptTypeEnum.JAVA.getDisplayName())
|
||||
.build();
|
||||
LiteflowResponse response = flowExecutor.execute2Resp("chain1", null, DefaultContext.class);
|
||||
DefaultContext context = response.getFirstContextBean();
|
||||
Assertions.assertTrue(response.isSuccess());
|
||||
Assertions.assertEquals("1", context.getData("testFlag"));
|
||||
|
||||
//改写脚本
|
||||
scriptContent = FileUtil.readUtf8String("refresh/s1_update.java");
|
||||
FlowBus.reloadScript("s1", scriptContent);
|
||||
response = flowExecutor.execute2Resp("chain1", null, DefaultContext.class);
|
||||
context = response.getFirstContextBean();
|
||||
Assertions.assertTrue(response.isSuccess());
|
||||
Assertions.assertEquals("2", context.getData("testFlag"));
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
/**
|
||||
* <p>Title: liteflow</p>
|
||||
* <p>Description: 轻量级的组件式流程框架</p>
|
||||
* @author Bryan.Zhang
|
||||
* @email weenyc31@163.com
|
||||
* @Date 2020/4/1
|
||||
*/
|
||||
package com.yomahub.liteflow.test.script.javaxpro.refresh.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,21 @@
|
||||
/**
|
||||
* <p>Title: liteflow</p>
|
||||
* <p>Description: 轻量级的组件式流程框架</p>
|
||||
* @author Bryan.Zhang
|
||||
* @email weenyc31@163.com
|
||||
* @Date 2020/4/1
|
||||
*/
|
||||
package com.yomahub.liteflow.test.script.javaxpro.refresh.cmp;
|
||||
|
||||
import com.yomahub.liteflow.annotation.LiteflowComponent;
|
||||
import com.yomahub.liteflow.core.NodeComponent;
|
||||
|
||||
@LiteflowComponent("b")
|
||||
public class BCmp extends NodeComponent {
|
||||
|
||||
@Override
|
||||
public void process() {
|
||||
System.out.println("BCmp executed!");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
liteflow.rule-source=refresh/flow.xml
|
||||
liteflow.parse-mode=PARSE_ONE_ON_FIRST_EXEC
|
||||
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE flow PUBLIC "liteflow" "liteflow.dtd">
|
||||
<flow>
|
||||
<chain name="chain1">
|
||||
THEN(a,s1,b);
|
||||
</chain>
|
||||
|
||||
</flow>
|
||||
@@ -0,0 +1,12 @@
|
||||
import com.yomahub.liteflow.core.NodeComponent;
|
||||
import com.yomahub.liteflow.slot.DefaultContext;
|
||||
|
||||
public class Demo extends NodeComponent {
|
||||
|
||||
@Override
|
||||
public void process() {
|
||||
DefaultContext context = this.getFirstContextBean();
|
||||
context.setData("testFlag","1");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
import com.yomahub.liteflow.core.NodeComponent;
|
||||
import com.yomahub.liteflow.slot.DefaultContext;
|
||||
|
||||
public class Demo extends NodeComponent {
|
||||
|
||||
@Override
|
||||
public void process() {
|
||||
DefaultContext context = this.getFirstContextBean();
|
||||
context.setData("testFlag","2");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -86,7 +86,7 @@ public class InstanceIdELSpringTest extends BaseTest {
|
||||
NodeInstanceIdManageSpi nodeInstanceIdManageSpi = NodeInstanceIdManageSpiHolder.getInstance().getNodeInstanceIdManageSpi();
|
||||
|
||||
for (int i = 0; i < strings.size(); i++) {
|
||||
Assertions.assertEquals(nodeInstanceIdManageSpi.getNodeLocationById("chain2", strings.get(i)), "a(" + i + ")");
|
||||
Assertions.assertEquals(nodeInstanceIdManageSpi.getNodeLocationById("chain2", strings.get(i)), i);
|
||||
}
|
||||
|
||||
System.out.println(executeStepStrWithInstanceId);
|
||||
|
||||
@@ -70,7 +70,7 @@ public class SQLWithXmlELInstanceIdSpringbootTest extends BaseTest {
|
||||
|
||||
String[] nodes = new String[]{"c", "b", "a"};
|
||||
for (int i = 0; i < strings.size(); i++) {
|
||||
Assertions.assertEquals(nodeInstanceIdManageSpi.getNodeLocationById("r_chain4", strings.get(i)), nodes[i] + "(0)");
|
||||
Assertions.assertEquals(nodeInstanceIdManageSpi.getNodeLocationById("r_chain4", strings.get(i)), 0);
|
||||
}
|
||||
|
||||
HashSet<String> hashSet = Sets.newHashSet(strings);
|
||||
|
||||
Reference in New Issue
Block a user