Target Version
3.0-dev。证据基于 origin/3.0-dev 提交 15f6eae5600197879a2fd5a0bc4c65a41df689af,目标仅覆盖 Message 成功落库后的下游 fan-out。
Evidence
message/source/message_server.h:560-573 在一个 MySQL 事务中提交 message 与 user_timeline,随后事务已经结束。
message/source/message_server.h:593-640 提交后才发布 Push/ES 事件;只有 publish confirm 失败或抛异常时才写 Redis Push/ES Outbox。
- 进程若在 MySQL commit 后、RabbitMQ publish 或 Redis Outbox enqueue 前崩溃,会留下已持久化但永远没有对应 Push/ES 事件的消息。
- Redis Outbox enqueue 本身异常时,
common/dao/data_redis.hpp:956-958,1034-1036 只记录日志,没有另一个耐久恢复源。
- MQ 重投无法稳定修复该窗口:重复 message 路径在
message/source/message_server.h:574-577 发现已存在后直接 ACK,不会重新生成 fan-out。
Problem or Goal
消除 MySQL commit 与下游事件登记之间的双写窗口。任何已提交消息都必须拥有可恢复、可幂等派发的 Push/ES 事件记录,即使 Message 在任意指令点崩溃。
Scope
- 将消息持久化和待派发事件登记纳入同一个 MySQL 本地事务。
- 建立独立 dispatcher/reaper,按状态、重试时间和 lease 安全发布并在 confirm 后标记完成。
- 为 Push 与 ES 事件定义稳定 event_id、幂等键、保留/清理和重建语义。
- 支持多 Message 实例并发 claim、崩溃接管、积压监控和运维重放。
- 迁移现有 Redis Outbox,明确兼容期、双读/停写顺序和回滚。
Non-goals
Acceptance Criteria
Test-first Plan
先增加 RL-OUTBOX-01 并运行:
make -C tests test-reliability TEST_RUN=TestRL_OUTBOX_MessageCommitCrashRecovery
预期 RED 是在 MySQL commit 后立即杀死 Message,消息可查询但 Push/ES 永不出现且 Redis Outbox 为空。最小 GREEN 是事务内 MySQL Outbox 和一个幂等 dispatcher;随后运行消息同步、WebSocket 通知、搜索 Scenario、同层 Reliability 与 BVT。
Risk and Security
Outbox 会增加 MySQL 写放大、表增长和 dispatcher 竞争,需容量预算、索引、批量 claim 与清理策略。事件 payload 可能含消息内容,应最小化存储、继承数据库访问控制和保留期;日志不得回显 payload。回滚必须保留未完成事件。
Architecture Impact
Yes。MySQL 新增 durable event 状态,Message 增加 dispatcher 所有权,Redis Outbox 从唯一补偿源迁移为兼容或可删除组件。
Core-flow Impact
Yes。改变 Message commit 后的 Push/ES 事件产生、重试、幂等、恢复和清理路径;MySQL 继续是消息真相源,ES 仍为派生索引。
Required Skill Updates
- 更新
.agents/skills/chatnow-orienting/references/technology-stack.md 与 repository-map.md,登记 Outbox 表、dispatcher 与配置所有权。
- 更新
.agents/skills/chatnow-orienting/references/core-flows.md,描述事务边界、事件状态机、重试与恢复。
- 更新
.agents/skills/chatnow-testing/references/case-catalog.md,登记 RL-OUTBOX-01 及关联 Scenario。
- 更新 schema migration 与运维文档,记录迁移、积压处理、清理和回滚。
Target Version
3.0-dev。证据基于
origin/3.0-dev提交15f6eae5600197879a2fd5a0bc4c65a41df689af,目标仅覆盖 Message 成功落库后的下游 fan-out。Evidence
message/source/message_server.h:560-573在一个 MySQL 事务中提交 message 与 user_timeline,随后事务已经结束。message/source/message_server.h:593-640提交后才发布 Push/ES 事件;只有 publish confirm 失败或抛异常时才写 Redis Push/ES Outbox。common/dao/data_redis.hpp:956-958,1034-1036只记录日志,没有另一个耐久恢复源。message/source/message_server.h:574-577发现已存在后直接 ACK,不会重新生成 fan-out。Problem or Goal
消除 MySQL commit 与下游事件登记之间的双写窗口。任何已提交消息都必须拥有可恢复、可幂等派发的 Push/ES 事件记录,即使 Message 在任意指令点崩溃。
Scope
Non-goals
Acceptance Criteria
Test-first Plan
先增加
RL-OUTBOX-01并运行:make -C tests test-reliability TEST_RUN=TestRL_OUTBOX_MessageCommitCrashRecovery预期 RED 是在 MySQL commit 后立即杀死 Message,消息可查询但 Push/ES 永不出现且 Redis Outbox 为空。最小 GREEN 是事务内 MySQL Outbox 和一个幂等 dispatcher;随后运行消息同步、WebSocket 通知、搜索 Scenario、同层 Reliability 与 BVT。
Risk and Security
Outbox 会增加 MySQL 写放大、表增长和 dispatcher 竞争,需容量预算、索引、批量 claim 与清理策略。事件 payload 可能含消息内容,应最小化存储、继承数据库访问控制和保留期;日志不得回显 payload。回滚必须保留未完成事件。
Architecture Impact
Yes。MySQL 新增 durable event 状态,Message 增加 dispatcher 所有权,Redis Outbox 从唯一补偿源迁移为兼容或可删除组件。
Core-flow Impact
Yes。改变 Message commit 后的 Push/ES 事件产生、重试、幂等、恢复和清理路径;MySQL 继续是消息真相源,ES 仍为派生索引。
Required Skill Updates
.agents/skills/chatnow-orienting/references/technology-stack.md与repository-map.md,登记 Outbox 表、dispatcher 与配置所有权。.agents/skills/chatnow-orienting/references/core-flows.md,描述事务边界、事件状态机、重试与恢复。.agents/skills/chatnow-testing/references/case-catalog.md,登记RL-OUTBOX-01及关联 Scenario。