幂等性
当连接失败导致您无法确定请求是否成功时,请使用 Idempotency-Key。其保证是恰好一次接受:在 3 小时保留窗口内,使用相同键和相同请求的重试必须解析为同一个已接受的操作,即使您丢失了原始响应。
工作原理
幂等性是可选启用的。在支持的 POST、PATCH、PUT 或 DELETE 请求中添加 Idempotency-Key 请求头。未携带该请求头的请求将正常处理,不进行去重。GET 请求会忽略该请求头。
在客户 API 上,工作区级和组织级的变更操作支持下文所述的响应重放。仅限用户的操作、无作用域的未认证操作以及流式操作不受此机制影响。具有独立重放契约的操作会在其参考页面中定义自身行为。例如,创建语音通话在您提供键时会保留原始接受快照,用于匹配的重试。
SDK 会为每个变更调用生成一个键,并在自动重试(包括创建通话)时复用该键。自动 SDK 重试无需您提供键。当一个预期操作跨越多次独立的 SDK 调用时(例如重启应用后的重试),请提供您自己的键。以下示例展示的就是这种场景。
await bird.email.send(
{
from: "hello@yourdomain.com",
to: ["delivered@messagebird.dev"],
subject: "Welcome!",
html: "<p>Thanks for signing up.</p>",
},
{ idempotencyKey: "welcome-user/usr_abc123" },
);client.email.send(
from_="hello@yourdomain.com",
to=["delivered@messagebird.dev"],
subject="Welcome!",
html="<p>Thanks for signing up.</p>",
options={"idempotency_key": "welcome-user/usr_abc123"},
)_, err := client.Email.Send(context.Background(), bird.EmailSendParams{
From: "hello@yourdomain.com",
To: []string{"delivered@messagebird.dev"},
Subject: "Welcome!",
HTML: "<p>Thanks for signing up.</p>",
}, option.WithIdempotencyKey("welcome-user/usr_abc123"))$bird->email->send(
from: 'hello@yourdomain.com',
to: ['delivered@messagebird.dev'],
subject: 'Welcome!',
html: '<p>Thanks for signing up.</p>',
options: new RequestOptions(idempotencyKey: 'welcome-user/usr_abc123'),
);curl -X POST https://us1.platform.bird.com/v1/email/messages \
-H "Authorization: Bearer $BIRD_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: welcome-user/usr_abc123" \
-d '{
"from": "hello@yourdomain.com",
"to": ["delivered@messagebird.dev"],
"subject": "Welcome!",
"html": "<p>Thanks for signing up.</p>"
}'键可以是任何非空字符串,最长 255 个字符。空的请求头值会跳过去重。推荐的格式是从您自身实体派生的确定性键,<event-type>/<entity-id>(例如 welcome-user/usr_abc123),这样跨进程重启的重试可以共享同一个键;每个逻辑操作使用一个随机 UUID 也可以。Bird SDK 会为每个变更请求自动生成 UUID 键,并在其内部重试中复用。
键的作用域为您的工作区;在组织级端点上,作用域为您的组织。已完成的响应会保留 3 小时;超过该窗口后的重试可能会作为新请求处理。如果过期后原始操作的结果仍未知,请将其保持为未决状态,并在再次发送前先核对其结果。
重放
三小时内的匹配重试必须解析为原始操作。如果其响应已被保留,API 会返回相同的状态码和响应体,而不会接受另一个操作。重放的响应会携带一个额外的响应头,方便您将其与首次处理的响应区分开:
HTTP/1.1 202 Accepted
Idempotency-Replay: true保留的响应可能包含 4xx 拒绝。修正请求时请使用新键:如果该请求的拒绝已被保留,未更改的重试会重放该拒绝,而更改后的请求会返回 409 E01005 IdempotencyKeyReuse。5xx 响应不会作为已完成的响应保留。恰好一次接受的保证同样适用于这些错误之后的重试。
失败场景
| 场景 | 响应 |
|---|---|
| 相同键、相同请求,原始响应在保留期内仍被保留 | 响应通过 Idempotency-Replay: true 重放 |
| 相同键、不同的请求体或端点 | 409,E01005 IdempotencyKeyReuse |
| 相同键,原始请求仍在处理中 | 409,E01004 RequestInProgress |
| 键超过 255 个字符,且端点声明了该请求头 | 422,E01001 ValidationError |
| 幂等性保护在执行前不可用 | 503,E01033 IdempotencyUnavailable;此次尝试未被执行 |
使用已完成的键发送不同的请求会被视为客户端 bug:Bird 会立即返回 409,而不是静默地返回一个与您发送内容不匹配的响应。请为新请求生成新键。比较范围涵盖方法、端点、路径和查询参数以及原始请求体,包括 JSON 空白字符。多部分上传会比较部分名称、文件名和内容;边界和部分顺序不影响重放。
RequestInProgress 表示使用相同键的并发请求尚未完成,通常是因为客户端超时设置过短,在第一次尝试仍在处理时就发起了重试。请稍等片刻,再使用相同的键和请求重试。参见错误了解包装这些错误的错误响应格式。
不会被缓存的内容
5xx 响应不会作为已完成的响应保留。 请在三小时内使用有上限的退避策略,以相同的键和完全相同的请求进行重试。即使原始响应已丢失,恰好一次接受的保证仍然适用。
如果幂等性保护在执行前不可用,API 会返回 503 E01033 IdempotencyUnavailable,且不会执行此次尝试。每次重试都应保留该键。此错误不描述使用相同键的先前尝试的结果。
实践指南
- 为每个逻辑操作生成一个键,并在该操作的每次 HTTP 尝试中复用它。
- 遇到网络错误、超时和
5xx时,在三小时内使用有上限的指数退避进行重试,并保留相同的键和完全相同的请求。 - 当重试次数用尽或保留期过期时,将结果未知的操作保持为未解决状态。在使用旧键或新键提交另一个操作之前,请先核对该操作的结果。
- 对于消息发送,请在请求被接受后检查消息状态以确认是否送达。
- 将
409 IdempotencyKeyReuse视为键生成中的错误,不要重试。 - 键在变更操作中是可选的。需要重试保护时使用键;在
GET请求中可以省略。
后续步骤
- 幂等性 API 参考:请求头和响应头的模式定义
- SDK 概念:SDK 中的自动键生成和重试行为
- 错误:错误响应格式和错误码目录
- 发送邮件:发送和批量端点