Files
orbit/docs/reports/phase-6-fault-boundaries.md

7.2 KiB
Raw Permalink Blame History

P6 首批:派发未送达与事务提交故障边界

日期:2026-09-18。本批补A04、W01/W13的精确故障切点,并补W16最终回执、旧查询结果与下一轮唤醒的竞争。工具只编译进测试二进制,生产服务、SDK运行代码、接口、模型和迁移不增加故障开关;数据库继续禁止外键。

A04:派发已提交,Worker尚未收到

公共SDK进程测试使用真实WS故障网关。网关已从真实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包代理及八个场景只允许连接一次性、明文、loopback测试数据库,不修改生产TLS配置,不输出SQL、凭据或业务正文。按MySQL包头逐包转发,识别真实COM_QUERY COMMIT:

切点 代理实际动作 独立数据库连接应观察到的事实
BEFORE 不把COMMIT转交MySQL,关闭连接 尚未提交的状态、任务、身份和消费确认全部回滚
AFTER 收到真实MySQL成功包,核验IN_TRANS已清除;不把确认交给驱动,关闭连接 数据已经完整提交,调用方收到连接错误,不能当作回滚后换身份

四种事务各覆盖两个切点:启动实例及首批任务、结果消费及创建后继、PENDING结果及建立下一轮等待、下一轮任务及轮次预算递增。故障调用必须返回错误,同时代理必须证明到达所选切点;不能仅因请求报错就推断发生过COMMIT。

通过不经过故障代理的连接读取真实表,检查实例/任务数量、Inbox处理确认、查询等待或轮次原子性。随后使用新运行器处理原候选,或用原启动键重报。最终每个场景恰好两个任务和两次尝试,无待处理Inbox或许可遗留,原版本、原流程/查询截止及尝试预算保持。PENDING等待仍从原结果事件时间计算,不从重报时间重新开始。

这证明数据库连接在提交边界断开的恢复行为,不等于MySQL进程宕机、复制切换、丢失已确认事务或磁盘故障验收。它也不将HTTP回执丢失冒充数据库提交结果不明。

W16:最终回执、旧查询结果、下一轮同时竞争

六种入队顺序使用真实MySQL锁等待确认三个事务都已重叠,再等原下一轮时间自然到达后放行。参与者分别是最终DONE信号受理、上一轮PENDING结果的重复消费、下一轮时钟。

上一轮必须已经保存等待,下一轮才可能到期。因此此处结果参与者是旧结果重放,测试明确保留这个因果关系,不构造不可能同时存在的“未提交PENDING和已到期下一轮”。已授权查询与新结果、冲突/未知结果的处理另由现有信号运行回归及真实进程恢复覆盖。

观察到两类合法顺序:最终信号先受理时,不创建第二轮;下一轮先创建时,最终信号取消尚未授权的第二轮查询并收集其结果。两者都只执行第一轮查询和一个后继任务,只完成一个等待。再次投递旧PENDING和旧时钟不能重新打开轮次或多建后继;原信号回执、版本、截止和精确输出保持。

复现和验证

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,重新引入外键的结构漂移被拒绝。模型和中文注释要求没有改变。

本批证据与前一批竞争/全停回归共同补齐P4/P5功能阶段核对所列的具体缺口;P4/P5报告据原功能清单记录阶段验收通过。P6进行中,P7及完整首版交付尚未完成。

最终文档检查:1184个本地链接、68个JSON块,错误0;git diff --check通过。

保留的生产门槛

本批关闭上述具体切点缺口,不代表故障模型或负载已穷尽。完整首版仍需运行指标/告警、可轮换凭据及安全重绑、历史保留/归档、慢消费者和重连风暴、六类容量负载、MySQL失联/主节点切换、备份恢复、跨故障域部署、SDK发布兼容和完整接入示例。

阶段范围和下一步见持续计划、P4/P5核对与原生产验收门槛。当前单机数据库证据不能换算成生产HA、RPO/RTO或百万企业容量承诺。