先画出失败时间线
09:00:00 Agent 提议创建报告 report_42
09:00:01 应用验证参数和权限,发出 POST /reports
09:00:11 客户端等待超时,没有收到 HTTP 响应
09:00:12 服务端可能仍在处理,也可能已成功创建报告
此时把状态标记为“未知”,而不是“失败”。若直接重新发一个没有关联标识的 POST,可能得到两份报告。先在自己或供应商的系统中查找先前请求的结果:客户端业务标识、服务方请求 ID、任务查询接口、审计日志都可能提供线索。具体能查什么取决于所用 API。
服务支持幂等键时怎么用
在首次提交前生成一个只对应这次业务操作的键,例如UUID v4,并把它与本次操作的固定参数一起保存。连接中断后,按供应商文档用同一个键、同一份参数重试,不要每次重试都生成新键。不同供应商对头名称、结果保存范围、有效期和失败响应的处理不同;先查其官方说明。Stripe 的 API 文档提供了一个具体实现示例,但不能推断所有模型或工具 API 都采用相同规则。
如果你维护自己的写入 API,仅在内存里记住最近的键是不够的:多个实例或服务重启后会失效。应在持久层对“用户/操作范围 + 幂等键”建立唯一约束,并把它与请求参数摘要、处理状态和结果关联。并发到达的相同键只能有一个执行者;另一条请求应得到同一结果或明确的处理中状态。相同键携带不同参数时应拒绝,避免旧键被拿去做新操作。
上线前跑六个验收用例
| 输入或故障 | 期望行为 |
|---|---|
| 首次提交键 A、参数 X | 只创建一份报告,记录业务 ID |
| 再次提交键 A、参数 X | 不重复创建;返回已有结果或可查询状态 |
| 键 A 携带参数 Y | 明确拒绝参数冲突 |
| 两个并发请求使用键 A | 只有一个请求执行写入 |
| 写入成功但响应丢失 | 查询或重试时能找到原结果 |
| 键超出服务方保留期 | 不假设仍会去重;先查询业务状态 |
如果服务方根本不提供查询结果或幂等能力,自动重试写入请求就缺少必要的安全依据。此时应暂停、记录请求标识并让用户或运维确认;不要把“网络重试成功率”放在重复写入风险之前。
HTTP 的“幂等方法”是协议语义;它不自动让任意
POST 安全。即使服务提供 Idempotency-Key,也要按该服务的实际文档核对保留期限和并发行为。依据:RFC 9110:幂等方法与通信失败后的重试;具体服务示例:Stripe 幂等请求文档。