From 4b554a8a2a2f7f4325581bb3e3cd0aaad8e66ec5 Mon Sep 17 00:00:00 2001 From: dengqichen Date: Tue, 4 Nov 2025 21:15:40 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E9=83=A8=E7=BD=B2=E6=97=A5?= =?UTF-8?q?=E5=BF=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../backend/deploy/entity/DeployRecord.java | 2 +- .../deploy/enums/DeployRecordStatusEnums.java | 19 ++-- ...eployRecordWorkflowStatusSyncListener.java | 106 ++++++++++++++++++ .../repository/IDeployRecordRepository.java | 6 +- .../service/impl/DeployRecordServiceImpl.java | 9 +- 5 files changed, 125 insertions(+), 17 deletions(-) create mode 100644 backend/src/main/java/com/qqchen/deploy/backend/deploy/listener/DeployRecordWorkflowStatusSyncListener.java diff --git a/backend/src/main/java/com/qqchen/deploy/backend/deploy/entity/DeployRecord.java b/backend/src/main/java/com/qqchen/deploy/backend/deploy/entity/DeployRecord.java index d29f50a3..6cc4ca2e 100644 --- a/backend/src/main/java/com/qqchen/deploy/backend/deploy/entity/DeployRecord.java +++ b/backend/src/main/java/com/qqchen/deploy/backend/deploy/entity/DeployRecord.java @@ -76,7 +76,7 @@ public class DeployRecord extends Entity { /** * 部署状态 */ - @Column(name = "status", nullable = false, length = 20) + @Column(name = "status", nullable = false, length = 50) @Enumerated(EnumType.STRING) private DeployRecordStatusEnums status; diff --git a/backend/src/main/java/com/qqchen/deploy/backend/deploy/enums/DeployRecordStatusEnums.java b/backend/src/main/java/com/qqchen/deploy/backend/deploy/enums/DeployRecordStatusEnums.java index c88ab0f3..c0b1f4d1 100644 --- a/backend/src/main/java/com/qqchen/deploy/backend/deploy/enums/DeployRecordStatusEnums.java +++ b/backend/src/main/java/com/qqchen/deploy/backend/deploy/enums/DeployRecordStatusEnums.java @@ -42,19 +42,20 @@ public enum DeployRecordStatusEnums { PARTIAL_SUCCESS("PARTIAL_SUCCESS", "部分成功"), /** - * 已取消 + * 审批被拒绝(终态) + */ + REJECTED("REJECTED", "审批被拒绝"), + + /** + * 已取消(终态) + * 用于:手动取消部署、超时自动取消等场景 */ CANCELLED("CANCELLED", "已取消"), /** - * 已终止 + * 已终止(终态) */ - TERMINATED("TERMINATED", "已终止"), - - /** - * 已暂停 - */ - SUSPENDED("SUSPENDED", "已暂停"); + TERMINATED("TERMINATED", "已终止"); private final String code; private final String description; @@ -75,7 +76,7 @@ public enum DeployRecordStatusEnums { case "COMPLETED_WITH_ERRORS" -> PARTIAL_SUCCESS; case "FAILED" -> FAILED; case "TERMINATED" -> TERMINATED; - case "SUSPENDED" -> SUSPENDED; + case "SUSPENDED" -> RUNNING; // 工作流暂停时,部署记录仍视为运行中(可恢复) default -> CREATED; }; } diff --git a/backend/src/main/java/com/qqchen/deploy/backend/deploy/listener/DeployRecordWorkflowStatusSyncListener.java b/backend/src/main/java/com/qqchen/deploy/backend/deploy/listener/DeployRecordWorkflowStatusSyncListener.java new file mode 100644 index 00000000..8064ac1e --- /dev/null +++ b/backend/src/main/java/com/qqchen/deploy/backend/deploy/listener/DeployRecordWorkflowStatusSyncListener.java @@ -0,0 +1,106 @@ +package com.qqchen.deploy.backend.deploy.listener; + +import com.qqchen.deploy.backend.deploy.service.IDeployRecordService; +import com.qqchen.deploy.backend.workflow.dto.event.WorkflowInstanceStatusChangeEvent; +import com.qqchen.deploy.backend.workflow.entity.WorkflowInstance; +import com.qqchen.deploy.backend.workflow.repository.IWorkflowInstanceRepository; +import com.qqchen.deploy.backend.workflow.repository.IWorkflowDefinitionRepository; +import com.qqchen.deploy.backend.workflow.repository.IWorkflowCategoryRepository; +import com.qqchen.deploy.backend.workflow.entity.WorkflowDefinition; +import com.qqchen.deploy.backend.workflow.entity.WorkflowCategory; +import jakarta.annotation.Resource; +import lombok.extern.slf4j.Slf4j; +import org.springframework.context.event.EventListener; +import org.springframework.stereotype.Component; +import org.springframework.transaction.annotation.Propagation; +import org.springframework.transaction.annotation.Transactional; + +/** + * 部署记录工作流状态同步监听器 + * 监听工作流实例状态变化事件,同步更新部署记录状态 + * + * @author qqchen + * @since 2025-11-02 + */ +@Slf4j +@Component +public class DeployRecordWorkflowStatusSyncListener { + + private static final String DEPLOYMENT_CATEGORY_CODE = "DEPLOYMENT"; + + @Resource + private IDeployRecordService deployRecordService; + + @Resource + private IWorkflowInstanceRepository workflowInstanceRepository; + + @Resource + private IWorkflowDefinitionRepository workflowDefinitionRepository; + + @Resource + private IWorkflowCategoryRepository workflowCategoryRepository; + + /** + * 监听工作流实例状态变化事件 + * 同步更新部署记录状态 + */ + @EventListener + @Transactional(propagation = Propagation.REQUIRES_NEW) + public void handleWorkflowStatusChange(WorkflowInstanceStatusChangeEvent event) { + try { + // 1. 查询工作流实例 + WorkflowInstance instance = workflowInstanceRepository + .findByProcessInstanceId(event.getProcessInstanceId()) + .orElse(null); + + if (instance == null) { + log.warn("工作流实例不存在: processInstanceId={}", event.getProcessInstanceId()); + return; + } + + // 2. 判断是否为部署类型的工作流(提前校验,避免不必要的操作) + if (!isDeploymentWorkflow(instance)) { + return; + } + + // 3. 更新工作流实例的结束时间(如果事件中有且实例中还没有) + if (event.getEndTime() != null && instance.getEndTime() == null) { + instance.setEndTime(event.getEndTime()); + workflowInstanceRepository.save(instance); + } + + // 4. 同步状态(处理状态优先级) + // 注意:这里需要确保 instance 的 endTime 已更新,因为 syncStatusFromWorkflowInstance 会使用它 + deployRecordService.syncStatusFromWorkflowInstance(instance, event.getStatus()); + + } catch (Exception e) { + log.error("同步部署记录状态失败(工作流状态变化): processInstanceId={}", + event.getProcessInstanceId(), e); + // 不影响主流程,只记录错误 + } + } + + /** + * 判断是否为部署类型的工作流 + */ + private boolean isDeploymentWorkflow(WorkflowInstance instance) { + if (instance.getWorkflowDefinitionId() == null) { + return false; + } + + WorkflowDefinition definition = workflowDefinitionRepository + .findById(instance.getWorkflowDefinitionId()) + .orElse(null); + + if (definition == null || definition.getCategoryId() == null) { + return false; + } + + WorkflowCategory category = workflowCategoryRepository + .findById(definition.getCategoryId()) + .orElse(null); + + return category != null && DEPLOYMENT_CATEGORY_CODE.equals(category.getCode()); + } +} + diff --git a/backend/src/main/java/com/qqchen/deploy/backend/deploy/repository/IDeployRecordRepository.java b/backend/src/main/java/com/qqchen/deploy/backend/deploy/repository/IDeployRecordRepository.java index d1c279c1..6079b43b 100644 --- a/backend/src/main/java/com/qqchen/deploy/backend/deploy/repository/IDeployRecordRepository.java +++ b/backend/src/main/java/com/qqchen/deploy/backend/deploy/repository/IDeployRecordRepository.java @@ -53,15 +53,15 @@ public interface IDeployRecordRepository extends IBaseRepository 30) " + " THEN 1 ELSE 0 END) as failedCount, " + " SUM(CASE WHEN dr.status = 'RUNNING' " + diff --git a/backend/src/main/java/com/qqchen/deploy/backend/deploy/service/impl/DeployRecordServiceImpl.java b/backend/src/main/java/com/qqchen/deploy/backend/deploy/service/impl/DeployRecordServiceImpl.java index 9e5762b5..1870d091 100644 --- a/backend/src/main/java/com/qqchen/deploy/backend/deploy/service/impl/DeployRecordServiceImpl.java +++ b/backend/src/main/java/com/qqchen/deploy/backend/deploy/service/impl/DeployRecordServiceImpl.java @@ -85,7 +85,7 @@ public class DeployRecordServiceImpl extends BaseServiceImpl