diff --git a/docs/architecture/message-lifecycle-and-ai-flow.md b/docs/architecture/message-lifecycle-and-ai-flow.md index b0c1bd92..b53682ed 100644 --- a/docs/architecture/message-lifecycle-and-ai-flow.md +++ b/docs/architecture/message-lifecycle-and-ai-flow.md @@ -140,7 +140,10 @@ ActionCableListener.OnEvent (internal/wsevent/bridge_listener.go:51) #### Durable realtime 投递语义 配置 WorkerPool 后,`EventPublisher` 先把 account 与 pubsub token 目标分别写入 -`background_jobs`,再由 `realtime:event_publish` job 发布到 Redis、Hub 和 SSE。 +`background_jobs`。在当前 Redis relay 配置下,account target job 发布到 account +room,由 `BroadcastRelay` 转发到 Hub,并由执行 job 的实例写 account SSE;pubsub +token target job 只发布到 token room,经 relay 转发到 Hub,不写 SSE。并非每个 +job 都同时直发 Redis、Hub 和 SSE。 幂等键避免同一条 `message.created`/目标重复入队,job claim 避免并发执行同一条 记录;它们不覆盖发布副作用与 job 完成状态之间的崩溃窗口: @@ -154,6 +157,11 @@ delivery。进程恢复后,在线 WebSocket/SSE 消费者可能再次收到同 SSE 不保存离线或慢消费者的确认状态,所以该契约保证发布尝试可恢复,不保证每个 客户端至少接收一次。 +该保证从 job 成功写入 `background_jobs` 开始。事务内入队失败会使业务事务回滚; +非事务入队失败则没有 durable job,因而不保证该事件会被发布。每个 target job 的 +`MaxAttempts=3`;达到上限(或遇到 permanent error)进入 `dead` 后不会再被自动 +重试,也不再保证发布,消费者仍需通过 REST reconciliation 恢复持久化状态。 + 消费者必须把 realtime 事件作为可重放通知处理: - `message.created` 使用订阅作用域、事件名和 payload 的稳定 message `id` 去重或