Files
orbit/docs/reports/phase-3-task-outbox.md

78 lines
7.7 KiB
Markdown
Raw Permalink 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 业务事务 Outbox 回归
验证日期:2026-09-17。独立业务示例、发送恢复、CLI和接入文档已实现;定向真实数据库、全量链路及最终输入边界补充回归均已正常退出,状态码0。P3最终范围核对、Weave及生产部署验收继续按计划推进。
## 1. 实现证据
- [独立模块](../../examples/task-outbox/README.md)只依赖独立Orbit SDK与业务侧MySQL驱动,核心SDK没有新增依赖。
- [模型](../../examples/task-outbox/internal/outbox/model.go)与[建表](../../examples/task-outbox/internal/outbox/schema.sql):2个业务实体、22个Go/SQL中文注释字段,零外键;不改变平台35个实体和289个持久化字段。
- [业务事务](../../examples/task-outbox/internal/outbox/store.go):业务操作与待发命令原子创建,稳定操作/提交身份、冻结请求、摘要、有限次数、租约代次及原回执;确认与业务任务关联再次同事务。
- [发送器](../../adapters/outbox/mysql/sender.go):事务外HTTP、当前凭据核对目标、原键重报、背压退避、未知结果分类、过期接管与旧代次拒绝。
- [CLI](../../examples/task-outbox/cmd/sender/main.go)及[完整命令/方法/恢复手册](../examples/task-outbox.md):init、enqueue、send、status和demo。
- [Makefile](../../Makefile)和[隔离脚本](../../scripts/test-mysql.sh)纳入独立模块,使用单独业务数据库和专用平台凭据,不触碰现有开发数据库。
## 2. 定向数据库与故障证据
[数据库回归](../../adapters/outbox/mysql/store_integration_test.go)验证:
1. 8个相同业务操作并发入库只有一条业务记录/Outbox,7次重复核对;修改正文、源引用或目标队列不能复用原操作。
2. 实际业务INSERT失败时Outbox一起回滚;业务关联UPDATE失败时ACCEPTED一起回滚,恢复后可保存原回执。
3. 8个领取者处理20条待发项,每项初次只被一个有效代次领取;过期接管沿用提交键,旧代次确认拒绝。
4. 错误目标、损坏文档、权限拒绝、幂等冲突和无效回执停止自动发送;背压遵守Retry-After,次数耗尽和截止产生REVIEW,最后一次未知响应不能绕过上限。
5. 实际Schema查询确认22个中文列注释、外键0,通过实际违规写入验证JSON、状态、次数和截止CHECK生效,领取查询使用ix_sender_due且无filesort;大整数9007199254740993在冻结请求与真实回执中保持精确。
[COMMIT故障代理](../../adapters/outbox/mysql/commit_loss_integration_test.go)在业务入库、领取和本地确认三处分别截获真实MySQL COMMIT OK包后丢弃。调用方得到ErrCommitUnconfirmed,新Store分别核对已存在业务记录、已提交租约和已确认关联,不假定COMMIT失败即回滚。
[HTTP回执丢失](../../adapters/outbox/mysql/http_integration_test.go)先取得真实平台受理结果,再向客户端发送不完整响应并断开;Outbox保持PENDING,原键重报后同一任务ACCEPTED、deduplicated=true、发送次数2,队列只有一项任务。错误持久化命名空间在提交前被拒绝。
[发送进程故障](../../adapters/outbox/mysql/process_integration_test.go)等待真实平台受理后、本地确认前的屏障,再SIGKILL并确认旧进程已退出。新进程等待数据库30秒租约自然到期,以原键取得原回执;最终只存在一个平台任务和一条本地业务记录。测试没有直接改时间来替代这项进程接管。
定向脚本第三轮正常退出,状态码0:Outbox集成33.009秒,其中发送进程故障31.19秒;init/demo均正常完成。随后增加的[真实CLI测试](../../adapters/outbox/mysql/cli_integration_test.go)进入本轮全量回归,验证编译后的enqueue重复、status、send及正常信号停止。
## 3. 发现与修正
- 初次故障注入复用了上一笔COMMIT标记,误把后续事务准备响应当作COMMIT成功;错误标记未消费导致代理等待。通过当前进程和数据库状态核实后,对归属本轮的测试进程取得SIGQUIT堆栈,确认问题,再修正逐命令标记及非阻塞故障通知;原测试终态失败后才重新运行。
- 进程恢复的首个断言统计了整个命名空间的业务记录,混入之前HTTP测试的其他队列;改为沿Outbox关联按命名空间和队列核对。平台任务及操作身份没有发生重复。
- HTTP故障先发送成功头与不完整正文,确保客户端看到响应不完整,不把连接层透明重放当成Outbox自身恢复证据。
- 最终复查增加非法UTF-8字符串的入库前拒绝,防止Go JSON编码静默替换业务标识;单元和真实数据库验证均确认业务行与Outbox未写入。此修改后重新完成基础检查和Outbox完整独立链路。
这些修正属于测试注入和验证范围;报告不把早期失败记为通过。
## 4. 环境、复现与全量结果
macOS、Go1.27.1、Docker单实例MySQL8.4.10,临时数据库、随机凭据与回环端口。业务表与平台库分离,但本轮使用同一个隔离MySQL进程,不代表生产跨故障域验收。
```sh
make fmt test vet build
make integration
```
全量脚本和最终Outbox补充脚本均已观察到终态退出码0。没有配置数据库时go test跳过Integration,不能据此声称已覆盖真实故障。
| 验证组 | 本轮实际结果 |
| --- | --- |
| fmt / race / vet / build | PASS;最终UTF-8修改后再次全部通过 |
| 全量MySQL平台组 | PASS,121.429秒;历史外键70→0、323个未替换索引组件保留 |
| SDK Worker | PASS,87.148秒 |
| SDK计划 / 队列 / 批量 / 查询 | PASS,5.607 / 4.957 / 1.407 / 1.362秒 |
| SDK订阅管理 / 消费 | PASS,34.081 / 51.750秒 |
| SDK人工核查与重试 | PASS,3.375秒 |
| Inbox数据库与消费者故障 | PASS,34.989秒 |
| Outbox完整组 | PASS,34.327秒;含CLI 1.34秒、真实发送进程恢复31.16秒 |
| SDK应用额度 | PASS,1.425秒 |
| 九项平台节点/Worker故障 | PASS,62.786秒;加上Inbox与Outbox进程,共十一项进程故障 |
| 完整可运行示例 | 17个核心SDK程序 + Inbox + Outbox,共19个通过 |
| 最终UTF-8增强后的Outbox独立复测 | PASS,33.808秒;真实MySQL、HTTP、CLI、三个COMMIT丢响应与自然租约进程恢复全部重跑,init/demo通过 |
全量链路先通过,随后仅增强独立Outbox模块的非法UTF-8入库校验,并补充完整模块复测;平台、核心SDK和协议代码未改变。文档链接/JSON块、SDK无服务端或MySQL依赖检查通过。耗时是这次正确性回归记录,不是容量或吞吐指标。
## 5. 范围与后续
- 本例证明本地业务事务与单项任务受理的稳定身份衔接,业务实际副作用仍由Worker幂等承担,结果回写使用订阅/Inbox等链路。
- 固定24小时发送窗口、100次领取、30秒租约、原请求重报;不提供无证据重置预算、自动换键或无限恢复。
- REVIEW保留原数据,由接入方带证据和审计的管理流程处置;本示例未实现通用业务审核系统或跨业务ORM适配。
- 核心SDK、平台Schema和执行协议均未改变;新增业务示例不是已发布的兼容性SDK包。
- 流程启动与信号Outbox类型需随Weave API实现;P6继续容量、数据库切换、备份恢复及运维验证。当前正确性与进程恢复证据不等同于生产高可用或百万规模容量结论。
2026-09-24 源码组织调整:发送核心及原故障回归迁至独立 adapters/outbox/mysql 模块,业务示例调用公共包;Outbox Record/SQL见[公共模型](../../adapters/outbox/mysql/model.go)与[表结构](../../adapters/outbox/mysql/schema.sql),sender_jobs 保留在旧业务示例。上述历史验证日期不变,新增验证另见[接入适配报告](outbox-http-integration.md)。