Повторите запрос, не выполняя работу дважды
Заголовок Idempotency-Key — каким запросам он нужен, чем отвечают на повторный запрос и как выбрать ключ.
3 мин чтения
Запрос, который выполняет флоу или двигает кредиты, несёт ваш собственный ключ в заголовке Idempotency-Key. Ключ называет одну единицу работы. На запрос, повторённый с его ключом, отвечают, а не выполняют его заново, поэтому повтор после таймаута или потерянного соединения ничего не выполняет дважды и ничего не списывает дважды.
Где нужен ключ
Заголовок обязателен для запросов, которые что-то тратят или двигают:
запрос, который выполняет флоу, —
POST /v1/operations/execute;движение кредитов клиента —
POST /v1/customers/{externalUserId}/topup,POST /v1/customers/{externalUserId}/chargeиPOST /v1/customers/{externalUserId}/adjust.
Страница каждого ресурса помечает эти операции. Остальные операции заголовок не читают.
Запрос без заголовка или с пустым заголовком отклоняется с
400и кодомidempotency_key_required. Ничего не выполняется.Ключ — не длиннее 190 символов. Более длинный отклоняется с
422и кодомinvalid_request— до того, как что-либо зарезервировано, списано или начислено.
Чем отвечают на повтор
Повтор — это тот же запрос с тем же ключом. Чем на него отвечают, зависит от того, что сделал первый запрос.
| Запрос | Повтор с его ключом |
|---|---|
| Выполнение флоу | Выполнение, которое открыл первый запрос, в том состоянии, в котором оно находится в этот момент, с replayed, равным true: 202, пока выполнение не закончено, и 200 с его результатом, когда закончено. Заново ничего не выполняется |
| Движение кредитов | Первый ответ — в течение 24 часов. После этого — счёт в его нынешнем виде. Кредиты двигаются один раз |
Ответ с ошибкой в одних случаях сохраняется, а в других — нет.
Выполнение флоу закрепляет за собой ключ, как только выполнение появилось. Ошибка, которая пришла до этого, —
flow_not_found, тело, которое не прошло проверку, — оставляет ключ свободным. Ошибка, которая пришла после, напримерinvalid_flow_input, закрывает выполнение, и повтор его читает:200, статусfailedи код.Движение кредитов сохраняет только успешный ответ. Отклонённый запрос можно отправить ещё раз с тем же ключом.
Другой запрос с занятым ключом
Ключ, который уже называет единицу работы, отклоняет другую. Ответ — 409 с кодом idempotency_conflict, и ничего не выполняется.
{
"error": {
"code": "idempotency_conflict",
"message": "The Idempotency-Key was already used with a different request body",
"request_id": "6b2e9c4a-1d7f-4e3b-8a5c-0f9d2e7b4c61"
}
}Что считается другим запросом, зависит от того, что называет ключ.
Для выполнения флоу тело сравнивается байт в байт. Другой вход, другой
context, другойexecution_mode— и даже те же поля в другом порядке — дают другой запрос.Для движения кредитов любое другое тело — другой запрос, пока хранится первый ответ. После этого движение кредитов сравнивается по клиенту, типу кредитов, виду движения и сумме.
Как выбрать ключ
Составляйте ключ из единицы работы: заказ и его шаг (
order-42:email) или идентификатор задачи вашей очереди. Тогда каждый повтор этой работы несёт тот же ключ, а следующая единица работы получает новый.Ключ, созданный случайно для каждой попытки, защищает только эту попытку. Повтор, который ваше приложение отправляет с новым ключом, — это новая работа, и за неё платят ещё раз.
Ключ принадлежит проекту. Два проекта могут использовать один и тот же ключ, а внутри проекта у каждой единицы работы — свой ключ.
Чтобы выполнить работу снова после неудачного запроса — с другим входом или другой моделью, — отправьте исправленный запрос с новым ключом.
Что читать дальше
Ключи идемпотентности — ключи, которые отправляют SDK, и ключ из задачи очереди.
Операции — запрос, который выполняет флоу, и вызовы модели, которые он сделал.
Коды ошибок — что значат коды отклонённого ключа и что делать с каждым.
Клиенты и кредиты — ключи пополнений, списаний и корректировок.
Быстрый старт — первый запрос с собственным ключом.
Обзор — остальные соглашения запроса.
Выполнения — прочитайте выполнение, которому принадлежит ключ, и его трассировку.