FlowEngineService 流程执行引擎核心服务 + 编译通过

This commit is contained in:
root
2026-03-17 23:56:07 +08:00
parent 8242e1348e
commit e1db57d541

View File

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