test: cover dispatch loss and workflow commit fault boundaries

This commit is contained in:
2026-09-18 10:52:19 +08:00
parent 19cb70368e
commit 1f1d833f69
12 changed files with 697 additions and 38 deletions

View File

@@ -1,10 +1,10 @@
# P4/P5 原范围核对与剩余验收
# P4/P5 平台功能阶段验收与生产边界
日期:2026-09-18。本报告按[原流程功能](../06-workflow-spec.md)、[开发计划](../08-development-plan.md)及[生产故障矩阵W01–W17](../05-production-acceptance.md)核对,保留未完成项。功能实现、单个场景通过与整个阶段验收分开记录;P4/P5尚不标为整体完成,P6/P7及持续目标保持进行中。
日期:2026-09-18。本报告按[原流程功能](../06-workflow-spec.md)、[开发计划](../08-development-plan.md)及[生产故障矩阵W01–W17](../05-production-acceptance.md)核对,保留未完成项。原功能均有服务端、公共HTTP/独立SDK、场景及异常回归证据;版本/暂停/全停与提交边界的补强完成后,P4/P5平台功能阶段验收通过。P6/P7及持续目标保持进行中,生产负载、部署拓扑和发布兼容不包含在这一结论中。
新增补强:[版本、暂停竞争与全停恢复回归](phase-4-5-races.md)提供W06/W09/W14/W15的实际事务及公共SDK进程证据。下表随该批更新,原轮询/恢复示例的验证记录保留。
新增补强:[版本、暂停竞争与全停恢复回归](phase-4-5-races.md)提供W06/W09/W14/W15的实际事务及公共SDK进程证据。另有[A04/W01/W13/W16故障边界](phase-6-fault-boundaries.md)的真实派发未送达、COMMIT前后断线和最终信号竞争证据。下表随两批更新,原轮询/恢复示例的验证记录保留。
## 本批交付
## 首批独立场景交付
新增两个独立可运行SDK示例,均只导入公开SDK及示例内部辅助包,不访问Orbit数据库或服务端模型:
@@ -36,7 +36,7 @@
| 编号 | 当前证据 | 仍需补强的具体边界 |
| --- | --- | --- |
| W01 | 受理/推进/后继创建的SQL失败与SAVEPOINT回滚,原结果和额度保持 | COMMIT回执不明与特定步骤写入切点的进程中断需要统一故障工具覆盖 |
| W01 | SQL失败/SAVEPOINT回滚及实例启动、后继创建的真实COMMIT前后断线;原身份恢复且状态/任务/消费确认原子一致,见[故障边界](phase-6-fault-boundaries.md) | MySQL进程/复制故障、存储持久化组合继续P6 |
| W02 | 结果持久化后全控制节点退出,两新节点消费,后继不重复 | 生产数据库切换另按P6,不与应用进程强杀等同 |
| W03 | 早到、重复、迟到、错误关联及代次的实际存储与SDK回归 | 仍须纳入容量模型中的大量信号积压 |
| W04 | TIMER、早到SIGNAL、独立等待恢复均有全停后接续 | 生产长时间等待、保留与清理策略按P6验收 |
@@ -48,13 +48,13 @@
| W10 | 同恢复键竞争、旧激活结果、旧信号代次及恢复后全停 | 滚动版本兼容、长期历史保留另按P6/P7 |
| W11 | 同轮重试与PENDING新轮次的存储、SDK及实际HTTP例子 | 渠道峰值与大批量同刻唤醒按P6 |
| W12 | 最大轮次、截止、原轮尝试耗尽拒绝绕过;新例子保留NEEDS_REVIEW | 不把本地时间预算测试换算成生产延迟指标 |
| W13 | 轮次创建失败回滚、PENDING落库及检查点全停恢复 | 精确COMMIT不确定窗口仍按W01/P6补强 |
| W13 | PENDING结果/等待和下一轮任务/预算分别覆盖COMMIT前回滚、提交后丢确认;新运行器按原候选恢复,原结果计时及查询预算保持 | 生产数据库失联、切换与容量继续P6 |
| W14 | PAUSE与开始/后继/领取/安全重试的真实事务竞争,双向入队、数据库授权时间、暂停收集结果、恢复任务/尝试数及原截止断言 | 不声称穷尽全部线程交错;高负载锁等待及故障切点继续P6 |
| W15 | 公共SDK暂停后提交任务结果/信号,两原节点全部SIGKILL并Wait退出;TIMER/下一查询轮就绪时间过去后两新节点接管,显式RESUME完成四任务/两轮查询 | 单机数据库进程故障证据;生产数据库高可用和长停机恢复另按P6 |
| W16 | 最终信号与查询结果按原受理时间裁决,在途PENDING结清、冲突核查、全停保留 | 普通SIGNAL三方竞争见W09;最终查询/回执/下一轮同时到达的故障切点及热点负载继续P6,不能拿W09替代 |
| W15 | 公共SDK暂停后提交任务结果/信号,两原节点全部SIGKILL并Wait退出;TIMER/下一查询轮就绪时间过去后两新节点接管,显式RESUME完成四任务/两轮查询 | 单机数据库下的应用进程故障证据;生产数据库高可用和长停机恢复另按P6 |
| W16 | 原受理时间裁决、在途PENDING结清/冲突核查/全停保留;另有最终信号、旧PENDING重放、下一轮时钟六种真实事务竞争,后继仅一个 | 新结果冲突与旧结果重放分别核验;不声称穷尽调度交错,热点负载继续P6 |
| W17 | 同版本同内容/不同内容、非法定义、SDK丢发布回执恢复 | 旧SDK/服务版本滚动兼容矩阵按P7发布候选核对 |
## 本批验证记录
## 首批独立场景验证记录(历史)
环境:macOS arm64、Go 1.27.1、Docker MySQL 8.4.10,一次性隔离数据库和真实Orbit进程。新例子先用`go run -race`运行,两个命令均退出0;恢复例子的网络断线由本机HTTP服务器真实注入。
@@ -66,9 +66,9 @@
首次定向脚本省去存储测试后忘记单独执行迁移,bootstrap在发放凭据前拒绝,已修正为先运行orbit-migrate。编译时也纠正了示例误用的来源字段名,正式SDK字段为PollRound。这些修正没有改变平台执行或恢复规则。
## 下一步按顺序完成
## 阶段结论与下一步
1. W06/W09/W14/W15已补真实数据库与公共SDK进程断言,并完成标准全量回归,见[专项回归](phase-4-5-races.md)。原四项缺口已关闭,后续按剩余生产故障推进。
2. 据这些结果再决定P4/P5功能阶段是否可验收,不能把本报告中的部分验证改成全项完成。
3. 进入P6统一观测、凭据轮换、历史保留/归档、故障切点工具、容量负载、备份恢复与滚动升级;继续保留A04精确未派达、MySQL切换、跨故障域等原门槛。
2. W01/W13已补真实COMMIT前后断线,W16已补最终信号/旧PENDING重放/下一轮竞争;本报告原功能表、故障表及两批完整回归共同支持P4/P5平台功能阶段验收。此次完整标准回归结果见[故障边界报告](phase-6-fault-boundaries.md),历史记录不覆盖为新数字。
3. P6已完成上述首批故障工具(包括A04未送达),下一步为统一观测、凭据轮换、历史保留/归档、容量负载、备份恢复与滚动升级;MySQL切换、跨故障域等原门槛继续保留。
4. P7补实际文件转换等仍缺的原场景、SDK版本发布与新接入者全量核对。百万企业支持能力只能根据实际工作负载和目标拓扑验证,当前不作容量承诺。

View File

@@ -0,0 +1,74 @@
# P6 首批:派发未送达与事务提交故障边界
日期:2026-09-18。本批补A04、W01/W13的精确故障切点,并补W16最终回执、旧查询结果与下一轮唤醒的竞争。工具只编译进测试二进制,生产服务、SDK运行代码、接口、模型和迁移不增加故障开关;数据库继续禁止外键。
## A04:派发已提交,Worker尚未收到
[公共SDK进程测试](../../sdk/go/dispatch_process_integration_test.go)使用[真实WS故障网关](../../sdk/go/worker_integration_test.go)。网关已从真实Orbit收到`task.assign`帧,但在转交业务Worker之前截留它,并阻止重连。
测试通过独立HTTP连接确认同一任务已处于LEASED、存在一次持久尝试、authorized_at为空。Worker实际处理器调用数仍为0。随后强杀原Orbit并Wait确认退出;该帧始终没有交给Worker,网关丢弃它。另起真实Orbit节点并按原提交键核对回执。
保持Worker离线,等待原30秒租约自然到期,不修改数据库时钟。新节点将未授权尝试记录为EXPIRED,ended_at不早于原lease_until,原任务回到WAITING且没有未知副作用标记。恢复WS后完成原任务:
- 业务处理器恰好执行1次;总尝试恰好2次,第一次未获授权,第二次SUCCEEDED。
- 沿用原任务、提交回执、总截止和2次尝试预算;RECONCILE_ONLY策略保持。
- 并发上限为1的队列可重新派发,证明旧预占已释放;完成后的未终结任务额度为0。
这条证据针对“未送达业务Worker”。帧已到测试网关,不声称平台从未向网络写过该帧,也不将已送达但未开始的场景混为同一切点。SDK不获得网关保存的旧执行秘密。
## W01/W13:MySQL COMMIT前后真实断线
[MySQL包代理及八个场景](../../internal/storage/mysql/commit_fault_integration_test.go)只允许连接一次性、明文、loopback测试数据库,不修改生产TLS配置,不输出SQL、凭据或业务正文。按MySQL包头逐包转发,识别真实COM_QUERY COMMIT:
| 切点 | 代理实际动作 | 独立数据库连接应观察到的事实 |
| --- | --- | --- |
| BEFORE | 不把COMMIT转交MySQL,关闭连接 | 尚未提交的状态、任务、身份和消费确认全部回滚 |
| AFTER | 收到真实MySQL成功包,核验IN_TRANS已清除;不把确认交给驱动,关闭连接 | 数据已经完整提交,调用方收到连接错误,不能当作回滚后换身份 |
四种事务各覆盖两个切点:启动实例及首批任务、结果消费及创建后继、PENDING结果及建立下一轮等待、下一轮任务及轮次预算递增。故障调用必须返回错误,同时代理必须证明到达所选切点;不能仅因请求报错就推断发生过COMMIT。
通过不经过故障代理的连接读取真实表,检查实例/任务数量、Inbox处理确认、查询等待或轮次原子性。随后使用新运行器处理原候选,或用原启动键重报。最终每个场景恰好两个任务和两次尝试,无待处理Inbox或许可遗留,原版本、原流程/查询截止及尝试预算保持。PENDING等待仍从原结果事件时间计算,不从重报时间重新开始。
这证明数据库连接在提交边界断开的恢复行为,不等于MySQL进程宕机、复制切换、丢失已确认事务或磁盘故障验收。它也不将HTTP回执丢失冒充数据库提交结果不明。
## W16:最终回执、旧查询结果、下一轮同时竞争
[六种入队顺序](../../internal/storage/mysql/workflow_final_signal_race_integration_test.go)使用真实MySQL锁等待确认三个事务都已重叠,再等原下一轮时间自然到达后放行。参与者分别是最终DONE信号受理、上一轮PENDING结果的重复消费、下一轮时钟。
上一轮必须已经保存等待,下一轮才可能到期。因此此处结果参与者是旧结果重放,测试明确保留这个因果关系,不构造不可能同时存在的“未提交PENDING和已到期下一轮”。已授权查询与新结果、冲突/未知结果的处理另由[现有信号运行回归](../../internal/storage/mysql/workflow_signal_runtime_integration_test.go)及真实进程恢复覆盖。
观察到两类合法顺序:最终信号先受理时,不创建第二轮;下一轮先创建时,最终信号取消尚未授权的第二轮查询并收集其结果。两者都只执行第一轮查询和一个后继任务,只完成一个等待。再次投递旧PENDING和旧时钟不能重新打开轮次或多建后继;原信号回执、版本、截止和精确输出保持。
## 复现和验证
```sh
make fmt test vet build
make integration
```
标准脚本的存储组自动执行`TestIntegrationWorkflowCommitFaults`与`TestIntegrationWorkflowFinalSignalRace`;原服务退出后的Worker进程组自动执行`TestIntegrationWorkerProcessUndeliveredAssignment`。无需额外生产依赖或手工开启故障环境变量。
定向环境:macOS arm64、Go 1.27.1、Docker MySQL 8.4.10、独立临时数据库及真实Orbit进程。最终定向存储组14个子场景退出0(21.100秒),A04进程组退出0(34.080秒)。MySQL驱动的预期EOF来自代理确实切断COMMIT连接,不是测试失败。首次编译纠正了测试误用的队列资源方法,改用已公开的GetQueue;未因此增加接口或扩大发放权限。
基础`make fmt test vet build`退出0。最终标准全量回归退出0:23个可运行SDK示例、2个独立业务模块,以及完整存储、协议与真实进程恢复链路均通过。标准脚本使用竞态检测;本批测试源码自启动完整回归后未再修改。
| 标准回归分组 | 结果与测试耗时 |
| --- | --- |
| 存储及迁移全部场景 | 退出0,266.966秒;包含八个COMMIT切点及六个W16入队顺序 |
| 原流程运行器进程全停/接管 | 退出0,49.022秒 |
| 独立业务Inbox | 退出0,35.638秒 |
| 独立业务Outbox | 退出0,34.167秒 |
| Worker/结果订阅进程故障 | 退出0,128.097秒;包含A04自然租约到期场景32.72秒 |
| 公共SDK流程暂停全停/恢复 | 退出0,13.845秒 |
以上耗时仅用于复现核对,不是吞吐或延迟指标。无外键升级回归同时确认:历史70个外键全部移除,323个原索引组成部分及任务数据保留,当前外键为0,重新引入外键的结构漂移被拒绝。模型和中文注释要求没有改变。
本批证据与[前一批竞争/全停回归](phase-4-5-races.md)共同补齐P4/P5功能阶段核对所列的具体缺口;[P4/P5报告](phase-4-5.md)据原功能清单记录阶段验收通过。P6进行中,P7及完整首版交付尚未完成。
最终文档检查:1184个本地链接、68个JSON块,错误0;`git diff --check`通过。
## 保留的生产门槛
本批关闭上述具体切点缺口,不代表故障模型或负载已穷尽。完整首版仍需运行指标/告警、可轮换凭据及安全重绑、历史保留/归档、慢消费者和重连风暴、六类容量负载、MySQL失联/主节点切换、备份恢复、跨故障域部署、SDK发布兼容和完整接入示例。
阶段范围和下一步见[持续计划](../08-development-plan.md)、[P4/P5核对](phase-4-5.md)与[原生产验收门槛](../05-production-acceptance.md)。当前单机数据库证据不能换算成生产HA、RPO/RTO或百万企业容量承诺。