跳转到内容

幂等与重试

每次实时调用都必须带 Idempotency-Key。它不是限流上的客套,而是让重试变得安全的前提。网络可能在供货方已经被请求之后才中断;没有这个 Key,想知道一次检测究竟跑没跑,唯一的办法就是再跑一次——再付一次钱。

填一个你能重新生成的值:UUID、订单号,或者本次工作的哈希。服务端以你的账号为作用域,所以不同用户之间不会撞车。

相同 Key请求体结果
新 Key任意正常执行并计费
相同 Key完全相同返回已存储的响应,replayed=true,不会产生新扣费
相同 Key有改动409 idempotency_conflict——Key 绑定在它第一次携带的请求体上
相同 Key完全相同,但首次调用还在执行409 request_in_progress,并带 Retry-After

Idempotency-Key 最长 191 字节,重放记录默认保留 30 天。

它们在响应里长得像,含义完全不同:

字段位置含义
replayed顶层这次调用根本没到供货方——你重放了一个 Key
cached每条 result 内部这个产品的结论来自结果缓存

重放的调用会完整复现原响应,包括每条 result 的 cached 值。两者都不改变你被扣了多少:重放不会动钱,缓存命中仍按产品的单次价格计费。

只有已定论的结果才会作为事实留存。失败和 unknown 不会被缓存——之后对同一标识、同一产品的检测会重新问供货方,而不是复述一个没有结论的答案。

你看到的现象该怎么做
超时,或 HTTP 500用原来的请求体和原来的 Key 重发。结果是不确定的,这正是 Key 存在的意义
409 request_in_progress等 Retry-After,再用相同 Key 和相同请求体重发
409 idempotency_conflict这个 Key 已经绑了别的请求体。换一个新 Key——不要改完请求体还接着用旧 Key
429 realtime_rate_limited等 Retry-After。什么都没提交,这个 Key 仍然没用过,可以安全重发
503 realtime_route_unavailable什么都没提交。稍后用同一个 Key 重试

唯一绝对不能做的事:超时之后用新 Key 提交同样的工作。如果第一次其实已经落地,你刚刚为同一次检测付了两遍钱。

HTTPcode
400idempotency_key_required——缺少请求头
409request_in_progress——原始调用仍在执行
409idempotency_conflict——该 Key 首次使用时携带的是另一个请求体