Foreshock
EN 订阅
文档

API

幂等

怎样安全地重试一次写、为什么重放不是一次新的裁决,以及重试买不到的那样东西。

更新于
2026-08-24

两个 POST 接口都接受 Idempotency-Key 请求头。在裁决接口上,你应当总是带上它。

契约

属性取值
请求头Idempotency-Key
长度8 到 255 字符。用 UUID。
作用域你的账户。
保留24 小时。
同键同体重放已存储的响应,包含原来的 decision_id,且不再计费。
同键异体409,type: .../idempotency-conflict。

被重放的响应带 Idempotency-Replayed: true。

怎么选键

从「这次请求关于什么」派生,而不是从「这是第几次尝试」派生。裁决一笔入金时,用从 deposit_ref 派生的键,意味着这笔入金的每一次重试——包括进程重启后、从另一个 worker 发出的重试——都收敛到同一条已存储的裁决上。

每次尝试换一个新 UUID 不是幂等。那是一种给自己重复计费、并让一笔入金留下两个 decision_id 的方式。

失败后重试

key := stable_key_for(deposit_ref)
attempt:
    response := POST /v1/decide/deposit  (Idempotency-Key: key)
    if response.status == 200:
        act_on(response.verdict)
    else:
        hold(deposit)                    # 不存在裁决
        back_off_and_retry(attempt)      # 同一个键,同一个请求体

复用键正是重试之所以安全的原因:如果第一次尝试其实已经到达我们这里并产生了裁决,只是连接断了,重试拿回的是同一条裁决,而不是又造了一条。

重试买不到什么

重试不能替代裁决。在你退避等待期间,这笔入金处于 HOLD。不要按计时器贷记,不要因为重试预算用完了就贷记,也不要把碰巧拿到的第一个 2xx 当成对你等待那段时间的追认。

409 意味着这个键已经被另一个请求体用过。不要用「换个新键,把改过的体发出去」来解决它——先搞清楚同一笔入金的请求体为什么变了。