Что означает идемпотентность метода в контексте API?

Ответ

Идемпотентность метода — это свойство, означающее, что многократное выполнение одной и той же операции с одинаковыми входными данными даёт тот же результат, что и однократное выполнение, и не вызывает дополнительных изменений состояния системы после первого успешного вызова.

Практическое значение:

Это ключевое свойство для обеспечения надёжности распределённых систем, так как клиенты могут безопасно повторять запросы при сбоях сети, не опасаясь побочных эффектов (например, списания денег дважды).

Примеры в HTTP:

Метод Идемпотентен? Почему
GET Да Получение данных. Повторные запросы не изменяют состояние.
PUT Да Обновление ресурса. PUT /users/1 {name: "Alice"} при повторении всегда оставит пользователя с name:"Alice".
DELETE Да Удаление ресурса. После первого успешного удаления ресурса его больше нет, последующие вызовы вернут 404 (Not Found), что является тем же итоговым состоянием.
POST Нет Создание ресурса. Каждый вызов POST /users создаст нового пользователя.
PATCH Обычно нет Частичное обновление. Например, PATCH /users/1 {balance: +100} при повторе увеличит баланс дважды.

Как обеспечить идемпотентность?

Для неидемпотентных операций (например, списание средств) используют:

  1. Идемпотентные ключи (Idempotency-Key): Клиент отправляет уникальный ключ с запросом. Сервер запоминает результат первой обработки и для повторных запросов с тем же ключом возвращает сохранённый ответ, не выполняя операцию заново.
  2. Оптимистичные блокировки: Использование версий (version или ETag) для предотвращения "потерянных" обновлений.

Ответ 18+ 🔞

Да ты посмотри, какая тема подъехала — идемпотентность, блядь! Это ж не просто какая-то хуйня, а фундаментальная штука, на которой всё держится, когда системы начинают друг другу в рот чих-пых по сети общаться.

Представь себе, ты в интернет-магазине жмёшь «Оплатить». Отправил запрос, а в ответ — тишина, ёпта. Сеть глюкнула, таймаут, сервер ушёл курить. И что, паниковать? Дёргать кнопку ещё десять раз? Так можно и последние штаны проебать, если за каждый твой тык списывают бабки! Вот тут-то и выходит на сцену наш герой — идемпотентный метод.

Что это за зверь такой? Если по-простому, то это такой метод, который можно тыкать сколько угодно раз, а хуйня случится только одна. Первый раз он сделает дело, а все последующие — просто пожмут плечами и скажут: «Чувак, расслабься, всё уже сделано, состояние то же самое». Как будто ты десять раз подряд просишь кофе: «Дай кофе. Дай кофе. Дай кофе». Бариста-то не осатанеет и не нальёт тебе десять чашек, он один раз нальёт и дальше будет кивать: «Вот твой кофе, мудила, уже стоит».

А нахуя это вообще нужно? Да затем, чтобы не сойти с ума в распределённых системах! Сети — они ненадёжные суки. Пакеты теряются, таймауты срабатывают, сервера падают. Клиент отправил запрос, ответа не дождался — он же не будет сидеть и гадать, ушло платёжное поручение в банк или нет. Он, естественно, пошлёт запрос ещё раз. А если операция не идемпотентная — пиши пропало, списали дважды. Идемпотентность — это как страховка от таких ебак.

Смотрим на HTTP-методы, кто тут мудак, а кто молодец:

Метод Идемпотентен? Объяснение на пальцах
GET Да Это просто спросить «что тут у вас?». Можно спрашивать до посинения — состояние не изменится.
PUT Да «Положи на полку N книгу X». Сколько раз ни говори — на полке N в итоге будет книга X. Остальные команды — впустую.
DELETE Да «Выкинь мусор из ведра». После первого раза ведро пусто. Второй раз команда просто констатирует: «Чувак, оно уже пустое, нихуя не делаю».
POST Нет А вот это, сука, опасно! «Роди мне ребёнка». Каждый новый запрос — это новый ребёнок. Десять запросов — десять детей, поздравляю, ёпта.
PATCH Обычно нет «Доложи на счёт сто рублей». Повторил — уже двести. Это же не одно и то же состояние, блядь!

Ну а если операция по своей природе — полная неидемпотентная пизда, как быть? Например, тот же платёж. Нельзя же просто так взять и сделать его идемпотентным. Тут в игру вступают костыли, но костыли гениальные:

  1. Идемпотентный ключ (Idempotency-Key). Это как билет с номером. Клиент, отправляя опасный POST на списание, пристёгивает к нему уникальный ключ (например, X-Idempotency-Key: pay_12345). Сервер этот ключ видит и думает: «Так, ключ pay_12345... О, я такой уже обрабатывал! Вот результат той операции, держи, заёб, и больше не приставай». А если не обрабатывал — делает дело и результат на ключ привязывает. Красота, блядь!

  2. Оптимистичные блокировки. Тут уже для случаев, когда состояние меняют много кто. Используют версию ресурса (version или ETag). Допустим, ты хочешь изменить запись. Читаешь её, видишь version=5. Отправляешь PUT с новыми данными и version=5. Сервер проверяет: а на самом деле версия ещё 5? Если да — применяет изменения, поднимает версию до 6. Если нет (значит, кто-то уже успел обновить) — говорит тебе: «Мудила, данные устарели, иди обнови». Это чтобы два программиста не перезаписали изменения друг друга вхолостую.

Вот так вот, блядь. Выглядит как скучная теория, а на деле — основа, чтобы система не разъебалась в труху при первом же чихе сети. Запомни: GET, PUT, DELETE — твои друзья, их можно повторять. POST и PATCH — опасные уёбки, с ними нужен либо уникальный ключ, либо мозги.