Skip to content

Make post-commit message fan-out transactional and recoverable #70

Description

@ULookup

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

  • 不在本 Issue 中解决 Transmite 到 RabbitMQ 的入站双写;Transmite 没有本地 MySQL 事务。
  • 不承诺 WebSocket exactly-once;客户端仍需按消息标识去重。
  • 不把 Elasticsearch 变成消息真相源。
  • 不顺带重构 ACK 路径;Make delivery ACK convergence durable and trustworthy #58 继续负责 ACK 收敛。

Acceptance Criteria

  • message、timeline 与待派发事件在同一 MySQL transaction 中原子提交或共同回滚。
  • 在 commit 后、publish 前、confirm 前后和状态更新前后杀死 Message,恢复后事件均能最终派发。
  • dispatcher 多实例不会永久重复副作用;重复发布由 event/message 幂等键收敛。
  • Push/ES 不可用时不影响消息持久化,Outbox lag/age/retry/dead 状态可观测。
  • 已完成事件有有界保留和清理策略,未完成事件不会被误删。
  • 迁移期间不存在 Redis 与 MySQL Outbox 都不负责的空窗。
  • Complete and document the reliability fault-injection layer #65 用例验证各崩溃点和依赖恢复后的最终收敛。

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.mdrepository-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 与运维文档,记录迁移、积压处理、清理和回滚。

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Severity/S1area/infra跨系统基础设施bugSomething isn't workingtech-debt设计已规划但代码未对齐的实现差距

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions