工作流修复
This commit is contained in:
parent
b4f2a9d400
commit
97e6b30e65
@ -2,6 +2,8 @@ package com.qqchen.deploy.backend.workflow.delegate;
|
|||||||
|
|
||||||
import com.fasterxml.jackson.core.type.TypeReference;
|
import com.fasterxml.jackson.core.type.TypeReference;
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
import com.qqchen.deploy.backend.workflow.dto.outputs.BaseNodeOutputs;
|
||||||
|
import com.qqchen.deploy.backend.workflow.enums.NodeExecutionStatusEnum;
|
||||||
import com.qqchen.deploy.backend.workflow.model.NodeContext;
|
import com.qqchen.deploy.backend.workflow.model.NodeContext;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.flowable.engine.delegate.DelegateExecution;
|
import org.flowable.engine.delegate.DelegateExecution;
|
||||||
@ -21,7 +23,7 @@ import static com.qqchen.deploy.backend.workflow.constants.WorkFlowConstants.WOR
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 任务委派者基类
|
* 任务委派者基类
|
||||||
|
* <p>
|
||||||
* 负责处理节点配置、输入映射和输出结果的统一处理
|
* 负责处理节点配置、输入映射和输出结果的统一处理
|
||||||
*
|
*
|
||||||
* @param <I> 输入映射类型 (InputMapping)
|
* @param <I> 输入映射类型 (InputMapping)
|
||||||
@ -54,6 +56,7 @@ public abstract class BaseNodeDelegate<I, O> implements JavaDelegate {
|
|||||||
public void execute(DelegateExecution execution) {
|
public void execute(DelegateExecution execution) {
|
||||||
|
|
||||||
String currentNodeId = null;
|
String currentNodeId = null;
|
||||||
|
NodeContext<I, O> nodeContext = new NodeContext<>();
|
||||||
try {
|
try {
|
||||||
// 1. 获取节点ID
|
// 1. 获取节点ID
|
||||||
currentNodeId = getFieldValue(nodeId, execution);
|
currentNodeId = getFieldValue(nodeId, execution);
|
||||||
@ -73,27 +76,29 @@ public abstract class BaseNodeDelegate<I, O> implements JavaDelegate {
|
|||||||
O outputsObj = executeInternal(execution, configsMap, inputMappingObj);
|
O outputsObj = executeInternal(execution, configsMap, inputMappingObj);
|
||||||
|
|
||||||
// ✅ 6. 使用 NodeContext 保存节点数据
|
// ✅ 6. 使用 NodeContext 保存节点数据
|
||||||
NodeContext<I, O> nodeContext = new NodeContext<>();
|
|
||||||
nodeContext.setConfigs(configsMap);
|
nodeContext.setConfigs(configsMap);
|
||||||
nodeContext.setInputMapping(inputMappingObj);
|
nodeContext.setInputMapping(inputMappingObj);
|
||||||
nodeContext.setOutputs(outputsObj);
|
nodeContext.setOutputs(outputsObj);
|
||||||
|
|
||||||
execution.setVariable(currentNodeId, nodeContext.toMap(objectMapper));
|
execution.setVariable(currentNodeId, nodeContext.toMap(objectMapper));
|
||||||
log.info("Stored NodeContext for: {}", currentNodeId);
|
log.info("Stored NodeContext for: {}", currentNodeId);
|
||||||
|
|
||||||
// 7. 设置节点执行状态为成功
|
// 7. 设置节点执行状态为成功
|
||||||
setExecutionStatus(execution, WORKFLOW_NODE_EXECUTION_STATE_SUCCESS);
|
setExecutionStatus(execution, WORKFLOW_NODE_EXECUTION_STATE_SUCCESS);
|
||||||
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
BaseNodeOutputs failureNodeOutputs = new BaseNodeOutputs();
|
||||||
|
failureNodeOutputs.setStatus(NodeExecutionStatusEnum.FAILURE);
|
||||||
|
nodeContext.setOutputs((O) failureNodeOutputs);
|
||||||
|
execution.setVariable(currentNodeId, nodeContext.toMap(objectMapper));
|
||||||
|
// 设置失败状态
|
||||||
setExecutionStatus(execution, WORKFLOW_NODE_EXECUTION_STATE_FAILURE);
|
setExecutionStatus(execution, WORKFLOW_NODE_EXECUTION_STATE_FAILURE);
|
||||||
|
log.error("Task execution failed", e);
|
||||||
log.error("Node execution failed: {}", currentNodeId, e);
|
|
||||||
throw new RuntimeException("Node execution failed: " + currentNodeId, e);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
||||||
* 执行具体的业务逻辑(子类实现)
|
* 执行具体的业务逻辑(子类实现)
|
||||||
*
|
*
|
||||||
* @param execution Flowable执行上下文
|
* @param execution Flowable执行上下文
|
||||||
@ -283,4 +288,4 @@ public abstract class BaseNodeDelegate<I, O> implements JavaDelegate {
|
|||||||
log.debug("Cleared previous node status for node: {}", execution.getCurrentActivityId());
|
log.debug("Cleared previous node status for node: {}", execution.getCurrentActivityId());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -4,6 +4,7 @@ import com.qqchen.deploy.backend.deploy.entity.ExternalSystem;
|
|||||||
import com.qqchen.deploy.backend.deploy.entity.JenkinsJob;
|
import com.qqchen.deploy.backend.deploy.entity.JenkinsJob;
|
||||||
import com.qqchen.deploy.backend.deploy.enums.JenkinsBuildStatus;
|
import com.qqchen.deploy.backend.deploy.enums.JenkinsBuildStatus;
|
||||||
import com.qqchen.deploy.backend.deploy.integration.IJenkinsServiceIntegration;
|
import com.qqchen.deploy.backend.deploy.integration.IJenkinsServiceIntegration;
|
||||||
|
import com.qqchen.deploy.backend.deploy.integration.response.JenkinsBuildResponse;
|
||||||
import com.qqchen.deploy.backend.deploy.integration.response.JenkinsQueueBuildInfoResponse;
|
import com.qqchen.deploy.backend.deploy.integration.response.JenkinsQueueBuildInfoResponse;
|
||||||
import com.qqchen.deploy.backend.deploy.repository.IExternalSystemRepository;
|
import com.qqchen.deploy.backend.deploy.repository.IExternalSystemRepository;
|
||||||
import com.qqchen.deploy.backend.deploy.repository.IJenkinsJobRepository;
|
import com.qqchen.deploy.backend.deploy.repository.IJenkinsJobRepository;
|
||||||
@ -76,8 +77,7 @@ public class JenkinsBuildDelegate extends BaseNodeDelegate<JenkinsBuildInputMapp
|
|||||||
JenkinsBuildStatus buildStatus = pollBuildStatus(externalSystem, jobName, buildInfo.getBuildNumber());
|
JenkinsBuildStatus buildStatus = pollBuildStatus(externalSystem, jobName, buildInfo.getBuildNumber());
|
||||||
|
|
||||||
// 5. 获取构建详细信息(包括 duration, changeSets, artifacts)
|
// 5. 获取构建详细信息(包括 duration, changeSets, artifacts)
|
||||||
com.qqchen.deploy.backend.deploy.integration.response.JenkinsBuildResponse buildDetails =
|
JenkinsBuildResponse buildDetails = jenkinsServiceIntegration.getBuildDetails(externalSystem, jobName, buildInfo.getBuildNumber());
|
||||||
jenkinsServiceIntegration.getBuildDetails(externalSystem, jobName, buildInfo.getBuildNumber());
|
|
||||||
|
|
||||||
// 打印调试信息
|
// 打印调试信息
|
||||||
log.info("Build details - changeSets: {}, artifacts: {}",
|
log.info("Build details - changeSets: {}, artifacts: {}",
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
package com.qqchen.deploy.backend.workflow.dto.outputs;
|
package com.qqchen.deploy.backend.workflow.dto.outputs;
|
||||||
|
|
||||||
import com.qqchen.deploy.backend.workflow.enums.ApprovalResultEnum;
|
import com.qqchen.deploy.backend.workflow.enums.ApprovalResultEnum;
|
||||||
|
import lombok.Builder;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.EqualsAndHashCode;
|
import lombok.EqualsAndHashCode;
|
||||||
|
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
package com.qqchen.deploy.backend.workflow.dto.outputs;
|
package com.qqchen.deploy.backend.workflow.dto.outputs;
|
||||||
|
|
||||||
import com.qqchen.deploy.backend.workflow.enums.NodeExecutionStatusEnum;
|
import com.qqchen.deploy.backend.workflow.enums.NodeExecutionStatusEnum;
|
||||||
|
import lombok.Builder;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
package com.qqchen.deploy.backend.workflow.dto.outputs;
|
package com.qqchen.deploy.backend.workflow.dto.outputs;
|
||||||
|
|
||||||
|
import lombok.Builder;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.EqualsAndHashCode;
|
import lombok.EqualsAndHashCode;
|
||||||
|
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
package com.qqchen.deploy.backend.workflow.dto.outputs;
|
package com.qqchen.deploy.backend.workflow.dto.outputs;
|
||||||
|
|
||||||
|
import lombok.Builder;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.EqualsAndHashCode;
|
import lombok.EqualsAndHashCode;
|
||||||
|
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
package com.qqchen.deploy.backend.workflow.dto.outputs;
|
package com.qqchen.deploy.backend.workflow.dto.outputs;
|
||||||
|
|
||||||
|
import lombok.Builder;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.EqualsAndHashCode;
|
import lombok.EqualsAndHashCode;
|
||||||
|
|
||||||
@ -12,17 +13,17 @@ import lombok.EqualsAndHashCode;
|
|||||||
@Data
|
@Data
|
||||||
@EqualsAndHashCode(callSuper = true)
|
@EqualsAndHashCode(callSuper = true)
|
||||||
public class ShellOutputs extends BaseNodeOutputs {
|
public class ShellOutputs extends BaseNodeOutputs {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 退出码
|
* 退出码
|
||||||
*/
|
*/
|
||||||
private Integer exitCode;
|
private Integer exitCode;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 标准输出
|
* 标准输出
|
||||||
*/
|
*/
|
||||||
private String stdout;
|
private String stdout;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 错误输出
|
* 错误输出
|
||||||
*/
|
*/
|
||||||
|
|||||||
@ -35,47 +35,47 @@ public class ApprovalTaskServiceImpl implements IApprovalTaskService {
|
|||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
private TaskService taskService;
|
private TaskService taskService;
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
private ObjectMapper objectMapper;
|
private ObjectMapper objectMapper;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<ApprovalTaskDTO> getMyTasks(String username) {
|
public List<ApprovalTaskDTO> getMyTasks(String username) {
|
||||||
log.info("查询用户 {} 的待办任务", username);
|
log.info("查询用户 {} 的待办任务", username);
|
||||||
|
|
||||||
List<Task> tasks = taskService.createTaskQuery()
|
List<Task> tasks = taskService.createTaskQuery()
|
||||||
.taskAssignee(username)
|
.taskAssignee(username)
|
||||||
.orderByTaskCreateTime()
|
.orderByTaskCreateTime()
|
||||||
.desc()
|
.desc()
|
||||||
.list();
|
.list();
|
||||||
|
|
||||||
return tasks.stream()
|
return tasks.stream()
|
||||||
.map(this::convertToDTO)
|
.map(this::convertToDTO)
|
||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<ApprovalTaskDTO> getTasksByProcessInstance(String processInstanceId) {
|
public List<ApprovalTaskDTO> getTasksByProcessInstance(String processInstanceId) {
|
||||||
log.info("查询流程实例 {} 的所有任务", processInstanceId);
|
log.info("查询流程实例 {} 的所有任务", processInstanceId);
|
||||||
|
|
||||||
List<Task> tasks = taskService.createTaskQuery()
|
List<Task> tasks = taskService.createTaskQuery()
|
||||||
.processInstanceId(processInstanceId)
|
.processInstanceId(processInstanceId)
|
||||||
.orderByTaskCreateTime()
|
.orderByTaskCreateTime()
|
||||||
.desc()
|
.desc()
|
||||||
.list();
|
.list();
|
||||||
|
|
||||||
return tasks.stream()
|
return tasks.stream()
|
||||||
.map(this::convertToDTO)
|
.map(this::convertToDTO)
|
||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ApprovalTaskDTO getTaskById(String taskId) {
|
public ApprovalTaskDTO getTaskById(String taskId) {
|
||||||
log.info("查询任务详情: {}", taskId);
|
log.info("查询任务详情: {}", taskId);
|
||||||
|
|
||||||
Task task = taskService.createTaskQuery()
|
Task task = taskService.createTaskQuery()
|
||||||
.taskId(taskId)
|
.taskId(taskId)
|
||||||
.singleResult();
|
.singleResult();
|
||||||
|
|
||||||
if (task == null) {
|
if (task == null) {
|
||||||
throw new BusinessException(ResponseCode.DATA_NOT_FOUND);
|
throw new BusinessException(ResponseCode.DATA_NOT_FOUND);
|
||||||
@ -91,8 +91,8 @@ public class ApprovalTaskServiceImpl implements IApprovalTaskService {
|
|||||||
|
|
||||||
// 检查任务是否存在
|
// 检查任务是否存在
|
||||||
Task task = taskService.createTaskQuery()
|
Task task = taskService.createTaskQuery()
|
||||||
.taskId(request.getTaskId())
|
.taskId(request.getTaskId())
|
||||||
.singleResult();
|
.singleResult();
|
||||||
|
|
||||||
if (task == null) {
|
if (task == null) {
|
||||||
throw new BusinessException(ResponseCode.DATA_NOT_FOUND);
|
throw new BusinessException(ResponseCode.DATA_NOT_FOUND);
|
||||||
@ -100,32 +100,32 @@ public class ApprovalTaskServiceImpl implements IApprovalTaskService {
|
|||||||
|
|
||||||
// ✅ 获取节点ID并更新 NodeContext
|
// ✅ 获取节点ID并更新 NodeContext
|
||||||
String nodeId = task.getTaskDefinitionKey();
|
String nodeId = task.getTaskDefinitionKey();
|
||||||
|
|
||||||
// 读取现有 NodeContext
|
// 读取现有 NodeContext
|
||||||
Object nodeDataObj = taskService.getVariable(task.getId(), nodeId);
|
Object nodeDataObj = taskService.getVariable(task.getId(), nodeId);
|
||||||
NodeContext<ApprovalInputMapping, ApprovalOutputs> nodeContext;
|
NodeContext<ApprovalInputMapping, ApprovalOutputs> nodeContext;
|
||||||
if (nodeDataObj instanceof Map) {
|
if (nodeDataObj instanceof Map) {
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
Map<String, Object> nodeDataMap = (Map<String, Object>) nodeDataObj;
|
Map<String, Object> nodeDataMap = (Map<String, Object>) nodeDataObj;
|
||||||
nodeContext = NodeContext.fromMap(nodeDataMap,
|
nodeContext = NodeContext.fromMap(nodeDataMap,
|
||||||
ApprovalInputMapping.class, ApprovalOutputs.class, objectMapper);
|
ApprovalInputMapping.class, ApprovalOutputs.class, objectMapper);
|
||||||
} else {
|
} else {
|
||||||
nodeContext = new NodeContext<>();
|
nodeContext = new NodeContext<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
// 创建临时审批数据(稍后由 ApprovalExecutionListener 完善)
|
// 创建临时审批数据(稍后由 ApprovalExecutionListener 完善)
|
||||||
ApprovalOutputs tempOutputs = new ApprovalOutputs();
|
ApprovalOutputs tempOutputs = new ApprovalOutputs();
|
||||||
tempOutputs.setApprovalResult(request.getResult());
|
tempOutputs.setApprovalResult(request.getResult());
|
||||||
tempOutputs.setApprover(task.getAssignee());
|
tempOutputs.setApprover(task.getAssignee());
|
||||||
tempOutputs.setApprovalTime(LocalDateTime.now());
|
tempOutputs.setApprovalTime(LocalDateTime.now());
|
||||||
tempOutputs.setApprovalComment(request.getComment());
|
tempOutputs.setApprovalComment(request.getComment());
|
||||||
|
|
||||||
// 暂时设置为 outputs(ApprovalExecutionListener 会完善)
|
// 暂时设置为 outputs(ApprovalExecutionListener 会完善)
|
||||||
nodeContext.setOutputs(tempOutputs);
|
nodeContext.setOutputs(tempOutputs);
|
||||||
|
|
||||||
// 保存回流程变量
|
// 保存回流程变量
|
||||||
taskService.setVariable(task.getId(), nodeId, nodeContext.toMap(objectMapper));
|
taskService.setVariable(task.getId(), nodeId, nodeContext.toMap(objectMapper));
|
||||||
|
|
||||||
// 5. 添加任务评论(供历史查询)
|
// 5. 添加任务评论(供历史查询)
|
||||||
if (request.getComment() != null) {
|
if (request.getComment() != null) {
|
||||||
taskService.addComment(request.getTaskId(), task.getProcessInstanceId(), request.getComment());
|
taskService.addComment(request.getTaskId(), task.getProcessInstanceId(), request.getComment());
|
||||||
@ -138,7 +138,7 @@ public class ApprovalTaskServiceImpl implements IApprovalTaskService {
|
|||||||
// - 构建完整的 ApprovalOutputs 对象
|
// - 构建完整的 ApprovalOutputs 对象
|
||||||
// - 以 nodeId 为 key 存储到流程变量
|
// - 以 nodeId 为 key 存储到流程变量
|
||||||
taskService.complete(request.getTaskId());
|
taskService.complete(request.getTaskId());
|
||||||
|
|
||||||
log.info("审批任务完成: taskId={}, result={}", request.getTaskId(), request.getResult());
|
log.info("审批任务完成: taskId={}, result={}", request.getTaskId(), request.getResult());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -156,14 +156,14 @@ public class ApprovalTaskServiceImpl implements IApprovalTaskService {
|
|||||||
|
|
||||||
if (task.getCreateTime() != null) {
|
if (task.getCreateTime() != null) {
|
||||||
dto.setCreateTime(LocalDateTime.ofInstant(
|
dto.setCreateTime(LocalDateTime.ofInstant(
|
||||||
task.getCreateTime().toInstant(),
|
task.getCreateTime().toInstant(),
|
||||||
ZoneId.systemDefault()));
|
ZoneId.systemDefault()));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (task.getDueDate() != null) {
|
if (task.getDueDate() != null) {
|
||||||
dto.setDueDate(LocalDateTime.ofInstant(
|
dto.setDueDate(LocalDateTime.ofInstant(
|
||||||
task.getDueDate().toInstant(),
|
task.getDueDate().toInstant(),
|
||||||
ZoneId.systemDefault()));
|
ZoneId.systemDefault()));
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取任务变量
|
// 获取任务变量
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user