跳转至

Writer SIGKILL 恢复门禁诊断(2026-08-23)

问题与根因

DurableMessageCommitter 的状态机有 reserve、record/history、Outbox durable publish、 mark COMMITTED 四段持久边界,但此前没有能在真实 writer 进程精确停在中间边界的 测试工具。内存 fake 或 panic!/abort() 不能证明操作系统杀进程后,Redis 与 Redpanda 的真实恢复路径仍按首次 intent 收敛。

变更范围

  • crates/qim-writer/src/committer.rs:仅在 fault-injection feature 下,在三个 已持久化窗口调用测试钩子。
  • crates/qim-writer/src/fault.rs:解析显式测试环境变量、同步写 marker、永久等待 外部 SIGKILL;默认生产构建不包含该模块。
  • scripts/integration/writer-kill9.sh:使用隔离 Redis + Redpanda、真实五服务和 外部 kill -9 运行 M-COMMIT-02/03/04。

不会改变状态机顺序、生产配置、共享 Compose/acceptance 脚本或存储契约。

三个精确窗口

门禁 marker point 证实的持久事实 禁止已经发生的操作
M-COMMIT-02 after-reserve reserve、首次坐标已原子持久化 record/history、Outbox
M-COMMIT-03 after-record record 与 history 已原子持久化 Outbox publish
M-COMMIT-04 after-outbox-publish Redpanda 已返回 durable delivery mark_outbox_published / COMMITTED

marker 含 PID、稳定幂等键及首次 message_id/conversation_seq,但不含 token 或正文。 脚本在读取完整 marker 后执行 kill -9 "$pid";钩子本身从不 panic、abort 或自行退出。

验收条件

每个窗口使用不同 sender/receiver/cmid:

  1. marker 的 PID 必须是脚本实际杀掉的 writer 进程,且 wait 返回信号退出码。
  2. 未注入故障的新 writer 重启后,以相同 payload + cmid 重试,ACK 的 message_id/conversation_seq 必须等于 marker 首次坐标。
  3. 相同 cmid、不同 payload 必须收到 ERROR,不得返回 ACK。
  4. PULL_HISTORY 中该 message_id 恰一条;发送者与接收者 PULL_MAILBOX 各恰一条。
  5. 从 Outbox topic 读取时,该 message_id 的逻辑键集合大小必须为一;M-COMMIT-04 可有同 key 的物理重发,后续 fanout/mailbox 必须按稳定 ID 收敛。

运行方式与外部条件

scripts/integration/writer-kill9.sh

需要 Docker daemon、隔离 Redis + Redpanda 镜像、Rust release 构建所需依赖,以及 本机可对脚本启动子进程发送 SIGKILL。任一依赖不可用必须失败并保留工件,不能标绿。

已执行验证(2026-08-23)

执行命令:

scripts/integration/writer-kill9.sh

隔离工件目录:/tmp/qim-artifacts.qim-it-u1000-1787495807-735631.wmI8gL。

门禁 SIGKILL 退出码 恢复验证 Outbox 物理记录
M-COMMIT-02 / after-reserve 137 ACK 首次坐标、历史一条、两侧邮箱各一条 1
M-COMMIT-03 / after-record 137 ACK 首次坐标、历史一条、两侧邮箱各一条 1
M-COMMIT-04 / after-outbox-publish 137 ACK 首次坐标、历史一条、两侧邮箱各一条 2(同一 canonical envelope)

三项均验证了相同 cmid、不同 payload 会收到 ERROR。M-COMMIT-04 的两条物理 Outbox 记录是杀进程发生在 publish 后、写 publication 前的预期重发;脚本逐条解码并 确认同一 message_id 的 canonical envelope 集合大小为一。