Files
flow-center-service/src/main/java/com/yunhai/flowcenter/engine/FlowAdvanceService.java
T
chenxing d2395c20ce feat(flow): 回调信封升级——事件携带操作人身份(operatorUserId/operatorName)
在飞工作合入:FlowEvent 增操作人字段(可空),引擎/推进监听/回调派发全程透传,
对齐 SDK FlowCallbackEvent 的 taskId/operator 字段(规范 §6.4)。
2026-09-22 16:54:02 +08:00

82 lines
3.8 KiB
Java
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package com.yunhai.flowcenter.engine;
import com.yunhai.flowcenter.entity.FlwDef;
import com.yunhai.flowcenter.entity.FlwInstance;
import com.yunhai.flowcenter.entity.FlwTask;
import com.yunhai.flowcenter.enums.FlwEnums;
import com.yunhai.flowcenter.repository.FlwDefRepository;
import com.yunhai.flowcenter.repository.FlwInstanceRepository;
import com.yunhai.flowcenter.repository.FlwTaskRepository;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
/**
* 节点放行推进(AFTER_COMMIT 监听器经代理调用本 bean,REQUIRES_NEW 生效——
* 事务已提交后的同步监听阶段没有活动事务,@Modifying 批量语句必须有新事务承载):
* 该节点待办清零且办件在途才推进;并发冲突由 flw_instance.version 乐观锁暴露,监听器层负责重试。
*/
@Slf4j
@Service
@RequiredArgsConstructor
public class FlowAdvanceService {
private final FlwInstanceRepository instanceRepository;
private final FlwDefRepository defRepository;
private final FlwTaskRepository taskRepository;
private final FlowEngine flowEngine;
/**
* @param nodeId 待放行节点
* @param edgeName 多出口节点所选出口(办理事件携带);可空——兜底从该节点
* 最近一条已同意任务的 edge_name 列重放(推进在 AFTER_COMMIT 新事务重查,
* 事件传参只是快路径,落库的值才是权威)
* @param operator 本节点办理人(TASK_HANDLED 事件 data 穿透;推进产生的
* TASK_CREATED/COMPLETED 操作人信封字段来源),可空
* @return 是否实际推进了
*/
@Transactional(propagation = Propagation.REQUIRES_NEW)
public boolean tryAdvance(Long instanceId, String nodeId, String edgeName, FlowOperator operator) {
FlwInstance instance = instanceRepository.findById(instanceId).orElse(null);
if (instance == null
|| instance.getStatus() != FlwEnums.InstanceStatus.APPROVING.getCode()) {
return false;
}
// 已推进过的节点不再放行(currentNodes 由引擎在放行时移除,乐观锁保证互斥)
String current = instance.getCurrentNodes();
boolean active = current != null && java.util.Arrays.stream(current.split(","))
.anyMatch(nodeId::equals);
if (!active) {
return false;
}
long pending = taskRepository.findByInstanceIdAndStatus(instanceId,
FlwEnums.TaskStatus.PENDING.getCode()).stream()
.filter(t -> nodeId.equals(t.getNodeId()))
.count();
if (pending > 0) {
return false;
}
FlwDef def = defRepository.findById(instance.getDefId()).orElse(null);
if (def == null) {
log.error("[flow-center] 办件定义缺失,推进中止:instance={} defId={}",
instanceId, instance.getDefId());
return false;
}
String chosen = edgeName;
if (chosen == null) {
chosen = taskRepository.findByInstanceIdAndStatus(instanceId,
FlwEnums.TaskStatus.APPROVED.getCode()).stream()
.filter(t -> nodeId.equals(t.getNodeId()) && t.getEdgeName() != null)
.max(java.util.Comparator.comparing(
FlwTask::getHandleTime, java.util.Comparator.nullsFirst(java.util.Comparator.naturalOrder())))
.map(FlwTask::getEdgeName)
.orElse(null);
}
flowEngine.continueAdvance(instance, def, nodeId, chosen, operator);
instanceRepository.save(instance);
return true;
}
}