Chuyển tới nội dung chính

Idempotency

Lỗi mạng hay hết thời gian chờ khiến bạn không biết request đã tới nơi hay chưa. Nếu cứ gửi lại, khách có thể nhận cùng một email hai lần hoặc bị yêu cầu trả tiền hai lần. Idempotency key giúp việc gửi lại an toàn: Hạ Tầng chỉ làm việc đó một lần và trả cùng một kết quả cho mọi lần lặp lại.

Hỗ trợ ở đâu​

Gửi key trong header Idempotency-Key. Key là chuỗi bất kỳ do bạn chọn, tối đa 256 ký tự.

EndpointPhạm vi của keyLặp lại với cùng bodyLặp lại với body khác
POST /emailsDoanh nghiệp200 với cùng id; không gửi lại thư400 invalid_idempotent_request
POST /paymentsDoanh nghiệp và môi trường Thanh toán201 với cùng thanh toán400 invalid_idempotent_request
POST /chat/conversations/{id}/messagesHội thoại200 với cùng tin nhắn và "duplicate": true200 với tin nhắn đầu (body không được so sánh)

POST /emails/batch và các endpoint khác không nhận idempotency key.

Gửi idempotency key​

Dùng key xác định nghiệp vụ, không phải lần gọi HTTP: mã đơn hàng, welcome-<user id>, invoice-<số>-reminder-1. Tạo key một lần, lưu cùng tác vụ, và dùng lại ở mọi lần thử.

curl -X POST https://api.hatang.dev/emails \
-H "Authorization: Bearer $HATANG_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: order-1001-confirmation" \
-d '{
"from": "Shop <[email protected]>",
"subject": "Đơn #1001 đã được xác nhận",
"html": "<p>Cảm ơn bạn đã đặt hàng!</p>"
}'

Key được lưu thế nào​

  • Email và thanh toán. Key được lưu cùng email hoặc thanh toán mà nó tạo ra, kèm bản băm của body request. Lần lặp lại với cùng key được so với bản băm đó. Key không hết hạn: còn email hay thanh toán thì key vẫn trỏ tới nó. Email được trả lại theo key không bị tính thêm vào hạn mức trong ngày.
  • Tin nhắn chat. Key trở thành client_id của tin nhắn. Lần lặp lại trong cùng hội thoại trả về tin nhắn đã có với "duplicate": true. Widget và SDK di động cũng làm như vậy với client_id gửi kèm mỗi tin nhắn, nhờ đó tin nhắn gửi hai lần khi mạng chập chờn chỉ hiện một lần trong hộp thư.
  • Môi trường Thanh toán. Key của thanh toán tính riêng theo môi trường, nên cùng một mã đơn dùng được một lần ở development và một lần ở production.

Xung đột​

nameStatusNguyên nhânNên làm gì
invalid_idempotent_request400Key đã được dùng với body khácBạn đã dùng lại key cho một nghiệp vụ khác. Tạo key mới; đừng bao giờ đổi body khi thử lại.
concurrent_idempotent_requests409Chỉ ở Email: hai request cùng key tới cùng một lúcChờ một chút rồi thử lại với cùng key; bạn nhận kết quả của request đầu.
{
"statusCode": 400,
"name": "invalid_idempotent_request",
"message": "Same idempotency key used with a different request payload"
}

"Body khác" là bất kỳ giá trị nào thay đổi, như một mốc thời gian mới hay một id ngẫu nhiên được sinh lại trong payload. Hãy dựng payload một lần, lưu cùng key, và gửi lại đúng payload đó ở mọi lần thử.

Lời khuyên khi thử lại​

  1. Tạo key trước lần gọi đầu tiên và lưu cùng tác vụ, để tiến trình có chết giữa chừng thì key vẫn còn.
  2. Chỉ thử lại lỗi tạm thời: lỗi mạng, 429 rate_limit_exceeded và 5xx. Tăng thời gian chờ theo cấp số nhân và tôn trọng retry-after (Giới hạn tần suất).
  3. Không thử lại lỗi 4xx ngoài 429 và 409 concurrent_idempotent_requests; hãy sửa request.
  4. Coi lần trả lại là thành công. 200 cho email lặp lại hay tin nhắn chat có "duplicate": true nghĩa là lần đầu đã thành công.
  5. Làm cho handler webhook cũng idempotent. Lượt gửi webhook có thể lặp lại; xem Webhook.

Bước tiếp theo​

Xem trang này dạng Markdown