From 32d5e45df03f0b7f848abef8c6708be5c356f987 Mon Sep 17 00:00:00 2001 From: xuans Date: Wed, 30 Sep 2026 05:21:47 +0800 Subject: [PATCH] =?UTF-8?q?=E8=A1=A5=E9=BD=90P0-10=E6=B4=BB=E5=8A=A8?= =?UTF-8?q?=E4=BB=BB=E5=8A=A1=E5=8F=96=E6=B6=88=E5=85=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/internal/httpapi/task_api.go | 11 +++++- .../httpapi/workflow_task_cancel_test.go | 37 +++++++++++++++++++ doc/Scert开发任务清单.md | 20 ++++++++++ doc/Scert整改任务执行清单.md | 18 +++++++++ doc/Scert整改合并优化清单.md | 24 ++++++++++++ doc/基础整改任务规格.md | 18 +++++++++ 6 files changed, 127 insertions(+), 1 deletion(-) diff --git a/backend/internal/httpapi/task_api.go b/backend/internal/httpapi/task_api.go index faa4ed8..702ad20 100644 --- a/backend/internal/httpapi/task_api.go +++ b/backend/internal/httpapi/task_api.go @@ -311,7 +311,7 @@ func (s *Server) cancelTask(c *gin.Context) { s.writeError(c, http.StatusInternalServerError, "读取任务失败", err) return } - if item.Status != "queued" && item.Status != "running" { + if !isCancellableTaskStatus(item.Status) { c.JSON(http.StatusConflict, gin.H{"error": "任务当前无法取消", "task": item}) return } @@ -442,6 +442,15 @@ func isActiveTaskStatus(status string) bool { } } +func isCancellableTaskStatus(status string) bool { + switch status { + case "queued", "running", "retry_wait", "cancelling": + return true + default: + return false + } +} + func (s *Server) listTasks(c *gin.Context) { reader, ok := s.projectTaskReader(c) if !ok { diff --git a/backend/internal/httpapi/workflow_task_cancel_test.go b/backend/internal/httpapi/workflow_task_cancel_test.go index c0dc2f2..5146a5d 100644 --- a/backend/internal/httpapi/workflow_task_cancel_test.go +++ b/backend/internal/httpapi/workflow_task_cancel_test.go @@ -36,6 +36,43 @@ func TestTaskAPICancelsTrackedCertificateWorkflowTask(t *testing.T) { } } +func TestTaskAPICanCancelRetryWaitAndCancellingTasks(t *testing.T) { + for _, status := range []string{"retry_wait", "cancelling"} { + t.Run(status, func(t *testing.T) { + server, tasks, _, closeDB := newTaskAPITestServer(t, nil) + defer closeDB() + started := time.Now().UTC().Add(-time.Minute) + item := repository.Task{ + ID: "cancel-" + status, DomainID: "domain-1", + HistoryScope: repository.HistoryScope{ScopeType: repository.ScopeProject, ProjectID: domain.DefaultProjectID}, + TaskType: "certificate_deploy", Status: status, Stage: "certificate_deploy", + StartedAt: &started, + } + if err := tasks.CreateTask(t.Context(), item); err != nil { + t.Fatal(err) + } + attempt := repository.TaskAttempt{ + ID: "attempt-" + status, TaskID: item.ID, AttemptNumber: 1, + Stage: item.Stage, Status: status, Message: "等待执行", StartedAt: &started, CreatedAt: started, + } + if err := tasks.CreateAttempt(t.Context(), attempt); err != nil { + t.Fatal(err) + } + + response := httptest.NewRecorder() + serveAdminHTTP(server, response, httptest.NewRequest(http.MethodDelete, "/api/v1/tasks/"+item.ID, nil)) + stored, err := tasks.GetTask(t.Context(), item.ID) + if response.Code != http.StatusOK || err != nil || stored.Status != "cancelled" { + t.Fatalf("%s 任务未能取消:%d %+v %v", status, response.Code, stored, err) + } + attempts, err := tasks.ListAttempts(t.Context(), item.ID) + if err != nil || len(attempts) != 1 || attempts[0].Status != "cancelled" { + t.Fatalf("%s 任务尝试状态未同步取消:%+v %v", status, attempts, err) + } + }) + } +} + func TestTaskAPICannotFalselyCancelWorkflowTasks(t *testing.T) { for _, kind := range []string{"renewal_run"} { t.Run(kind, func(t *testing.T) { diff --git a/doc/Scert开发任务清单.md b/doc/Scert开发任务清单.md index 71165c8..070b43a 100644 --- a/doc/Scert开发任务清单.md +++ b/doc/Scert开发任务清单.md @@ -3629,6 +3629,17 @@ Linux Ubuntu 22.04 上的 `Scert-admin` 手动启停、无开机自启动、无 - [~] 进行中:P0-10 的 DNS 验证、批量部署结果、其他入口任务事务链、重试幂等及跨数据库实机验证仍需继续审查。 - [ ] 未开始:P0-12 备份恢复、浏览器清缓存、密码 SSH、远端部署和最终生产门禁仍未执行。 - [!] 总体验收不得升级:当前仍处于 **P0-03 完成,待复审**,本轮没有新增 `[✓]` 复审通过项。 + +## 本轮开发进度(2026-09-29,P0-10 任务取消入口) + +总体验收继续保持 **P0-03:完成,待复审**。本轮只补齐开发阶段的任务取消状态边界。 + +- [x] 任务取消入口已支持 `queued`、`running`、`retry_wait`、`cancelling` 四种活动状态。 +- [x] 已补充任务与任务尝试同步变更为 `cancelled` 的 HTTP 回归测试。 +- [x] `go test ./...`、`go vet ./...`、`git diff --check` 通过。 +- [~] P0-10 其余任务入口、任务尝试完整矩阵、跨数据库实机矩阵和统一复审继续进行。 +- [ ] P0-12 备份恢复、浏览器、密码 SSH、远端部署和最终生产门禁尚未完成。 +- [!] 不得将本地自动化结果标记为生产验收通过;总体验收仍为 **P0-03 完成,待复审**。 ## 最新执行摘要(2026-09-29 继续开发) 总体验收位置继续保持 **P0-03 完成,待复审**。本轮完成开发阶段的证书任务并发保护、DNS 验证阶段进度记录,以及域名与服务器双向多对多部署关联的回归核验;不代表生产部署验收通过。 @@ -3661,3 +3672,12 @@ Linux Ubuntu 22.04 上的 `Scert-admin` 手动启停、无开机自启动、无 - [~] 进行中:远端数据库当前为空,现场只有一台可用测试服务器,尚未用虚构数据替代第二台真实服务器;双向多对多的生产数据关联、实际证书推送和回滚仍需具备真实目标后复核。 - [~] 进行中:三数据库生产矩阵、真实 DNS/ACME 申请、真实多服务器证书推送、最终生产门禁仍需继续执行。 - [!] 总体验收不得升级:当前仍为 **P0-03 完成,待复审**,本轮没有新增 `[✓]` 复审通过项。 + +## 最新进度追加(2026-09-29,P0-10 任务取消入口) + +- [x] 任务取消入口已与仓储层统一,支持 `queued`、`running`、`retry_wait`、`cancelling` 四种活动状态。 +- [x] 已补充任务和任务尝试同步取消的 HTTP 回归测试;管理证书和自动续期任务仍禁止通用取消。 +- [x] `go test ./...`、`go vet ./...`、`git diff --check` 通过。 +- [~] P0-10 其他任务入口、任务尝试矩阵、跨数据库实机矩阵和统一复审继续进行。 +- [ ] P0-12 备份恢复、浏览器、密码 SSH、远端部署和最终生产门禁尚未完成。 +- [!] 总体验收继续保持 **P0-03:完成,待复审**,不得将本地自动化结果标记为生产验收通过。 diff --git a/doc/Scert整改任务执行清单.md b/doc/Scert整改任务执行清单.md index 5be1d53..4b88e94 100644 --- a/doc/Scert整改任务执行清单.md +++ b/doc/Scert整改任务执行清单.md @@ -935,6 +935,15 @@ P0-05 从 `[!]` 调整为 `[~]`,并未标记完成;P0-04 剩余门禁和全 - [~] 进行中:P0-10 的 DNS 验证、批量部署结果、其他入口任务事务链、重试幂等及跨数据库实机验证仍需继续审查。 - [ ] 未开始:P0-12 备份恢复、浏览器清缓存、密码 SSH、远端部署和最终生产门禁仍未执行。 - [!] 总体验收不得升级:当前仍处于 **P0-03 完成,待复审**,本轮没有新增 `[✓]` 复审通过项。 + +## 本轮执行记录(2026-09-29,P0-10 任务取消入口) + +- [x] 已完成,等待复审:修正 HTTP 任务取消入口,使其与仓储层支持的四种活动状态保持一致。 +- [x] 已完成,等待复审:覆盖 `retry_wait`、`cancelling` 的任务及任务尝试取消回归;管理证书和自动续期任务继续拒绝通用取消。 +- [x] 已完成,等待复审:后端定向测试、全量测试、静态检查和差异检查通过。 +- [~] 进行中:P0-10 仍需继续审查其他任务入口、重试、幂等、恢复和跨数据库行为。 +- [ ] 未开始:P0-12 备份恢复以及最终生产流程门禁。 +- [!] 总体验收保持 **P0-03:完成,待复审**,没有新增 `[✓]`。 ## 最新执行摘要(2026-09-29 继续开发) 总体验收位置继续保持 **P0-03 完成,待复审**。本轮完成开发阶段的证书任务并发保护、DNS 验证阶段进度记录,以及域名与服务器双向多对多部署关联的回归核验;不代表生产部署验收通过。 @@ -967,3 +976,12 @@ P0-05 从 `[!]` 调整为 `[~]`,并未标记完成;P0-04 剩余门禁和全 - [~] 进行中:远端数据库当前为空,现场只有一台可用测试服务器,尚未用虚构数据替代第二台真实服务器;双向多对多的生产数据关联、实际证书推送和回滚仍需具备真实目标后复核。 - [~] 进行中:三数据库生产矩阵、真实 DNS/ACME 申请、真实多服务器证书推送、最终生产门禁仍需继续执行。 - [!] 总体验收不得升级:当前仍为 **P0-03 完成,待复审**,本轮没有新增 `[✓]` 复审通过项。 + +## 最新执行记录(2026-09-29,P0-10 任务取消入口) + +- [x] 已完成,等待复审:HTTP 任务取消入口已支持仓储层定义的四种活动状态。 +- [x] 已完成,等待复审:覆盖 `retry_wait`、`cancelling` 的任务和任务尝试取消回归;自动续期和管理证书任务仍由工作流控制。 +- [x] 已完成,等待复审:后端定向测试、全量测试、静态检查和差异检查通过。 +- [~] 进行中:P0-10 仍需继续审查其他任务入口、重试、幂等、恢复和跨数据库行为。 +- [ ] 未开始:P0-12 备份恢复以及最终生产流程门禁。 +- [!] 总体验收保持 **P0-03:完成,待复审**,没有新增 `[✓]`。 diff --git a/doc/Scert整改合并优化清单.md b/doc/Scert整改合并优化清单.md index af5ac7d..d4c09c0 100644 --- a/doc/Scert整改合并优化清单.md +++ b/doc/Scert整改合并优化清单.md @@ -1560,6 +1560,18 @@ P0-11 生产验收门禁 - [ ] 未开始:P0-12 备份恢复、三数据库实库矩阵、浏览器清缓存、密码 SSH、远端部署、HTTPS/DNS/ACME、Linux/Windows 服务和最终生产门禁。 - [!] 总体验收不得升级:当前仍为 **P0-03 完成,待复审**,本轮没有新增 `[✓]` 复审通过项。 +## 本轮开发进度(2026-09-29,P0-10 任务取消入口) + +总体验收位置继续保持 **P0-03:完成,待复审**;本轮仅补齐任务取消入口与任务状态模型的开发缺口,不代表 P0-10 整项复审通过,也不代表生产部署验收通过。 + +- [x] 已完成,等待复审:任务取消 HTTP 入口与仓储层状态范围统一,支持 `queued`、`running`、`retry_wait`、`cancelling` 四种活动状态。 +- [x] 已完成,等待复审:新增 `retry_wait`、`cancelling` 任务及任务尝试的取消回归测试,确认任务和当前任务尝试均转为 `cancelled`。 +- [x] 已完成,等待复审:管理证书续期和自动续期任务仍由工作流控制,继续拒绝通过通用任务接口直接取消。 +- [x] 已完成,等待复审:定向 HTTP 测试、后端全量 `go test ./...`、`go vet ./...` 和 `git diff --check` 均通过。 +- [~] 进行中:P0-10 其余任务入口、三数据库实机矩阵、崩溃恢复复核和统一复审仍需继续执行。 +- [ ] 未开始:P0-12 备份恢复、最终浏览器清缓存、密码 SSH、远端部署和生产门禁仍未完成。 +- [!] 总体验收不得升级:当前仍为 **P0-03 完成,待复审**,本轮没有新增 `[✓]` 复审通过项。 + 本轮下一步继续审查任务中心剩余入口和备份恢复;开发阶段收尾后,再统一执行生产构建、实机部署和验收。 ## 本轮开发补充(2026-09-29) @@ -1608,3 +1620,15 @@ P0-11 生产验收门禁 - [~] 进行中:远端数据库当前为空,现场只有一台可用测试服务器,尚未用虚构数据替代第二台真实服务器;双向多对多的生产数据关联、实际证书推送和回滚仍需具备真实目标后复核。 - [~] 进行中:三数据库生产矩阵、真实 DNS/ACME 申请、真实多服务器证书推送、最终生产门禁仍需继续执行。 - [!] 总体验收不得升级:当前仍为 **P0-03 完成,待复审**,本轮没有新增 `[✓]` 复审通过项。 + +## 最新进度追加(2026-09-29,P0-10 任务取消入口) + +总体验收位置继续保持 **P0-03:完成,待复审**;本轮仅补齐任务取消入口与状态模型的一致性,不代表整项复审通过或生产部署验收通过。 + +- [x] 已完成,等待复审:任务取消入口支持 `queued`、`running`、`retry_wait`、`cancelling` 四种活动状态。 +- [x] 已完成,等待复审:新增 `retry_wait`、`cancelling` 任务及任务尝试取消回归,确认任务和活动尝试均进入 `cancelled`。 +- [x] 已完成,等待复审:管理证书续期和自动续期任务仍由工作流控制,通用任务接口继续拒绝直接取消。 +- [x] 已完成,等待复审:定向测试、后端全量 `go test ./...`、`go vet ./...` 和 `git diff --check` 均通过。 +- [~] 进行中:P0-10 其余任务入口、跨数据库实机矩阵、崩溃恢复复核和统一复审仍需继续。 +- [ ] 未开始:P0-12 备份恢复、最终浏览器清缓存、密码 SSH、远端部署和生产门禁仍未完成。 +- [!] 总体验收不得升级,当前仍为 **P0-03 完成,待复审**,没有新增 `[✓]` 复审通过项。 diff --git a/doc/基础整改任务规格.md b/doc/基础整改任务规格.md index 1a63195..02e9013 100644 --- a/doc/基础整改任务规格.md +++ b/doc/基础整改任务规格.md @@ -511,6 +511,15 @@ P0-06 与 P0-07 均维持 `[~]`,六阶段中的隔离、生产和最终验收 - [~] 进行中:P0-10 的 DNS 验证、批量部署结果、其他入口任务事务链、重试幂等及跨数据库实机验证仍需继续审查。 - [ ] 未开始:P0-12 备份恢复、浏览器清缓存、密码 SSH、远端部署和最终生产门禁仍未执行。 - [!] 总体验收不得升级:当前仍处于 **P0-03 完成,待复审**,本轮没有新增 `[✓]` 复审通过项。 + +## 最新开发证据(2026-09-29,P0-10) + +- [x] 任务取消入口现在统一接受 `queued`、`running`、`retry_wait`、`cancelling` 活动状态。 +- [x] 任务取消事务会同步结束对应的活动任务尝试;管理证书和自动续期任务不受通用取消入口控制。 +- [x] 已通过后端全量测试、静态检查和差异检查。 +- [~] P0-10 其他任务链与三数据库实机复核仍在进行。 +- [ ] P0-12 备份恢复及最终生产门禁尚未开始。 +- [!] 总体验收不得升级,仍为 **P0-03:完成,待复审**。 ## 最新执行摘要(2026-09-29 继续开发) 总体验收位置继续保持 **P0-03 完成,待复审**。本轮完成开发阶段的证书任务并发保护、DNS 验证阶段进度记录,以及域名与服务器双向多对多部署关联的回归核验;不代表生产部署验收通过。 @@ -545,3 +554,12 @@ P0-06 与 P0-07 均维持 `[~]`,六阶段中的隔离、生产和最终验收 - [~] 进行中:远端数据库当前为空,现场只有一台可用测试服务器,尚未用虚构数据替代第二台真实服务器;双向多对多的生产数据关联、实际证书推送和回滚仍需具备真实目标后复核。 - [~] 进行中:三数据库生产矩阵、真实 DNS/ACME 申请、真实多服务器证书推送、最终生产门禁仍需继续执行。 - [!] 总体验收不得升级:当前仍为 **P0-03 完成,待复审**,本轮没有新增 `[✓]` 复审通过项。 + +## 最新进度追加(2026-09-29,P0-10 任务取消入口) + +- [x] 任务取消入口统一接受 `queued`、`running`、`retry_wait`、`cancelling` 活动状态。 +- [x] 任务取消事务同步结束对应活动任务尝试;管理证书和自动续期任务不受通用取消入口控制。 +- [x] 已通过后端全量测试、静态检查和差异检查。 +- [~] P0-10 其他任务链与三数据库实机复核仍在进行。 +- [ ] P0-12 备份恢复及最终生产门禁尚未开始。 +- [!] 总体验收不得升级,仍为 **P0-03:完成,待复审**。