203 lines
5.8 KiB
Markdown
203 lines
5.8 KiB
Markdown
# 部署记录状态:CANCELLED vs REJECTED 分析
|
||
|
||
## 当前状态
|
||
|
||
### CANCELLED(已取消)的使用场景
|
||
|
||
**唯一使用场景**:审批被拒绝
|
||
- 位置:`DeployRecordServiceImpl.updateStatusFromApproval()`
|
||
- 代码:`record.setStatus(DeployRecordStatusEnums.CANCELLED);`
|
||
- 日志:`"部署记录状态已更新为已取消(审批被拒)"`
|
||
|
||
**结论**:当前 `CANCELLED` 只用于审批被拒绝的场景。
|
||
|
||
### 其他状态的使用场景
|
||
|
||
| 状态 | 使用场景 | 来源 |
|
||
|------|---------|------|
|
||
| **TERMINATED** | 工作流被手动终止 | 工作流状态 `TERMINATED` |
|
||
| **FAILED** | 工作流执行失败 | 工作流状态 `FAILED` |
|
||
| **CANCELLED** | 审批被拒绝 | 审批事件 `ApprovalResultEnum.REJECTED` |
|
||
|
||
## 问题分析
|
||
|
||
### 问题1:语义不清晰
|
||
|
||
**当前问题**:
|
||
- `CANCELLED`(已取消)语义模糊,不能明确表示是"审批被拒绝"
|
||
- 未来如果有手动取消部署功能,会产生歧义
|
||
|
||
**对比**:
|
||
- 工作流层面:`ApprovalResultEnum.REJECTED`(拒绝)
|
||
- 部署记录层面:`CANCELLED`(已取消)
|
||
- **不一致**:两个层面使用不同的语义
|
||
|
||
### 问题2:未来扩展性
|
||
|
||
**未来可能的场景**:
|
||
1. **手动取消部署**:用户主动取消正在运行的部署
|
||
- 应该使用什么状态?如果用 `CANCELLED`,会与"审批被拒绝"混淆
|
||
2. **超时自动取消**:部署超时自动取消
|
||
- 应该使用什么状态?
|
||
|
||
## 方案对比
|
||
|
||
### 方案A:保留 CANCELLED,新增 REJECTED(推荐)
|
||
|
||
**状态定义**:
|
||
```java
|
||
public enum DeployRecordStatusEnums {
|
||
// ... 其他状态 ...
|
||
|
||
/**
|
||
* 审批被拒绝(终态)
|
||
*/
|
||
REJECTED("REJECTED", "审批被拒绝"),
|
||
|
||
/**
|
||
* 已取消(终态)
|
||
* 用于:手动取消部署、超时自动取消等场景
|
||
*/
|
||
CANCELLED("CANCELLED", "已取消"),
|
||
|
||
// ... 其他状态 ...
|
||
}
|
||
```
|
||
|
||
**优点**:
|
||
1. ✅ 语义清晰:`REJECTED` 明确表示"审批被拒绝"
|
||
2. ✅ 与工作流层面保持一致:`ApprovalResultEnum.REJECTED` → `DeployRecordStatusEnums.REJECTED`
|
||
3. ✅ 保留扩展性:`CANCELLED` 可用于未来手动取消场景
|
||
4. ✅ 状态语义明确,便于理解和维护
|
||
|
||
**缺点**:
|
||
- 需要新增枚举值
|
||
- 需要修改相关代码
|
||
- 需要数据库迁移(如果已有数据)
|
||
|
||
**需要修改的地方**:
|
||
1. 枚举类:新增 `REJECTED`
|
||
2. `DeployRecordServiceImpl.updateStatusFromApproval()`:改为 `REJECTED`
|
||
3. `isFinalState()`:添加 `REJECTED`
|
||
4. 统计查询:`REJECTED` 计入失败计数
|
||
5. `fromWorkflowStatus()`:不需要修改(因为 `REJECTED` 不是从工作流状态转换来的)
|
||
|
||
### 方案B:直接用 REJECTED 替代 CANCELLED
|
||
|
||
**状态定义**:
|
||
```java
|
||
public enum DeployRecordStatusEnums {
|
||
// ... 其他状态 ...
|
||
|
||
/**
|
||
* 审批被拒绝(终态)
|
||
*/
|
||
REJECTED("REJECTED", "审批被拒绝"),
|
||
|
||
// 删除 CANCELLED
|
||
}
|
||
```
|
||
|
||
**优点**:
|
||
1. ✅ 语义清晰
|
||
2. ✅ 与工作流层面保持一致
|
||
3. ✅ 简化状态模型
|
||
|
||
**缺点**:
|
||
1. ❌ 失去扩展性:如果未来需要手动取消功能,需要再添加状态
|
||
2. ❌ 如果未来需要区分"审批被拒绝"和"手动取消",需要再次修改
|
||
|
||
### 方案C:保持现状(不推荐)
|
||
|
||
**优点**:
|
||
- 无需修改代码
|
||
|
||
**缺点**:
|
||
1. ❌ 语义不清晰
|
||
2. ❌ 与工作流层面不一致
|
||
3. ❌ 未来扩展困难
|
||
|
||
## 推荐方案
|
||
|
||
**推荐采用方案A:保留 CANCELLED,新增 REJECTED**
|
||
|
||
### 理由
|
||
|
||
1. **语义清晰**:
|
||
- `REJECTED`:明确表示"审批被拒绝"
|
||
- `CANCELLED`:用于"手动取消"等场景
|
||
|
||
2. **状态映射清晰**:
|
||
```
|
||
审批层面:ApprovalResultEnum.REJECTED
|
||
↓
|
||
部署记录:DeployRecordStatusEnums.REJECTED
|
||
```
|
||
|
||
3. **未来扩展性**:
|
||
- 如果未来需要手动取消部署功能,可以直接使用 `CANCELLED`
|
||
- 如果不需要手动取消,`CANCELLED` 可以保留但不用
|
||
|
||
4. **状态完整性**:
|
||
- 终态包括:`SUCCESS`、`FAILED`、`REJECTED`、`CANCELLED`、`TERMINATED`、`PARTIAL_SUCCESS`
|
||
- 语义清晰,便于理解和维护
|
||
|
||
## 实施建议
|
||
|
||
### 步骤1:新增 REJECTED 枚举
|
||
|
||
```java
|
||
/**
|
||
* 审批被拒绝(终态)
|
||
*/
|
||
REJECTED("REJECTED", "审批被拒绝"),
|
||
```
|
||
|
||
### 步骤2:修改审批状态更新逻辑
|
||
|
||
```java
|
||
} else {
|
||
// 审批被拒绝,更新为审批被拒绝
|
||
record.setStatus(DeployRecordStatusEnums.REJECTED);
|
||
log.info("部署记录状态已更新为审批被拒绝: id={}, workflowInstanceId={}",
|
||
record.getId(), workflowInstanceId);
|
||
}
|
||
```
|
||
|
||
### 步骤3:更新终态判断
|
||
|
||
```java
|
||
private boolean isFinalState(DeployRecordStatusEnums status) {
|
||
return status == DeployRecordStatusEnums.SUCCESS
|
||
|| status == DeployRecordStatusEnums.FAILED
|
||
|| status == DeployRecordStatusEnums.REJECTED // 新增
|
||
|| status == DeployRecordStatusEnums.CANCELLED
|
||
|| status == DeployRecordStatusEnums.TERMINATED
|
||
|| status == DeployRecordStatusEnums.PARTIAL_SUCCESS;
|
||
}
|
||
```
|
||
|
||
### 步骤4:更新统计查询
|
||
|
||
```sql
|
||
-- 在统计查询中,REJECTED 计入失败
|
||
SUM(CASE WHEN dr.status IN ('FAILED', 'REJECTED', 'CANCELLED', 'TERMINATED', 'PARTIAL_SUCCESS')
|
||
OR (dr.status = 'CREATED' AND TIMESTAMPDIFF(MINUTE, dr.create_time, NOW()) > 30)
|
||
THEN 1 ELSE 0 END) as failedCount
|
||
```
|
||
|
||
### 步骤5:数据库迁移(可选)
|
||
|
||
如果已有审批被拒绝的记录,状态为 `CANCELLED`,可以考虑:
|
||
- 保留现有数据(`CANCELLED` 继续表示审批被拒绝)
|
||
- 或者迁移数据(将 `CANCELLED` 迁移为 `REJECTED`)
|
||
|
||
## 结论
|
||
|
||
**推荐新增 `REJECTED` 状态**,用于明确表示"审批被拒绝",与工作流层面的 `ApprovalResultEnum.REJECTED` 保持一致。
|
||
|
||
**保留 `CANCELLED` 状态**,用于未来可能的手动取消部署功能。
|
||
|
||
这样既保证了语义清晰,又保留了扩展性。
|
||
|