增加部署日志
This commit is contained in:
parent
b6b23bfd34
commit
990889858c
@ -0,0 +1,17 @@
|
|||||||
|
package com.qqchen.deploy.backend.deploy.converter;
|
||||||
|
|
||||||
|
import com.qqchen.deploy.backend.deploy.dto.DeployRecordDTO;
|
||||||
|
import com.qqchen.deploy.backend.deploy.entity.DeployRecord;
|
||||||
|
import com.qqchen.deploy.backend.framework.converter.BaseConverter;
|
||||||
|
import org.mapstruct.Mapper;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 部署记录转换器
|
||||||
|
*
|
||||||
|
* @author qqchen
|
||||||
|
* @since 2025-11-02
|
||||||
|
*/
|
||||||
|
@Mapper(config = BaseConverter.class)
|
||||||
|
public interface DeployRecordConverter extends BaseConverter<DeployRecord, DeployRecordDTO> {
|
||||||
|
}
|
||||||
|
|
||||||
@ -0,0 +1,55 @@
|
|||||||
|
package com.qqchen.deploy.backend.deploy.dto;
|
||||||
|
|
||||||
|
import com.qqchen.deploy.backend.deploy.enums.DeployRecordStatusEnums;
|
||||||
|
import com.qqchen.deploy.backend.framework.dto.BaseDTO;
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 部署记录DTO
|
||||||
|
*
|
||||||
|
* @author qqchen
|
||||||
|
* @since 2025-11-02
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
@Schema(description = "部署记录信息")
|
||||||
|
public class DeployRecordDTO extends BaseDTO {
|
||||||
|
|
||||||
|
@Schema(description = "工作流实例ID")
|
||||||
|
private Long workflowInstanceId;
|
||||||
|
|
||||||
|
@Schema(description = "业务标识")
|
||||||
|
private String businessKey;
|
||||||
|
|
||||||
|
@Schema(description = "团队应用配置ID")
|
||||||
|
private Long teamApplicationId;
|
||||||
|
|
||||||
|
@Schema(description = "团队ID")
|
||||||
|
private Long teamId;
|
||||||
|
|
||||||
|
@Schema(description = "应用ID")
|
||||||
|
private Long applicationId;
|
||||||
|
|
||||||
|
@Schema(description = "环境ID")
|
||||||
|
private Long environmentId;
|
||||||
|
|
||||||
|
@Schema(description = "部署人")
|
||||||
|
private String deployBy;
|
||||||
|
|
||||||
|
@Schema(description = "部署备注")
|
||||||
|
private String deployRemark;
|
||||||
|
|
||||||
|
@Schema(description = "部署状态")
|
||||||
|
private DeployRecordStatusEnums status;
|
||||||
|
|
||||||
|
@Schema(description = "开始时间")
|
||||||
|
private LocalDateTime startTime;
|
||||||
|
|
||||||
|
@Schema(description = "结束时间")
|
||||||
|
private LocalDateTime endTime;
|
||||||
|
}
|
||||||
|
|
||||||
@ -0,0 +1,40 @@
|
|||||||
|
package com.qqchen.deploy.backend.deploy.dto;
|
||||||
|
|
||||||
|
import com.qqchen.deploy.backend.deploy.enums.DeployRecordStatusEnums;
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 部署记录摘要DTO
|
||||||
|
*
|
||||||
|
* @author qqchen
|
||||||
|
* @since 2025-11-02
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@Schema(description = "部署记录摘要")
|
||||||
|
public class DeployRecordSummaryDTO {
|
||||||
|
|
||||||
|
@Schema(description = "部署记录ID")
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
@Schema(description = "部署状态")
|
||||||
|
private DeployRecordStatusEnums status;
|
||||||
|
|
||||||
|
@Schema(description = "部署人")
|
||||||
|
private String deployBy;
|
||||||
|
|
||||||
|
@Schema(description = "开始时间")
|
||||||
|
private LocalDateTime startTime;
|
||||||
|
|
||||||
|
@Schema(description = "结束时间")
|
||||||
|
private LocalDateTime endTime;
|
||||||
|
|
||||||
|
@Schema(description = "部署备注")
|
||||||
|
private String deployRemark;
|
||||||
|
|
||||||
|
@Schema(description = "持续时间(毫秒)")
|
||||||
|
private Long duration;
|
||||||
|
}
|
||||||
|
|
||||||
@ -0,0 +1,40 @@
|
|||||||
|
package com.qqchen.deploy.backend.deploy.dto;
|
||||||
|
|
||||||
|
import com.qqchen.deploy.backend.deploy.enums.DeployRecordStatusEnums;
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 部署统计信息DTO
|
||||||
|
*
|
||||||
|
* @author qqchen
|
||||||
|
* @since 2025-11-02
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@Schema(description = "部署统计信息")
|
||||||
|
public class DeployStatisticsDTO {
|
||||||
|
|
||||||
|
@Schema(description = "总部署次数")
|
||||||
|
private Long totalCount;
|
||||||
|
|
||||||
|
@Schema(description = "成功次数")
|
||||||
|
private Long successCount;
|
||||||
|
|
||||||
|
@Schema(description = "失败次数")
|
||||||
|
private Long failedCount;
|
||||||
|
|
||||||
|
@Schema(description = "运行中次数")
|
||||||
|
private Long runningCount;
|
||||||
|
|
||||||
|
@Schema(description = "最近部署时间")
|
||||||
|
private LocalDateTime lastDeployTime;
|
||||||
|
|
||||||
|
@Schema(description = "最近部署人")
|
||||||
|
private String lastDeployBy;
|
||||||
|
|
||||||
|
@Schema(description = "最新部署状态")
|
||||||
|
private DeployRecordStatusEnums latestStatus;
|
||||||
|
}
|
||||||
|
|
||||||
@ -1,8 +1,11 @@
|
|||||||
package com.qqchen.deploy.backend.deploy.dto;
|
package com.qqchen.deploy.backend.deploy.dto;
|
||||||
|
|
||||||
|
import com.qqchen.deploy.backend.deploy.enums.DeployRecordStatusEnums;
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 可部署应用DTO
|
* 可部署应用DTO
|
||||||
*
|
*
|
||||||
@ -48,5 +51,14 @@ public class DeployableApplicationDTO {
|
|||||||
|
|
||||||
@Schema(description = "工作流流程标识(processKey)")
|
@Schema(description = "工作流流程标识(processKey)")
|
||||||
private String workflowDefinitionKey;
|
private String workflowDefinitionKey;
|
||||||
|
|
||||||
|
@Schema(description = "部署统计信息")
|
||||||
|
private DeployStatisticsDTO deployStatistics;
|
||||||
|
|
||||||
|
@Schema(description = "是否正在部署中")
|
||||||
|
private Boolean isDeploying;
|
||||||
|
|
||||||
|
@Schema(description = "最近部署记录列表(最多10条)")
|
||||||
|
private List<DeployRecordSummaryDTO> recentDeployRecords;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -0,0 +1,95 @@
|
|||||||
|
package com.qqchen.deploy.backend.deploy.entity;
|
||||||
|
|
||||||
|
import com.qqchen.deploy.backend.deploy.enums.DeployRecordStatusEnums;
|
||||||
|
import com.qqchen.deploy.backend.framework.annotation.LogicDelete;
|
||||||
|
import com.qqchen.deploy.backend.framework.domain.Entity;
|
||||||
|
import jakarta.persistence.Column;
|
||||||
|
import jakarta.persistence.EnumType;
|
||||||
|
import jakarta.persistence.Enumerated;
|
||||||
|
import jakarta.persistence.Table;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 部署记录实体
|
||||||
|
*
|
||||||
|
* @author qqchen
|
||||||
|
* @since 2025-11-02
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
@jakarta.persistence.Entity
|
||||||
|
@Table(name = "deploy_record")
|
||||||
|
@LogicDelete
|
||||||
|
public class DeployRecord extends Entity<Long> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 工作流实例ID
|
||||||
|
*/
|
||||||
|
@Column(name = "workflow_instance_id", nullable = false)
|
||||||
|
private Long workflowInstanceId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 业务标识(UUID)
|
||||||
|
*/
|
||||||
|
@Column(name = "business_key", nullable = false, length = 64)
|
||||||
|
private String businessKey;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 团队应用配置ID
|
||||||
|
*/
|
||||||
|
@Column(name = "team_application_id", nullable = false)
|
||||||
|
private Long teamApplicationId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 团队ID
|
||||||
|
*/
|
||||||
|
@Column(name = "team_id", nullable = false)
|
||||||
|
private Long teamId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 应用ID
|
||||||
|
*/
|
||||||
|
@Column(name = "application_id", nullable = false)
|
||||||
|
private Long applicationId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 环境ID
|
||||||
|
*/
|
||||||
|
@Column(name = "environment_id", nullable = false)
|
||||||
|
private Long environmentId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 部署人
|
||||||
|
*/
|
||||||
|
@Column(name = "deploy_by", length = 50)
|
||||||
|
private String deployBy;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 部署备注
|
||||||
|
*/
|
||||||
|
@Column(name = "deploy_remark", length = 500)
|
||||||
|
private String deployRemark;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 部署状态
|
||||||
|
*/
|
||||||
|
@Column(name = "status", nullable = false, length = 20)
|
||||||
|
@Enumerated(EnumType.STRING)
|
||||||
|
private DeployRecordStatusEnums status;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 开始时间
|
||||||
|
*/
|
||||||
|
@Column(name = "start_time")
|
||||||
|
private LocalDateTime startTime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 结束时间
|
||||||
|
*/
|
||||||
|
@Column(name = "end_time")
|
||||||
|
private LocalDateTime endTime;
|
||||||
|
}
|
||||||
|
|
||||||
@ -0,0 +1,78 @@
|
|||||||
|
package com.qqchen.deploy.backend.deploy.enums;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 部署记录状态枚举
|
||||||
|
*
|
||||||
|
* @author qqchen
|
||||||
|
* @since 2025-11-02
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
public enum DeployRecordStatusEnums {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 已创建
|
||||||
|
*/
|
||||||
|
CREATED("CREATED", "已创建"),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 运行中
|
||||||
|
*/
|
||||||
|
RUNNING("RUNNING", "运行中"),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 部署成功
|
||||||
|
*/
|
||||||
|
SUCCESS("SUCCESS", "部署成功"),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 部署失败
|
||||||
|
*/
|
||||||
|
FAILED("FAILED", "部署失败"),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 部分成功(工作流完成但存在失败的节点)
|
||||||
|
*/
|
||||||
|
PARTIAL_SUCCESS("PARTIAL_SUCCESS", "部分成功"),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 已取消
|
||||||
|
*/
|
||||||
|
CANCELLED("CANCELLED", "已取消"),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 已终止
|
||||||
|
*/
|
||||||
|
TERMINATED("TERMINATED", "已终止"),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 已暂停
|
||||||
|
*/
|
||||||
|
SUSPENDED("SUSPENDED", "已暂停");
|
||||||
|
|
||||||
|
private final String code;
|
||||||
|
private final String description;
|
||||||
|
|
||||||
|
DeployRecordStatusEnums(String code, String description) {
|
||||||
|
this.code = code;
|
||||||
|
this.description = description;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将工作流状态转换为部署记录状态
|
||||||
|
*/
|
||||||
|
public static DeployRecordStatusEnums fromWorkflowStatus(String workflowStatus) {
|
||||||
|
return switch (workflowStatus) {
|
||||||
|
case "CREATED" -> CREATED;
|
||||||
|
case "RUNNING" -> RUNNING;
|
||||||
|
case "COMPLETED" -> SUCCESS;
|
||||||
|
case "COMPLETED_WITH_ERRORS" -> PARTIAL_SUCCESS;
|
||||||
|
case "FAILED" -> FAILED;
|
||||||
|
case "TERMINATED" -> TERMINATED;
|
||||||
|
case "SUSPENDED" -> SUSPENDED;
|
||||||
|
default -> CREATED;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@ -0,0 +1,37 @@
|
|||||||
|
package com.qqchen.deploy.backend.deploy.query;
|
||||||
|
|
||||||
|
import com.qqchen.deploy.backend.framework.annotation.QueryField;
|
||||||
|
import com.qqchen.deploy.backend.framework.enums.QueryType;
|
||||||
|
import com.qqchen.deploy.backend.framework.query.BaseQuery;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 部署记录查询条件
|
||||||
|
*
|
||||||
|
* @author qqchen
|
||||||
|
* @since 2025-11-02
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
public class DeployRecordQuery extends BaseQuery {
|
||||||
|
|
||||||
|
@QueryField(field = "teamApplicationId", type = QueryType.EQUAL)
|
||||||
|
private Long teamApplicationId;
|
||||||
|
|
||||||
|
@QueryField(field = "applicationId", type = QueryType.EQUAL)
|
||||||
|
private Long applicationId;
|
||||||
|
|
||||||
|
@QueryField(field = "environmentId", type = QueryType.EQUAL)
|
||||||
|
private Long environmentId;
|
||||||
|
|
||||||
|
@QueryField(field = "teamId", type = QueryType.EQUAL)
|
||||||
|
private Long teamId;
|
||||||
|
|
||||||
|
@QueryField(field = "status", type = QueryType.EQUAL)
|
||||||
|
private String status;
|
||||||
|
|
||||||
|
@QueryField(field = "deployBy", type = QueryType.LIKE)
|
||||||
|
private String deployBy;
|
||||||
|
}
|
||||||
|
|
||||||
@ -0,0 +1,102 @@
|
|||||||
|
package com.qqchen.deploy.backend.deploy.repository;
|
||||||
|
|
||||||
|
import com.qqchen.deploy.backend.deploy.entity.DeployRecord;
|
||||||
|
import com.qqchen.deploy.backend.framework.repository.IBaseRepository;
|
||||||
|
import org.springframework.data.domain.Page;
|
||||||
|
import org.springframework.data.domain.Pageable;
|
||||||
|
import org.springframework.data.jpa.repository.Query;
|
||||||
|
import org.springframework.data.repository.query.Param;
|
||||||
|
import org.springframework.stereotype.Repository;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 部署记录仓库
|
||||||
|
*
|
||||||
|
* @author qqchen
|
||||||
|
* @since 2025-11-02
|
||||||
|
*/
|
||||||
|
@Repository
|
||||||
|
public interface IDeployRecordRepository extends IBaseRepository<DeployRecord, Long> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据工作流实例ID查询部署记录
|
||||||
|
*/
|
||||||
|
Optional<DeployRecord> findByWorkflowInstanceIdAndDeletedFalse(Long workflowInstanceId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据团队应用ID查询最新部署记录
|
||||||
|
*/
|
||||||
|
Optional<DeployRecord> findFirstByTeamApplicationIdAndDeletedFalseOrderByCreateTimeDesc(Long teamApplicationId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据应用ID和环境ID查询最新部署记录
|
||||||
|
*/
|
||||||
|
Optional<DeployRecord> findFirstByApplicationIdAndEnvironmentIdAndDeletedFalseOrderByCreateTimeDesc(
|
||||||
|
Long applicationId, Long environmentId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据团队应用ID分页查询部署记录
|
||||||
|
*/
|
||||||
|
Page<DeployRecord> findByTeamApplicationIdAndDeletedFalseOrderByCreateTimeDesc(
|
||||||
|
Long teamApplicationId, Pageable pageable);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据应用ID和环境ID查询部署记录列表
|
||||||
|
*/
|
||||||
|
List<DeployRecord> findByApplicationIdAndEnvironmentIdAndDeletedFalseOrderByCreateTimeDesc(
|
||||||
|
Long applicationId, Long environmentId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 批量查询部署统计信息(按团队应用ID分组)
|
||||||
|
*/
|
||||||
|
@Query("SELECT dr.teamApplicationId, " +
|
||||||
|
"COUNT(dr.id) as totalCount, " +
|
||||||
|
"SUM(CASE WHEN dr.status = 'SUCCESS' THEN 1 ELSE 0 END) as successCount, " +
|
||||||
|
"SUM(CASE WHEN dr.status IN ('FAILED', 'CANCELLED', 'TERMINATED') THEN 1 ELSE 0 END) as failedCount, " +
|
||||||
|
"SUM(CASE WHEN dr.status IN ('CREATED', 'RUNNING') THEN 1 ELSE 0 END) as runningCount, " +
|
||||||
|
"MAX(dr.startTime) as lastDeployTime " +
|
||||||
|
"FROM DeployRecord dr " +
|
||||||
|
"WHERE dr.teamApplicationId IN :teamApplicationIds AND dr.deleted = false " +
|
||||||
|
"GROUP BY dr.teamApplicationId")
|
||||||
|
List<Object[]> findDeployStatisticsByTeamApplicationIds(
|
||||||
|
@Param("teamApplicationIds") List<Long> teamApplicationIds);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 批量查询每个团队应用的最新部署记录(用于获取最新状态和部署人)
|
||||||
|
* 使用原生SQL避免JPQL类型问题
|
||||||
|
*/
|
||||||
|
@Query(value = "SELECT dr.* FROM deploy_record dr " +
|
||||||
|
"INNER JOIN (" +
|
||||||
|
" SELECT team_application_id, MAX(id) as max_id " +
|
||||||
|
" FROM deploy_record " +
|
||||||
|
" WHERE team_application_id IN (:teamApplicationIds) " +
|
||||||
|
" AND deleted = false " +
|
||||||
|
" GROUP BY team_application_id" +
|
||||||
|
") latest ON dr.id = latest.max_id " +
|
||||||
|
"WHERE dr.deleted = false " +
|
||||||
|
"ORDER BY dr.create_time DESC",
|
||||||
|
nativeQuery = true)
|
||||||
|
List<DeployRecord> findLatestDeployRecordsByTeamApplicationIds(
|
||||||
|
@Param("teamApplicationIds") List<Long> teamApplicationIds);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 批量查询每个团队应用的最近N条部署记录
|
||||||
|
* 使用原生SQL实现(MySQL支持窗口函数)
|
||||||
|
*/
|
||||||
|
@Query(value = "SELECT * FROM (" +
|
||||||
|
" SELECT dr.*, " +
|
||||||
|
" ROW_NUMBER() OVER (PARTITION BY dr.team_application_id ORDER BY dr.create_time DESC) as rn " +
|
||||||
|
" FROM deploy_record dr " +
|
||||||
|
" WHERE dr.team_application_id IN :teamApplicationIds " +
|
||||||
|
" AND dr.deleted = false" +
|
||||||
|
") ranked " +
|
||||||
|
"WHERE ranked.rn <= :limit " +
|
||||||
|
"ORDER BY ranked.team_application_id, ranked.create_time DESC",
|
||||||
|
nativeQuery = true)
|
||||||
|
List<DeployRecord> findRecentDeployRecordsByTeamApplicationIds(
|
||||||
|
@Param("teamApplicationIds") List<Long> teamApplicationIds,
|
||||||
|
@Param("limit") int limit);
|
||||||
|
}
|
||||||
|
|
||||||
@ -0,0 +1,56 @@
|
|||||||
|
package com.qqchen.deploy.backend.deploy.service;
|
||||||
|
|
||||||
|
import com.qqchen.deploy.backend.deploy.dto.DeployRecordDTO;
|
||||||
|
import com.qqchen.deploy.backend.deploy.entity.DeployRecord;
|
||||||
|
import com.qqchen.deploy.backend.workflow.entity.WorkflowInstance;
|
||||||
|
import com.qqchen.deploy.backend.workflow.enums.WorkflowInstanceStatusEnums;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 部署记录服务接口
|
||||||
|
*
|
||||||
|
* @author qqchen
|
||||||
|
* @since 2025-11-02
|
||||||
|
*/
|
||||||
|
public interface IDeployRecordService {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建部署记录
|
||||||
|
*
|
||||||
|
* @param workflowInstanceId 工作流实例ID
|
||||||
|
* @param businessKey 业务标识
|
||||||
|
* @param teamApplicationId 团队应用配置ID
|
||||||
|
* @param teamId 团队ID
|
||||||
|
* @param applicationId 应用ID
|
||||||
|
* @param environmentId 环境ID
|
||||||
|
* @param deployBy 部署人
|
||||||
|
* @param deployRemark 部署备注
|
||||||
|
* @return 部署记录DTO
|
||||||
|
*/
|
||||||
|
DeployRecordDTO createDeployRecord(
|
||||||
|
Long workflowInstanceId,
|
||||||
|
String businessKey,
|
||||||
|
Long teamApplicationId,
|
||||||
|
Long teamId,
|
||||||
|
Long applicationId,
|
||||||
|
Long environmentId,
|
||||||
|
String deployBy,
|
||||||
|
String deployRemark
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据工作流实例同步部署记录状态
|
||||||
|
*
|
||||||
|
* @param instance 工作流实例
|
||||||
|
* @param status 工作流状态
|
||||||
|
*/
|
||||||
|
void syncStatusFromWorkflowInstance(WorkflowInstance instance, WorkflowInstanceStatusEnums status);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据工作流实例ID查询部署记录
|
||||||
|
*
|
||||||
|
* @param workflowInstanceId 工作流实例ID
|
||||||
|
* @return 部署记录DTO
|
||||||
|
*/
|
||||||
|
DeployRecordDTO findByWorkflowInstanceId(Long workflowInstanceId);
|
||||||
|
}
|
||||||
|
|
||||||
@ -0,0 +1,116 @@
|
|||||||
|
package com.qqchen.deploy.backend.deploy.service.impl;
|
||||||
|
|
||||||
|
import com.qqchen.deploy.backend.deploy.converter.DeployRecordConverter;
|
||||||
|
import com.qqchen.deploy.backend.deploy.dto.DeployRecordDTO;
|
||||||
|
import com.qqchen.deploy.backend.deploy.entity.DeployRecord;
|
||||||
|
import com.qqchen.deploy.backend.deploy.enums.DeployRecordStatusEnums;
|
||||||
|
import com.qqchen.deploy.backend.deploy.query.DeployRecordQuery;
|
||||||
|
import com.qqchen.deploy.backend.deploy.repository.IDeployRecordRepository;
|
||||||
|
import com.qqchen.deploy.backend.deploy.service.IDeployRecordService;
|
||||||
|
import com.qqchen.deploy.backend.framework.service.impl.BaseServiceImpl;
|
||||||
|
import com.qqchen.deploy.backend.workflow.entity.WorkflowInstance;
|
||||||
|
import com.qqchen.deploy.backend.workflow.enums.WorkflowInstanceStatusEnums;
|
||||||
|
import jakarta.annotation.Resource;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 部署记录服务实现
|
||||||
|
*
|
||||||
|
* @author qqchen
|
||||||
|
* @since 2025-11-02
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@Service
|
||||||
|
public class DeployRecordServiceImpl extends BaseServiceImpl<DeployRecord, DeployRecordDTO, DeployRecordQuery, Long>
|
||||||
|
implements IDeployRecordService {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private IDeployRecordRepository deployRecordRepository;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private DeployRecordConverter deployRecordConverter;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Transactional
|
||||||
|
public DeployRecordDTO createDeployRecord(
|
||||||
|
Long workflowInstanceId,
|
||||||
|
String businessKey,
|
||||||
|
Long teamApplicationId,
|
||||||
|
Long teamId,
|
||||||
|
Long applicationId,
|
||||||
|
Long environmentId,
|
||||||
|
String deployBy,
|
||||||
|
String deployRemark
|
||||||
|
) {
|
||||||
|
// 检查是否已存在
|
||||||
|
DeployRecord existing = deployRecordRepository
|
||||||
|
.findByWorkflowInstanceIdAndDeletedFalse(workflowInstanceId)
|
||||||
|
.orElse(null);
|
||||||
|
|
||||||
|
if (existing != null) {
|
||||||
|
log.warn("部署记录已存在: workflowInstanceId={}", workflowInstanceId);
|
||||||
|
return deployRecordConverter.toDto(existing);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 创建新记录
|
||||||
|
DeployRecord record = new DeployRecord();
|
||||||
|
record.setWorkflowInstanceId(workflowInstanceId);
|
||||||
|
record.setBusinessKey(businessKey);
|
||||||
|
record.setTeamApplicationId(teamApplicationId);
|
||||||
|
record.setTeamId(teamId);
|
||||||
|
record.setApplicationId(applicationId);
|
||||||
|
record.setEnvironmentId(environmentId);
|
||||||
|
record.setDeployBy(deployBy);
|
||||||
|
record.setDeployRemark(deployRemark);
|
||||||
|
record.setStatus(DeployRecordStatusEnums.CREATED);
|
||||||
|
record.setStartTime(LocalDateTime.now());
|
||||||
|
|
||||||
|
DeployRecord saved = deployRecordRepository.save(record);
|
||||||
|
log.info("创建部署记录成功: id={}, workflowInstanceId={}, applicationId={}, environmentId={}",
|
||||||
|
saved.getId(), workflowInstanceId, applicationId, environmentId);
|
||||||
|
|
||||||
|
return deployRecordConverter.toDto(saved);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Transactional
|
||||||
|
public void syncStatusFromWorkflowInstance(WorkflowInstance instance, WorkflowInstanceStatusEnums status) {
|
||||||
|
DeployRecord record = deployRecordRepository
|
||||||
|
.findByWorkflowInstanceIdAndDeletedFalse(instance.getId())
|
||||||
|
.orElse(null);
|
||||||
|
|
||||||
|
if (record == null) {
|
||||||
|
log.warn("部署记录不存在,无法同步状态: workflowInstanceId={}", instance.getId());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 转换状态
|
||||||
|
DeployRecordStatusEnums deployStatus = DeployRecordStatusEnums.fromWorkflowStatus(status.name());
|
||||||
|
|
||||||
|
// 更新状态和时间
|
||||||
|
record.setStatus(deployStatus);
|
||||||
|
if (instance.getStartTime() != null && record.getStartTime() == null) {
|
||||||
|
record.setStartTime(instance.getStartTime());
|
||||||
|
}
|
||||||
|
if (instance.getEndTime() != null) {
|
||||||
|
record.setEndTime(instance.getEndTime());
|
||||||
|
}
|
||||||
|
|
||||||
|
deployRecordRepository.save(record);
|
||||||
|
log.debug("同步部署记录状态: id={}, workflowInstanceId={}, status={}",
|
||||||
|
record.getId(), instance.getId(), deployStatus);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DeployRecordDTO findByWorkflowInstanceId(Long workflowInstanceId) {
|
||||||
|
return deployRecordRepository
|
||||||
|
.findByWorkflowInstanceIdAndDeletedFalse(workflowInstanceId)
|
||||||
|
.map(deployRecordConverter::toDto)
|
||||||
|
.orElse(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@ -16,11 +16,16 @@ import com.qqchen.deploy.backend.workflow.dto.inputmapping.JenkinsBuildInputMapp
|
|||||||
import com.qqchen.deploy.backend.workflow.entity.WorkflowDefinition;
|
import com.qqchen.deploy.backend.workflow.entity.WorkflowDefinition;
|
||||||
import com.qqchen.deploy.backend.workflow.repository.IWorkflowDefinitionRepository;
|
import com.qqchen.deploy.backend.workflow.repository.IWorkflowDefinitionRepository;
|
||||||
import com.qqchen.deploy.backend.workflow.service.IWorkflowInstanceService;
|
import com.qqchen.deploy.backend.workflow.service.IWorkflowInstanceService;
|
||||||
|
import com.qqchen.deploy.backend.deploy.service.IDeployRecordService;
|
||||||
|
import com.qqchen.deploy.backend.deploy.repository.IDeployRecordRepository;
|
||||||
|
import com.qqchen.deploy.backend.deploy.entity.DeployRecord;
|
||||||
|
import com.qqchen.deploy.backend.deploy.enums.DeployRecordStatusEnums;
|
||||||
import jakarta.annotation.Resource;
|
import jakarta.annotation.Resource;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
@ -66,6 +71,12 @@ public class DeployServiceImpl implements IDeployService {
|
|||||||
@Resource
|
@Resource
|
||||||
private IWorkflowInstanceService workflowInstanceService;
|
private IWorkflowInstanceService workflowInstanceService;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private IDeployRecordService deployRecordService;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private IDeployRecordRepository deployRecordRepository;
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
private ObjectMapper objectMapper;
|
private ObjectMapper objectMapper;
|
||||||
|
|
||||||
@ -178,7 +189,62 @@ public class DeployServiceImpl implements IDeployService {
|
|||||||
approverMap = Collections.emptyMap();
|
approverMap = Collections.emptyMap();
|
||||||
}
|
}
|
||||||
|
|
||||||
// 12. 组装团队数据
|
// 12. 批量查询部署记录信息
|
||||||
|
List<Long> teamApplicationIds = allTeamApps.stream()
|
||||||
|
.map(TeamApplication::getId)
|
||||||
|
.collect(toList());
|
||||||
|
|
||||||
|
// 12.1 批量查询部署统计信息
|
||||||
|
final Map<Long, DeployStatisticsDTO> statisticsMap = new HashMap<>();
|
||||||
|
final Map<Long, DeployRecord> latestRecordMap = new HashMap<>();
|
||||||
|
final Map<Long, List<DeployRecord>> recentRecordsMap = new HashMap<>();
|
||||||
|
|
||||||
|
if (!teamApplicationIds.isEmpty()) {
|
||||||
|
// 查询统计信息
|
||||||
|
List<Object[]> statisticsList = deployRecordRepository
|
||||||
|
.findDeployStatisticsByTeamApplicationIds(teamApplicationIds);
|
||||||
|
for (Object[] row : statisticsList) {
|
||||||
|
Long teamApplicationId = (Long) row[0];
|
||||||
|
Long totalCount = ((Number) row[1]).longValue();
|
||||||
|
Long successCount = ((Number) row[2]).longValue();
|
||||||
|
Long failedCount = ((Number) row[3]).longValue();
|
||||||
|
Long runningCount = ((Number) row[4]).longValue();
|
||||||
|
LocalDateTime lastDeployTime = (LocalDateTime) row[5];
|
||||||
|
|
||||||
|
DeployStatisticsDTO stats = new DeployStatisticsDTO();
|
||||||
|
stats.setTotalCount(totalCount);
|
||||||
|
stats.setSuccessCount(successCount);
|
||||||
|
stats.setFailedCount(failedCount);
|
||||||
|
stats.setRunningCount(runningCount);
|
||||||
|
stats.setLastDeployTime(lastDeployTime);
|
||||||
|
statisticsMap.put(teamApplicationId, stats);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 查询最新部署记录(用于获取最新状态和部署人)
|
||||||
|
List<DeployRecord> latestRecords = deployRecordRepository
|
||||||
|
.findLatestDeployRecordsByTeamApplicationIds(teamApplicationIds);
|
||||||
|
latestRecordMap.putAll(latestRecords.stream()
|
||||||
|
.collect(toMap(DeployRecord::getTeamApplicationId, r -> r)));
|
||||||
|
|
||||||
|
// 更新统计信息中的最新状态和部署人
|
||||||
|
latestRecordMap.forEach((teamAppId, record) -> {
|
||||||
|
DeployStatisticsDTO stats = statisticsMap.get(teamAppId);
|
||||||
|
if (stats == null) {
|
||||||
|
stats = new DeployStatisticsDTO();
|
||||||
|
statisticsMap.put(teamAppId, stats);
|
||||||
|
}
|
||||||
|
stats.setLatestStatus(record.getStatus());
|
||||||
|
stats.setLastDeployBy(record.getDeployBy());
|
||||||
|
});
|
||||||
|
|
||||||
|
// 查询最近10条部署记录
|
||||||
|
List<DeployRecord> recentRecords = deployRecordRepository
|
||||||
|
.findRecentDeployRecordsByTeamApplicationIds(teamApplicationIds, 10);
|
||||||
|
recentRecordsMap.putAll(recentRecords.stream()
|
||||||
|
.collect(groupingBy(DeployRecord::getTeamApplicationId)));
|
||||||
|
}
|
||||||
|
|
||||||
|
// 13. 组装团队数据
|
||||||
Map<Long, TeamMember> teamMemberMap = teamMembers.stream()
|
Map<Long, TeamMember> teamMemberMap = teamMembers.stream()
|
||||||
.collect(toMap(TeamMember::getTeamId, tm -> tm));
|
.collect(toMap(TeamMember::getTeamId, tm -> tm));
|
||||||
|
|
||||||
@ -194,12 +260,15 @@ public class DeployServiceImpl implements IDeployService {
|
|||||||
appMap,
|
appMap,
|
||||||
systemMap,
|
systemMap,
|
||||||
workflowMap,
|
workflowMap,
|
||||||
approverMap
|
approverMap,
|
||||||
|
statisticsMap,
|
||||||
|
latestRecordMap,
|
||||||
|
recentRecordsMap
|
||||||
))
|
))
|
||||||
.filter(Objects::nonNull)
|
.filter(Objects::nonNull)
|
||||||
.collect(toList());
|
.collect(toList());
|
||||||
|
|
||||||
// 13. 组装最终结果
|
// 14. 组装最终结果
|
||||||
UserDeployableDTO result = new UserDeployableDTO();
|
UserDeployableDTO result = new UserDeployableDTO();
|
||||||
result.setUserId(user.getId());
|
result.setUserId(user.getId());
|
||||||
result.setUsername(user.getUsername());
|
result.setUsername(user.getUsername());
|
||||||
@ -236,7 +305,10 @@ public class DeployServiceImpl implements IDeployService {
|
|||||||
Map<Long, Application> appMap,
|
Map<Long, Application> appMap,
|
||||||
Map<Long, ExternalSystem> systemMap,
|
Map<Long, ExternalSystem> systemMap,
|
||||||
Map<Long, WorkflowDefinition> workflowMap,
|
Map<Long, WorkflowDefinition> workflowMap,
|
||||||
Map<Long, User> approverMap
|
Map<Long, User> approverMap,
|
||||||
|
Map<Long, DeployStatisticsDTO> statisticsMap,
|
||||||
|
Map<Long, DeployRecord> latestRecordMap,
|
||||||
|
Map<Long, List<DeployRecord>> recentRecordsMap
|
||||||
) {
|
) {
|
||||||
Team team = teamMap.get(teamId);
|
Team team = teamMap.get(teamId);
|
||||||
if (team == null) {
|
if (team == null) {
|
||||||
@ -286,7 +358,10 @@ public class DeployServiceImpl implements IDeployService {
|
|||||||
appMap,
|
appMap,
|
||||||
systemMap,
|
systemMap,
|
||||||
workflowMap,
|
workflowMap,
|
||||||
approverMap
|
approverMap,
|
||||||
|
statisticsMap,
|
||||||
|
latestRecordMap,
|
||||||
|
recentRecordsMap
|
||||||
);
|
);
|
||||||
|
|
||||||
envDTOs.add(envDTO);
|
envDTOs.add(envDTO);
|
||||||
@ -312,7 +387,10 @@ public class DeployServiceImpl implements IDeployService {
|
|||||||
Map<Long, Application> appMap,
|
Map<Long, Application> appMap,
|
||||||
Map<Long, ExternalSystem> systemMap,
|
Map<Long, ExternalSystem> systemMap,
|
||||||
Map<Long, WorkflowDefinition> workflowMap,
|
Map<Long, WorkflowDefinition> workflowMap,
|
||||||
Map<Long, User> approverMap
|
Map<Long, User> approverMap,
|
||||||
|
Map<Long, DeployStatisticsDTO> statisticsMap,
|
||||||
|
Map<Long, DeployRecord> latestRecordMap,
|
||||||
|
Map<Long, List<DeployRecord>> recentRecordsMap
|
||||||
) {
|
) {
|
||||||
DeployableEnvironmentDTO envDTO = new DeployableEnvironmentDTO();
|
DeployableEnvironmentDTO envDTO = new DeployableEnvironmentDTO();
|
||||||
envDTO.setEnvironmentId(env.getId());
|
envDTO.setEnvironmentId(env.getId());
|
||||||
@ -349,7 +427,15 @@ public class DeployServiceImpl implements IDeployService {
|
|||||||
|
|
||||||
// 应用列表
|
// 应用列表
|
||||||
List<DeployableApplicationDTO> appDTOs = teamApps.stream()
|
List<DeployableApplicationDTO> appDTOs = teamApps.stream()
|
||||||
.map(ta -> buildApplicationDTO(ta, appMap, systemMap, workflowMap))
|
.map(ta -> buildApplicationDTO(
|
||||||
|
ta,
|
||||||
|
appMap,
|
||||||
|
systemMap,
|
||||||
|
workflowMap,
|
||||||
|
statisticsMap,
|
||||||
|
latestRecordMap,
|
||||||
|
recentRecordsMap
|
||||||
|
))
|
||||||
.filter(Objects::nonNull)
|
.filter(Objects::nonNull)
|
||||||
.collect(toList());
|
.collect(toList());
|
||||||
|
|
||||||
@ -381,7 +467,10 @@ public class DeployServiceImpl implements IDeployService {
|
|||||||
TeamApplication ta,
|
TeamApplication ta,
|
||||||
Map<Long, Application> appMap,
|
Map<Long, Application> appMap,
|
||||||
Map<Long, ExternalSystem> systemMap,
|
Map<Long, ExternalSystem> systemMap,
|
||||||
Map<Long, WorkflowDefinition> workflowMap
|
Map<Long, WorkflowDefinition> workflowMap,
|
||||||
|
Map<Long, DeployStatisticsDTO> statisticsMap,
|
||||||
|
Map<Long, DeployRecord> latestRecordMap,
|
||||||
|
Map<Long, List<DeployRecord>> recentRecordsMap
|
||||||
) {
|
) {
|
||||||
Application app = appMap.get(ta.getApplicationId());
|
Application app = appMap.get(ta.getApplicationId());
|
||||||
if (app == null) {
|
if (app == null) {
|
||||||
@ -416,9 +505,66 @@ public class DeployServiceImpl implements IDeployService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 部署统计信息和记录
|
||||||
|
DeployStatisticsDTO statistics = statisticsMap.get(ta.getId());
|
||||||
|
if (statistics != null) {
|
||||||
|
dto.setDeployStatistics(statistics);
|
||||||
|
|
||||||
|
// 判断是否正在部署中
|
||||||
|
DeployRecord latestRecord = latestRecordMap.get(ta.getId());
|
||||||
|
if (latestRecord != null) {
|
||||||
|
DeployRecordStatusEnums status = latestRecord.getStatus();
|
||||||
|
dto.setIsDeploying(status == DeployRecordStatusEnums.CREATED ||
|
||||||
|
status == DeployRecordStatusEnums.RUNNING);
|
||||||
|
} else {
|
||||||
|
dto.setIsDeploying(false);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// 没有部署记录,设置默认值
|
||||||
|
DeployStatisticsDTO emptyStats = new DeployStatisticsDTO();
|
||||||
|
emptyStats.setTotalCount(0L);
|
||||||
|
emptyStats.setSuccessCount(0L);
|
||||||
|
emptyStats.setFailedCount(0L);
|
||||||
|
emptyStats.setRunningCount(0L);
|
||||||
|
dto.setDeployStatistics(emptyStats);
|
||||||
|
dto.setIsDeploying(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 最近部署记录列表
|
||||||
|
List<DeployRecord> recentRecords = recentRecordsMap.getOrDefault(ta.getId(), Collections.emptyList());
|
||||||
|
List<DeployRecordSummaryDTO> recordSummaryList = recentRecords.stream()
|
||||||
|
.map(this::buildDeployRecordSummary)
|
||||||
|
.collect(toList());
|
||||||
|
dto.setRecentDeployRecords(recordSummaryList);
|
||||||
|
|
||||||
return dto;
|
return dto;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构建部署记录摘要DTO
|
||||||
|
*/
|
||||||
|
private DeployRecordSummaryDTO buildDeployRecordSummary(DeployRecord record) {
|
||||||
|
DeployRecordSummaryDTO summary = new DeployRecordSummaryDTO();
|
||||||
|
summary.setId(record.getId());
|
||||||
|
summary.setStatus(record.getStatus());
|
||||||
|
summary.setDeployBy(record.getDeployBy());
|
||||||
|
summary.setStartTime(record.getStartTime());
|
||||||
|
summary.setEndTime(record.getEndTime());
|
||||||
|
summary.setDeployRemark(record.getDeployRemark());
|
||||||
|
|
||||||
|
// 计算持续时间(毫秒)
|
||||||
|
if (record.getStartTime() != null && record.getEndTime() != null) {
|
||||||
|
long duration = java.time.Duration.between(record.getStartTime(), record.getEndTime()).toMillis();
|
||||||
|
summary.setDuration(duration);
|
||||||
|
} else if (record.getStartTime() != null) {
|
||||||
|
// 如果正在运行,计算到目前为止的持续时间
|
||||||
|
long duration = java.time.Duration.between(record.getStartTime(), LocalDateTime.now()).toMillis();
|
||||||
|
summary.setDuration(duration);
|
||||||
|
}
|
||||||
|
|
||||||
|
return summary;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Transactional
|
@Transactional
|
||||||
public DeployResultDTO executeDeploy(DeployRequestDTO request) {
|
public DeployResultDTO executeDeploy(DeployRequestDTO request) {
|
||||||
@ -483,7 +629,19 @@ public class DeployServiceImpl implements IDeployService {
|
|||||||
log.info("部署流程已启动: businessKey={}, workflowInstanceId={}, application={}, environment={}",
|
log.info("部署流程已启动: businessKey={}, workflowInstanceId={}, application={}, environment={}",
|
||||||
businessKey, workflowInstance.getId(), application.getAppCode(), environment.getEnvCode());
|
businessKey, workflowInstance.getId(), application.getAppCode(), environment.getEnvCode());
|
||||||
|
|
||||||
// 9. 返回结果
|
// 9. 创建部署记录(此时已有实例ID)
|
||||||
|
deployRecordService.createDeployRecord(
|
||||||
|
workflowInstance.getId(),
|
||||||
|
businessKey,
|
||||||
|
teamApp.getId(),
|
||||||
|
teamApp.getTeamId(),
|
||||||
|
teamApp.getApplicationId(),
|
||||||
|
teamApp.getEnvironmentId(),
|
||||||
|
SecurityUtils.getCurrentUsername(),
|
||||||
|
request.getRemark()
|
||||||
|
);
|
||||||
|
|
||||||
|
// 10. 返回结果
|
||||||
DeployResultDTO result = new DeployResultDTO();
|
DeployResultDTO result = new DeployResultDTO();
|
||||||
result.setWorkflowInstanceId(workflowInstance.getId());
|
result.setWorkflowInstanceId(workflowInstance.getId());
|
||||||
result.setBusinessKey(businessKey);
|
result.setBusinessKey(businessKey);
|
||||||
|
|||||||
@ -23,6 +23,9 @@ import com.qqchen.deploy.backend.workflow.dto.query.WorkflowHistoricalInstancesQ
|
|||||||
import com.qqchen.deploy.backend.workflow.repository.IWorkflowDefinitionRepository;
|
import com.qqchen.deploy.backend.workflow.repository.IWorkflowDefinitionRepository;
|
||||||
import com.qqchen.deploy.backend.workflow.repository.IWorkflowInstanceRepository;
|
import com.qqchen.deploy.backend.workflow.repository.IWorkflowInstanceRepository;
|
||||||
import com.qqchen.deploy.backend.workflow.repository.IWorkflowNodeInstanceRepository;
|
import com.qqchen.deploy.backend.workflow.repository.IWorkflowNodeInstanceRepository;
|
||||||
|
import com.qqchen.deploy.backend.workflow.repository.IWorkflowCategoryRepository;
|
||||||
|
import com.qqchen.deploy.backend.workflow.entity.WorkflowCategory;
|
||||||
|
import com.qqchen.deploy.backend.deploy.service.IDeployRecordService;
|
||||||
import com.qqchen.deploy.backend.workflow.service.IFormDataService;
|
import com.qqchen.deploy.backend.workflow.service.IFormDataService;
|
||||||
import com.qqchen.deploy.backend.workflow.service.IFormDefinitionService;
|
import com.qqchen.deploy.backend.workflow.service.IFormDefinitionService;
|
||||||
import com.qqchen.deploy.backend.workflow.service.IWorkflowInstanceService;
|
import com.qqchen.deploy.backend.workflow.service.IWorkflowInstanceService;
|
||||||
@ -86,13 +89,65 @@ public class WorkflowInstanceServiceImpl extends BaseServiceImpl<WorkflowInstanc
|
|||||||
@Resource
|
@Resource
|
||||||
private WorkflowNodeInstanceConverter workflowNodeInstanceConverter;
|
private WorkflowNodeInstanceConverter workflowNodeInstanceConverter;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private IDeployRecordService deployRecordService;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private IWorkflowCategoryRepository workflowCategoryRepository;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 部署分类编码常量
|
||||||
|
*/
|
||||||
|
private static final String DEPLOYMENT_CATEGORY_CODE = "DEPLOYMENT";
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public WorkflowInstance updateInstanceStatus(String processInstanceId, WorkflowInstanceStatusEnums status, LocalDateTime endTime) {
|
public WorkflowInstance updateInstanceStatus(String processInstanceId, WorkflowInstanceStatusEnums status, LocalDateTime endTime) {
|
||||||
WorkflowInstance instance = workflowInstanceRepository.findByProcessInstanceId(processInstanceId)
|
WorkflowInstance instance = workflowInstanceRepository.findByProcessInstanceId(processInstanceId)
|
||||||
.orElseThrow(() -> new RuntimeException("Workflow instance not found: " + processInstanceId));
|
.orElseThrow(() -> new RuntimeException("Workflow instance not found: " + processInstanceId));
|
||||||
instance.setStatus(status);
|
instance.setStatus(status);
|
||||||
instance.setEndTime(endTime);
|
instance.setEndTime(endTime);
|
||||||
return workflowInstanceRepository.save(instance);
|
WorkflowInstance saved = workflowInstanceRepository.save(instance);
|
||||||
|
|
||||||
|
// 同步部署记录状态(如果是部署类型的工作流)
|
||||||
|
try {
|
||||||
|
syncDeployRecordIfNeeded(saved, status);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("同步部署记录状态失败: workflowInstanceId={}, status={}",
|
||||||
|
saved.getId(), status, e);
|
||||||
|
// 不影响主流程,只记录错误
|
||||||
|
}
|
||||||
|
|
||||||
|
return saved;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 如果需要,同步部署记录状态
|
||||||
|
*/
|
||||||
|
private void syncDeployRecordIfNeeded(WorkflowInstance instance, WorkflowInstanceStatusEnums status) {
|
||||||
|
// 1. 查询工作流定义
|
||||||
|
WorkflowDefinition definition = workflowDefinitionRepository.findById(instance.getWorkflowDefinitionId())
|
||||||
|
.orElse(null);
|
||||||
|
|
||||||
|
if (definition == null || definition.getCategoryId() == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. 查询分类
|
||||||
|
WorkflowCategory category = workflowCategoryRepository.findById(definition.getCategoryId())
|
||||||
|
.orElse(null);
|
||||||
|
|
||||||
|
if (category == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. 判断是否是部署类型(通过分类code)
|
||||||
|
if (!DEPLOYMENT_CATEGORY_CODE.equals(category.getCode())) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 4. 同步部署记录状态
|
||||||
|
deployRecordService.syncStatusFromWorkflowInstance(instance, status);
|
||||||
|
log.debug("部署记录状态同步成功: workflowInstanceId={}, status={}", instance.getId(), status);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@ -1070,3 +1070,36 @@ CREATE TABLE deploy_server
|
|||||||
CONSTRAINT fk_server_category FOREIGN KEY (category_id) REFERENCES deploy_server_category (id)
|
CONSTRAINT fk_server_category FOREIGN KEY (category_id) REFERENCES deploy_server_category (id)
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='服务器管理表';
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='服务器管理表';
|
||||||
|
|
||||||
|
-- 部署记录表
|
||||||
|
CREATE TABLE deploy_record
|
||||||
|
(
|
||||||
|
id BIGINT AUTO_INCREMENT PRIMARY KEY COMMENT '主键ID',
|
||||||
|
create_by VARCHAR(100) NULL COMMENT '创建人',
|
||||||
|
create_time DATETIME(6) NULL COMMENT '创建时间',
|
||||||
|
update_by VARCHAR(100) NULL COMMENT '更新人',
|
||||||
|
update_time DATETIME(6) NULL COMMENT '更新时间',
|
||||||
|
version INT NOT NULL DEFAULT 1 COMMENT '版本号',
|
||||||
|
deleted BIT NOT NULL DEFAULT 0 COMMENT '是否删除',
|
||||||
|
|
||||||
|
workflow_instance_id BIGINT NOT NULL COMMENT '工作流实例ID(关联workflow_instance)',
|
||||||
|
business_key VARCHAR(64) NOT NULL COMMENT '业务标识(UUID)',
|
||||||
|
team_application_id BIGINT NOT NULL COMMENT '团队应用配置ID(关联deploy_team_application)',
|
||||||
|
team_id BIGINT NOT NULL COMMENT '团队ID',
|
||||||
|
application_id BIGINT NOT NULL COMMENT '应用ID',
|
||||||
|
environment_id BIGINT NOT NULL COMMENT '环境ID',
|
||||||
|
deploy_by VARCHAR(50) NULL COMMENT '部署人',
|
||||||
|
deploy_remark VARCHAR(500) NULL COMMENT '部署备注',
|
||||||
|
status VARCHAR(20) NOT NULL COMMENT '部署状态(CREATED/RUNNING/SUCCESS/FAILED等)',
|
||||||
|
start_time DATETIME(6) NULL COMMENT '开始时间',
|
||||||
|
end_time DATETIME(6) NULL COMMENT '结束时间',
|
||||||
|
|
||||||
|
UNIQUE INDEX uk_workflow_instance (workflow_instance_id),
|
||||||
|
INDEX idx_team_application (team_application_id),
|
||||||
|
INDEX idx_application (application_id),
|
||||||
|
INDEX idx_environment (environment_id),
|
||||||
|
INDEX idx_status (status),
|
||||||
|
INDEX idx_start_time (start_time),
|
||||||
|
CONSTRAINT fk_deploy_record_instance FOREIGN KEY (workflow_instance_id) REFERENCES workflow_instance (id),
|
||||||
|
CONSTRAINT fk_deploy_record_team_app FOREIGN KEY (team_application_id) REFERENCES deploy_team_application (id)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='部署记录表';
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user