Skip to content
预计 1 分钟右侧目录可快速定位

Worker 失败后怎样重投而不重复副作用:Idempotent Worker、Retry Queue 与 DLQ ​

前置:Run/Node 发给 Worker 后会发生什么:Queue、Ack、Redelivery 与 At-least-once
核心问题:同一个 dispatch_id 被消费三次时,哪一层负责保证业务效果只提交一次,什么时候应该进入 DLQ?

Broker Delivery ID 不是业务 Operation ID ​

同一个逻辑 Node 可能被 broker 重新发布成新消息。真正稳定的 identity 应来自 Runtime,例如:

text
operation_id = run_id + node_id + logical_attempt

Broker 的 message/delivery id 只用于诊断 delivery,本地幂等记录围绕 operation_id。

Worker 入口先查事实,再做副作用 ​

text
receive message
→ load node + operation record
→ already SUCCEEDED? return existing result / ack
→ not eligible? ack/discard stale message
→ claim current lease
→ execute
→ durable commit result
→ ack

如果 Tool 是远端副作用,还要使用 Tool 支持的 idempotency key 或 reconciliation;Worker record 只能防止“已知成功后再次执行”,无法消除“远端成功但本地未知”的窗口。

Retry Queue 应保存“下一次何时、为什么” ​

一次失败至少归类:

text
TRANSIENT      → retry after backoff
RATE_LIMITED   → retry respecting Retry-After / budget
DEPENDENCY_DOWN→ retry/defer
INVALID_INPUT  → terminal, do not retry
PERMISSION     → terminal / require intervention
UNKNOWN_SIDE_EFFECT → reconcile first

Retry message/envelope 要携带稳定 operation identity、attempt、next_eligible_at 和错误分类。不要每次重试重新生成业务 idempotency key。

DLQ 不是垃圾桶 ​

进入 DLQ 的消息至少需要:

  • run/node/operation identity;
  • 原始 message metadata;
  • normalized error + attempt history;
  • last known runtime version;
  • correlation/trace id;
  • 是否可能已产生外部副作用。

并且必须有:告警、查询、人工决策、reconciliation、redrive。

Redrive 不是“点一下重新发消息”。在重驱前要重新检查:

text
Run 是否已 cancel/terminal?
Tool schema 是否变化?
权限/approval 是否仍有效?
side effect 是否需要 reconciliation?

Failure Modes ​

Retry 创建新的 Operation ID ​

后果: 下游把每次 attempt 当新业务动作。

处理: logical operation 稳定,attempt 单独递增。

DLQ 只存 payload,没有执行证据 ​

后果: 无法判断能不能安全 redrive。

处理: 保存错误、版本、trace、side-effect uncertainty,并把 redrive 当显式 command。

如何验证 ​

场景必须成立
同消息 redeliver 3 次已成功 operation 不再次产生副作用
429 后 retryoperation id 不变,attempt 增加,遵守 delay
invalid input不进入无限 retry loop
DLQ redrive 前 Run 已 cancelled不重新执行

自测 ​

  1. 同一个 dispatch_id 被消费三次,哪一个稳定 identity 应贯穿重试,才能保证业务效果只提交一次?
  2. 一条消息已经多次失败且确认不是瞬时错误。什么时候应进入 DLQ,而不是继续无限 retry?进入后还需要保存什么诊断信息?

Sources ​

AI Engineering · Agent · Harness · Backend Systems