🔁 Обеспечение идемпотентности API
Идемпотентная операция — это операция, которая при многократном вызове не меняет состояние ресурса. То есть, если мы повторно вызываем идемпотентный метод API, то не возникнет ошибок, связанных с дублированием одной и той же операции (например, двойных списаний баланса за один и тот же заказ).
По-хорошему, любой API должен быть идемпотентным.
Идемпотентность в REST API
HTTP-методы
❗️ Важно: ответ идемпотентного метода может меняться. Например, при повторном вызове идемпотентного API создания заказа — заказ не будет создаваться ещё раз, но API может ответить как 200, так и 400. При обоих кодах ответа API будет идемпотентно с точки зрения состояния сервера (заказ один, с ним ничего не происходит), а с точки зрения клиента поведение существенно разное.
❗️ Проблемы неидемпотентных API
Проблема №1. Дублирование операций.
При сетевых задержках или ошибках одна и та же операция может быть выполнена несколько раз.
Пример с заказом такси:
1️⃣ Пользователь вызывает такси в приложении
2️⃣ Приложение отправляет запрос на создание заказа на сервер
3️⃣ Возникает сбой, и приложение не получает успешный ответ по таймауту
4️⃣ Приложение показывает сообщение «произошла ошибка» и делает кнопку заказа снова активной
5️⃣ Пользователь снова нажимает кнопку
6️⃣ К пользователю может приехать два такси вместо одного
Проблема №2. Неконсистентное состояние.
Неидемпотентные операции затрудняют отслеживание текущего состояния системы, что может привести к ошибкам и неконсистентности данных.
Пример с заказом такси:
1️⃣ Пользователь изменяет пункт назначения в активном заказе такси через приложение.
2️⃣ Приложение отправляет запрос PATCH /v1/orders/{id} на сервер для обновления заказа
3️⃣ Возникает сбой, и приложение не получает подтверждение об успешном обновлении
4️⃣ Приложение показывает пользователю сообщение об ошибке и предлагает повторить попытку
5️⃣ Пользователь решает изменить пункт назначения на новый и снова отправляет запрос
6️⃣ Сервер обрабатывает оба запроса: сначала второй, затем первый. В системе возникает неконсистентность: водитель видит один пункт назначения, а пользователь ожидает, что будет доставлен в другое место.
Идемпотентность создания и изменения
Способы обеспечения идемпотентности методов создания (POST) и частичного изменения (PATCH):
1. Ключ идемпотентности в заголовке запросов
2. Версионирование состояния
3. Блокировка на основе правил
🗝 Ключ идемпотентности
Это уникальный идентификатор операции, который помогает защититься от повторного исполнения операции.
Как это работает:
1. Клиент генерирует уникальный ключ идемпотентности и отправляет его в заголовке запроса. Например, Idempotency-Key: <UUID>
2. Сервер проверяет, был ли уже обработан запрос с таким ключом. Если да, возвращает результат предыдущего запроса, не выполняя операцию повторно. Иначе просто выполняет операцию.
⬇️ Продолжение ниже⬇️
Идемпотентная операция — это операция, которая при многократном вызове не меняет состояние ресурса. То есть, если мы повторно вызываем идемпотентный метод API, то не возникнет ошибок, связанных с дублированием одной и той же операции (например, двойных списаний баланса за один и тот же заказ).
По-хорошему, любой API должен быть идемпотентным.
Идемпотентность в REST API
HTTP-методы
GET
, PUT
, DELETE
формально считаются идемпотентными, тогда как POST
и PATCH
нет. Это не означает, что нельзя сделать GET
неидемпотентным, а POST
идемпотентным.Проблема №1. Дублирование операций.
При сетевых задержках или ошибках одна и та же операция может быть выполнена несколько раз.
Пример с заказом такси:
Проблема №2. Неконсистентное состояние.
Неидемпотентные операции затрудняют отслеживание текущего состояния системы, что может привести к ошибкам и неконсистентности данных.
Пример с заказом такси:
Идемпотентность создания и изменения
Способы обеспечения идемпотентности методов создания (POST) и частичного изменения (PATCH):
1. Ключ идемпотентности в заголовке запросов
2. Версионирование состояния
3. Блокировка на основе правил
🗝 Ключ идемпотентности
Это уникальный идентификатор операции, который помогает защититься от повторного исполнения операции.
Как это работает:
1. Клиент генерирует уникальный ключ идемпотентности и отправляет его в заголовке запроса. Например, Idempotency-Key: <UUID>
2. Сервер проверяет, был ли уже обработан запрос с таким ключом. Если да, возвращает результат предыдущего запроса, не выполняя операцию повторно. Иначе просто выполняет операцию.