FlowEngineService 流程执行引擎核心服务 + 编译通过
This commit is contained in:
@@ -0,0 +1,246 @@
|
|||||||
|
package com.ruoyi.wcs.flow.engine;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
import com.ruoyi.wcs.flow.domain.*;
|
||||||
|
import com.ruoyi.wcs.flow.service.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* WCS 轻量流程执行引擎
|
||||||
|
* 按流程定义依次执行节点,记录实例和节点日志
|
||||||
|
*
|
||||||
|
* @author wcs
|
||||||
|
*/
|
||||||
|
@Service
|
||||||
|
public class FlowEngineService
|
||||||
|
{
|
||||||
|
private static final Logger log = LoggerFactory.getLogger(FlowEngineService.class);
|
||||||
|
|
||||||
|
private Map<String, INodeHandler> handlerMap = new HashMap<>();
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private IWcsFlowDefService flowDefService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private IWcsFlowNodeService flowNodeService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private IWcsFlowLineService flowLineService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private IWcsFlowInstanceService flowInstanceService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private IWcsFlowNodeLogService flowNodeLogService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
public void setHandlers(List<INodeHandler> handlers)
|
||||||
|
{
|
||||||
|
for (INodeHandler handler : handlers)
|
||||||
|
{
|
||||||
|
handlerMap.put(handler.getNodeType(), handler);
|
||||||
|
}
|
||||||
|
log.info("[FlowEngine] 已注册 {} 个节点处理器: {}", handlerMap.size(), handlerMap.keySet());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 执行流程
|
||||||
|
*
|
||||||
|
* @param flowDefId 流程定义ID
|
||||||
|
* @return 流程实例ID
|
||||||
|
*/
|
||||||
|
@Transactional
|
||||||
|
public Long executeFlow(Long flowDefId)
|
||||||
|
{
|
||||||
|
// 1. 查询流程定义
|
||||||
|
WcsFlowDef flowDef = flowDefService.selectFlowDefById(flowDefId);
|
||||||
|
if (flowDef == null)
|
||||||
|
{
|
||||||
|
throw new RuntimeException("流程定义不存在: " + flowDefId);
|
||||||
|
}
|
||||||
|
if (!"1".equals(flowDef.getStatus()))
|
||||||
|
{
|
||||||
|
throw new RuntimeException("流程未发布,无法执行: " + flowDef.getFlowCode());
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. 创建流程实例
|
||||||
|
WcsFlowInstance instance = new WcsFlowInstance();
|
||||||
|
instance.setFlowDefId(flowDefId);
|
||||||
|
instance.setStatus("1"); // 执行中
|
||||||
|
instance.setStartTime(new Date());
|
||||||
|
flowInstanceService.insertFlowInstance(instance);
|
||||||
|
Long instanceId = instance.getId();
|
||||||
|
log.info("[FlowEngine] 流程实例创建: instanceId={}, flowCode={}", instanceId, flowDef.getFlowCode());
|
||||||
|
|
||||||
|
// 3. 加载节点和连线
|
||||||
|
List<WcsFlowNode> nodes = flowNodeService.selectFlowNodeListByFlowId(flowDefId);
|
||||||
|
List<WcsFlowLine> lines = flowLineService.selectFlowLineListByFlowId(flowDefId);
|
||||||
|
|
||||||
|
// 按nodeId建索引
|
||||||
|
Map<Long, WcsFlowNode> nodeMap = nodes.stream()
|
||||||
|
.collect(Collectors.toMap(WcsFlowNode::getNodeId, n -> n));
|
||||||
|
|
||||||
|
// 4. 找到开始节点
|
||||||
|
WcsFlowNode currentNode = findStartNode(nodes);
|
||||||
|
if (currentNode == null)
|
||||||
|
{
|
||||||
|
updateInstanceStatus(instance, "3", "未找到开始节点");
|
||||||
|
throw new RuntimeException("流程缺少开始节点: " + flowDef.getFlowCode());
|
||||||
|
}
|
||||||
|
|
||||||
|
// 5. 执行上下文
|
||||||
|
Map<String, Object> context = new HashMap<>();
|
||||||
|
context.put("flowDefId", flowDefId);
|
||||||
|
context.put("instanceId", instanceId);
|
||||||
|
|
||||||
|
// 6. 按连线顺序执行
|
||||||
|
int maxSteps = 100; // 防止死循环
|
||||||
|
int step = 0;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
while (currentNode != null && step < maxSteps)
|
||||||
|
{
|
||||||
|
step++;
|
||||||
|
log.info("[FlowEngine] 执行节点: step={}, nodeId={}, type={}, name={}",
|
||||||
|
step, currentNode.getNodeId(), currentNode.getNodeType(), currentNode.getNodeName());
|
||||||
|
|
||||||
|
// 记录节点日志-开始
|
||||||
|
WcsFlowNodeLog nodeLog = new WcsFlowNodeLog();
|
||||||
|
nodeLog.setInstanceId(instanceId);
|
||||||
|
nodeLog.setNodeId(String.valueOf(currentNode.getNodeId()));
|
||||||
|
nodeLog.setNodeType(currentNode.getNodeType());
|
||||||
|
nodeLog.setStatus("1"); // 执行中
|
||||||
|
nodeLog.setStartTime(new Date());
|
||||||
|
flowNodeLogService.insertFlowNodeLog(nodeLog);
|
||||||
|
|
||||||
|
// 获取handler
|
||||||
|
INodeHandler handler = getHandler(currentNode.getNodeType());
|
||||||
|
if (handler == null)
|
||||||
|
{
|
||||||
|
nodeLog.setStatus("3"); // 失败
|
||||||
|
nodeLog.setErrorMsg("未找到节点处理器: " + currentNode.getNodeType());
|
||||||
|
nodeLog.setEndTime(new Date());
|
||||||
|
flowNodeLogService.updateFlowNodeLog(nodeLog);
|
||||||
|
updateInstanceStatus(instance, "3", nodeLog.getErrorMsg());
|
||||||
|
return instanceId;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 执行节点
|
||||||
|
NodeResult result = handler.execute(currentNode.getConfigJson(), context);
|
||||||
|
|
||||||
|
// 更新节点日志
|
||||||
|
nodeLog.setEndTime(new Date());
|
||||||
|
if (result.isSuccess())
|
||||||
|
{
|
||||||
|
nodeLog.setStatus("2"); // 成功
|
||||||
|
nodeLog.setOutput(result.getOutput());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
nodeLog.setStatus("3"); // 失败
|
||||||
|
nodeLog.setErrorMsg(result.getErrorMsg());
|
||||||
|
flowNodeLogService.updateFlowNodeLog(nodeLog);
|
||||||
|
updateInstanceStatus(instance, "3", result.getErrorMsg());
|
||||||
|
return instanceId;
|
||||||
|
}
|
||||||
|
flowNodeLogService.updateFlowNodeLog(nodeLog);
|
||||||
|
|
||||||
|
// end节点,流程结束
|
||||||
|
if ("end".equals(currentNode.getNodeType()))
|
||||||
|
{
|
||||||
|
log.info("[FlowEngine] 流程执行完成: instanceId={}", instanceId);
|
||||||
|
updateInstanceStatus(instance, "2", null); // 已完成
|
||||||
|
return instanceId;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 找下一个节点
|
||||||
|
currentNode = findNextNode(currentNode, result, lines, nodeMap);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 超过最大步数
|
||||||
|
if (step >= maxSteps)
|
||||||
|
{
|
||||||
|
updateInstanceStatus(instance, "3", "超过最大执行步数: " + maxSteps);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
log.error("[FlowEngine] 流程执行异常: instanceId={}", instanceId, e);
|
||||||
|
updateInstanceStatus(instance, "3", e.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
return instanceId;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 找开始节点
|
||||||
|
*/
|
||||||
|
private WcsFlowNode findStartNode(List<WcsFlowNode> nodes)
|
||||||
|
{
|
||||||
|
return nodes.stream()
|
||||||
|
.filter(n -> "start".equals(n.getNodeType()))
|
||||||
|
.findFirst()
|
||||||
|
.orElse(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据连线找下一个节点
|
||||||
|
*/
|
||||||
|
private WcsFlowNode findNextNode(WcsFlowNode current, NodeResult result,
|
||||||
|
List<WcsFlowLine> lines, Map<Long, WcsFlowNode> nodeMap)
|
||||||
|
{
|
||||||
|
List<WcsFlowLine> outLines = lines.stream()
|
||||||
|
.filter(l -> current.getNodeId().equals(l.getSourceNodeId()))
|
||||||
|
.sorted(Comparator.comparingInt(l -> l.getSortOrder() != null ? l.getSortOrder() : 0))
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
|
if (outLines.isEmpty())
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// condition节点:按branchKey匹配conditionExpr
|
||||||
|
if ("condition".equals(current.getNodeType()) && result.getBranchKey() != null)
|
||||||
|
{
|
||||||
|
for (WcsFlowLine line : outLines)
|
||||||
|
{
|
||||||
|
if (result.getBranchKey().equals(line.getConditionExpr()))
|
||||||
|
{
|
||||||
|
return nodeMap.get(line.getTargetNodeId());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 没匹配到,走第一条(默认分支)
|
||||||
|
log.warn("[FlowEngine] 条件分支未匹配, branchKey={}, 走默认分支", result.getBranchKey());
|
||||||
|
}
|
||||||
|
|
||||||
|
// 非condition节点或默认:走第一条连线
|
||||||
|
return nodeMap.get(outLines.get(0).getTargetNodeId());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取节点处理器
|
||||||
|
*/
|
||||||
|
private INodeHandler getHandler(String nodeType)
|
||||||
|
{
|
||||||
|
return handlerMap.get(nodeType);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新流程实例状态
|
||||||
|
*/
|
||||||
|
private void updateInstanceStatus(WcsFlowInstance instance, String status, String remark)
|
||||||
|
{
|
||||||
|
instance.setStatus(status);
|
||||||
|
instance.setEndTime(new Date());
|
||||||
|
if (remark != null)
|
||||||
|
{
|
||||||
|
instance.setRemark(remark);
|
||||||
|
}
|
||||||
|
flowInstanceService.updateFlowInstance(instance);
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user