enhancement #IBJO4X 建立统一元数据操作类,所有元数据的操作的入口

This commit is contained in:
everywhere.z
2025-01-24 16:54:19 +08:00
parent a3658192e6
commit 9853e3e460
14 changed files with 306 additions and 17 deletions

View File

@@ -273,9 +273,7 @@ public class FlowBus {
throw new ScriptLoadException(errorMsg); throw new ScriptLoadException(errorMsg);
} }
} }
String activeNodeId = StrUtil.isEmpty(cmpInstance.getNodeId()) ? nodeId : cmpInstance.getNodeId(); String activeNodeId = StrUtil.isEmpty(cmpInstance.getNodeId()) ? nodeId : cmpInstance.getNodeId();
node.setCompiled(true);
put2NodeMap(activeNodeId, node); put2NodeMap(activeNodeId, node);
addFallbackNode(node); addFallbackNode(node);
} }

View File

@@ -185,6 +185,12 @@ public class Node implements Executable, Cloneable, Rollbackable{
.buildNodeExecutor(instance.getNodeExecutorClass()); .buildNodeExecutor(instance.getNodeExecutorClass());
// 调用节点执行器进行执行 // 调用节点执行器进行执行
nodeExecutor.execute(instance); nodeExecutor.execute(instance);
// 如果是脚本节点并且是后置编译的那么在成功执行好脚本节点后把编译flag置为true
// 这个只能在成功执行好之后设置如果在编译好之后设置那么设置的只有FlowBus中的nodeMap中的
if (this.type.isScript() && !this.isCompiled){
this.setCompiled(true);
}
} else { } else {
LOG.info("[X]skip component[{}] execution", instance.getDisplayName()); LOG.info("[X]skip component[{}] execution", instance.getDisplayName());
} }

View File

@@ -5,14 +5,11 @@ import cn.hutool.crypto.digest.MD5;
import com.yomahub.liteflow.flow.FlowBus; import com.yomahub.liteflow.flow.FlowBus;
import com.yomahub.liteflow.flow.element.Chain; import com.yomahub.liteflow.flow.element.Chain;
import com.yomahub.liteflow.flow.element.Condition; 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.element.Node;
import com.yomahub.liteflow.flow.entity.InstanceInfoDto; import com.yomahub.liteflow.flow.entity.InstanceInfoDto;
import com.yomahub.liteflow.util.JsonUtil;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.StringUtils;
import java.util.*; import java.util.*;
import static com.yomahub.liteflow.util.JsonUtil.*;
import static com.yomahub.liteflow.util.SerialsUtil.generateShortUUID; import static com.yomahub.liteflow.util.SerialsUtil.generateShortUUID;
/** /**
@@ -73,7 +70,7 @@ public abstract class BaseNodeInstanceIdManageSpi implements NodeInstanceIdManag
List<String> instanceIds = new ArrayList<>(); List<String> instanceIds = new ArrayList<>();
for (int i = 1; i < instanceIdFile.size(); i++) { 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) { for (InstanceInfoDto dto : instanceInfos) {
if (Objects.equals(dto.getNodeId(), nodeId)) { if (Objects.equals(dto.getNodeId(), nodeId)) {
@@ -133,24 +130,23 @@ public abstract class BaseNodeInstanceIdManageSpi implements NodeInstanceIdManag
* 根据实例id获取 节点实例定位 * 根据实例id获取 节点实例定位
*/ */
@Override @Override
public String getNodeLocationById(String chainId, String instanceId) { public int getNodeLocationById(String chainId, String instanceId) {
if (StringUtils.isBlank(chainId) || StringUtils.isBlank(instanceId)) { if (StringUtils.isBlank(chainId) || StringUtils.isBlank(instanceId)) {
return ""; return -1;
} }
// 第一行为elMd5 第二行为实例id json格式信息 // 第一行为elMd5 第二行为实例id json格式信息
List<String> instanceIdFile = readInstanceIdFile(chainId); List<String> instanceIdFile = readInstanceIdFile(chainId);
for (int i = 1; i < instanceIdFile.size(); i++) { 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) { for (InstanceInfoDto dto : instanceInfos) {
if (Objects.equals(dto.getInstanceId(), instanceId)) { if (Objects.equals(dto.getInstanceId(), instanceId)) {
return dto.getNodeId() + "(" + dto.getIndex() + ")"; return dto.getIndex();
} }
} }
} }
return -1;
return "";
} }
/** /**
@@ -171,7 +167,7 @@ public abstract class BaseNodeInstanceIdManageSpi implements NodeInstanceIdManag
// 文件存在,则直接读取 // 文件存在,则直接读取
List<InstanceInfoDto> instanceInfos = new ArrayList<>(); List<InstanceInfoDto> instanceInfos = new ArrayList<>();
for (int i = 1; i < instanceIdFile.size(); i++) { 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; List<InstanceInfoDto> finalInstanceInfos = instanceInfos;

View File

@@ -22,7 +22,7 @@ public interface NodeInstanceIdManageSpi {
void writeInstanceIdFile(List<InstanceInfoDto> instanceIdList, String elMd5, String chainId); void writeInstanceIdFile(List<InstanceInfoDto> instanceIdList, String elMd5, String chainId);
// 根据实例id获取 节点实例定位 // 根据实例id获取 节点实例定位
String getNodeLocationById(String chainId, String instanceId); int getNodeLocationById(String chainId, String instanceId);
// 根据chainId instanceId返回Node节点信息 // 根据chainId instanceId返回Node节点信息
Node getNodeByIdAndInstanceId(String chainId, String instanceId); Node getNodeByIdAndInstanceId(String chainId, String instanceId);

View File

@@ -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);
}
/**
* 通过chainIdnodeIdindex去获取具体的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);
}
/**
* 通过chainIdnodeInstanceId去获取这个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);
}
/**
* 通过chainIdnodeId去获取这个节点的所有的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);
}
}

View File

@@ -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"));
}
}

View File

@@ -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!");
}
}

View File

@@ -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!");
}
}

View File

@@ -0,0 +1,2 @@
liteflow.rule-source=refresh/flow.xml
liteflow.parse-mode=PARSE_ONE_ON_FIRST_EXEC

View File

@@ -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>

View File

@@ -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");
}
}

View File

@@ -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");
}
}

View File

@@ -86,7 +86,7 @@ public class InstanceIdELSpringTest extends BaseTest {
NodeInstanceIdManageSpi nodeInstanceIdManageSpi = NodeInstanceIdManageSpiHolder.getInstance().getNodeInstanceIdManageSpi(); NodeInstanceIdManageSpi nodeInstanceIdManageSpi = NodeInstanceIdManageSpiHolder.getInstance().getNodeInstanceIdManageSpi();
for (int i = 0; i < strings.size(); i++) { 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); System.out.println(executeStepStrWithInstanceId);

View File

@@ -70,7 +70,7 @@ public class SQLWithXmlELInstanceIdSpringbootTest extends BaseTest {
String[] nodes = new String[]{"c", "b", "a"}; String[] nodes = new String[]{"c", "b", "a"};
for (int i = 0; i < strings.size(); i++) { 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); HashSet<String> hashSet = Sets.newHashSet(strings);