Files
orbit/docs/reports/phase-3-cancellation.md

105 lines
7.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# P3 取消与无外键回归记录
验证日期:2026-09-17。本阶段交付任务取消闭环,并落实用户要求的无数据库外键设计。P3 配额/背压、可靠订阅及 P4–P7 仍未完成;持续目标保持进行中。
## 1. 已实现行为
- WAITING、LEASED、RUNNING、NEEDS_REVIEW 的取消控制,动作与队列授权、CAS、稳定幂等身份、取消事件及审计同事务提交。
- 开始前取消阻止 Start 并释放许可;运行中只保存意图、返回 HTTP 202,不提前释放许可或伪造完成。
- 取消后不延长期限、不产生后续重试;有效成功结果仍能确认,普通取消错误或失联保持未知效果。
- 明确取消结果使用 task.finish / CANCELLED;本次确认停止不能清除此前未核实的外部效果。
- 可选择的 task.cancel 通知、Resume/Start/Renew 中的当前取消意图、独立 SDK 自动停止处理器和有界收尾。
- [完整取消场景](../../examples/cancellation/main.go)、[接口与升级说明](../api/cancellation.md) 已同步交付。
- 迁移 000007 扩展取消证据;000008 移除 70 个历史外键,保留索引、唯一约束、CHECK、触发器和数据。实体数仍为 32,没有新增持久化字段。
- 开发规范明确禁止再引入外键。应用启动/readiness 核验迁移及零外键要求;任务、计划及 Worker 关联由服务端事务校验。
## 2. 环境、命令及结果
macOS 本机、Go 1.27.1、Docker 单实例 MySQL 8.4.10。完整集成使用一次性数据库、随机凭据及回环端口;测试结束删除容器,没有修改已有业务库。
```sh
make fmt test vet build
make integration
go test -race ./internal/transport/httpserver -run '^TestWorkerPublishedContract$'
cd sdk/go
GOWORK=off go test -race ./...
GOWORK=off go vet ./...
```
上述检查均通过。普通单元运行未配置集成环境时会跳过数据库/外部进程用例,真实证据来自完整 integration。
| 测试组 | 本轮实际结果 |
| --- | --- |
| MySQL 全部集成 | PASS,52.851 秒 |
| 历史 v7 → 当前无外键升级 | PASS,3.99 秒 |
| 无外键条件下的资源归属校验 | PASS,0.08 秒 |
| 取消事务、恢复及竞争 | PASS,2.89 秒 |
| SDK Worker 连接与运行器全部集成 | PASS,78.267 秒 |
| 其中自动取消六种故障/结果场景 | PASS,15.51 秒 |
| SDK 计划生命周期 | PASS,含包开销 4.586 秒 |
| 真实进程故障组 | PASS,21.500 秒 |
| 八个完整示例 | health / tasks / worker-protocol / worker / history / retry / schedules / cancellation 全部通过 |
上述耗时是单次测试用时,不是性能或容量指标。
## 3. 零外键与关联校验证据
[无外键集成用例](../../internal/storage/mysql/no_foreign_keys_integration_test.go) 在独立库重建真实 v7,再使用正式 Migrate 入口升级:
- information_schema 中外键从 70 变为 0,新建完整结构也断言外键为 0。
- 升级前后的全部 325 条索引列定义完全一致,包含索引名、唯一性、列顺序、前缀、类型及可见性。
- 预置任务的所有字段逐一核对不变,包括大整数参数、状态、版本、策略和时间;再次执行迁移成功。
- 仅在一次性测试库故意添加违规外键,验证 CheckSchema 拒绝;移除后恢复通过。这是漂移注入测试,正常迁移与服务不创建该测试外键。
- 对不存在的队列及另一命名空间队列,任务提交、计划创建、Worker 注册均返回 NOT_FOUND;无残留任务、计划、幂等记录或新 Worker 会话。
- 会话的父进程关系被故意改坏后,控制请求返回 STALE_SESSION,不能借用错误关联继续消费。
Worker 注册补充了事务内队列存在性检查;会话使用核验进程、凭据及代次。已有任务、计划和执行事务保留其命名空间、父资源与尝试身份校验。
历史迁移文件保留原校验和,通过 000008 前向移除外键;新装也运行至当前版本。取消/恢复不再取得为历史外键检查准备的会话共享锁,使用队列 → 任务 → 尝试 → 许可的锁顺序。此前开始/取消竞争曾因隐式外键锁发生死锁,本轮在无外键结构上通过该竞争用例;这不表示所有负载下不存在其他锁竞争。
应用校验不能防止绕过服务的直接 SQL 错写。当前无公开硬删除,后续清理及流程/订阅引擎必须遵守 [关联与保留规则](../07-data-model.md)。
## 4. 取消事务证据
[数据库用例](../../internal/storage/mysql/worker_cancel_integration_test.go) 覆盖:
- LEASED 取消后禁止 Start,许可只释放一次,迟到成功仅作为证据。
- RUNNING 收到取消时保持任务/尝试运行及许可;有效成功、失败、未知、确认取消分别按真实结果处理,不创建重试。
- 旧 Start ACK 保留原回执,同时带当前取消意图;取消后 Renew 不延长期限。
- 新节点会话隔离旧连接,Resume 后取消意图仍存在;原取消请求在任务最终完成后重报,仍返回原 RUNNING 快照。
- 先前未知效果不能被后一次确认取消抹掉;无取消意图的 CANCELLED 报告被拒绝。
- 测试触发器使审计写入失败,取消意图和版本整体回滚;解除故障后可用原身份重试。
- 已取消的授权尝试到期进入核查,迟到取消结果只保存证据。
- 12 次并发 Start/Cancel:取消获胜阻止开始,Start 获胜使旧版本取消冲突,随后可按新版本记录运行中意图。
## 5. SDK 与故障证据
[SDK 真实服务用例](../../sdk/go/worker_cancel_integration_test.go) 覆盖六种情况:
1. 明确确认停止,丢失 Finish ACK 后原结果重报,最终 CANCELLED 且一次尝试。
2. 普通 context 错误返回 UNKNOWN,任务进入 NEEDS_REVIEW。
3. 取消后仍取得真实成功结果,成功和精确整数保留。
4. 丢失取消通知并断开连接,重连 Resume 仍能停止原处理器。
5. Start ACK 丢失且暂时断网,取消后重连,处理器调用次数为 0。
6. 处理器不配合取消,任务到期核查,Run 在 ShutdownTimeout 后返回未收尾错误,不能假称已排空。
协议 Schema 与实际解析共同验证可选 Hello 字段、取消通知、当前 Lease 意图、CANCELLED 结果和 retryable 分类。低层 SDK 验证通知读取、取消等待不关闭连接,以及带取消意图的 Lease 不提供继续执行权。
完整取消示例实际输出:
```text
task=<独立任务ID> cancel_requested=true accepted_state=RUNNING
final_state=CANCELLED attempts=1
worker_drained=true running=0
```
原有 WSS、安全重试、计划调度及真实进程故障回归同步通过;进程组包括 ACK 丢失后节点接管、Worker 强杀后未知核查、调度强杀与服务间隙后的两节点补跑。
## 6. 当前边界与后续
- 取消要求业务遵守 context;不能强杀 goroutine,也不能撤回外部已经发生的副作用。普通错误不证明停止成功。
- 取消通知是有界提示,持久化意图和结果才是权威。服务端取消扫描每批最多 256 项,SDK 未读通知最多 32 条。
- 先停旧服务、应用全部迁移、启动新版服务,再升级自动 SDK;没有宣称通过混合版本滚动升级验收。
- 本次验证单数据库及本机进程故障,未验证数据库复制切换、跨故障域网络分区、大表在线 DDL、备份恢复或百万租户吞吐。
- 后续继续 P3 配额/背压与可靠订阅,随后推进 Weave。当前没有把取消闭环或无外键改造等同于最终生产交付。