Зачем нужно знать об идемпотентности Идемпотентность – это свойство какой-либо операции, например, вызова функции или выполнения HTTP-запроса. Операция считается идемпотентной, если повторные выполнения приводят к тому же результату что и первое выполнение. Возьмем команду mkdir в линуксе. Она создает директорию: mkdir jopa. Что будет если выполнить эту команду два раза? Во второй раз мы получим ошибку. То есть операция не идемпотентная. Тоже самое справедливо и для многих других команд работающих с файловой системой. Что дальше? А дальше делаем выводы. Если мы напишем какой-то скрипт, выполняющий подготовку файловой системы, например создающий базовую структуру для нового проекта (типа ./prepare.sh /lala), то отсутствие идемпотентности начнет серьезно мешать. Что может пойти не так? Во время и после отработки: 1. Отключат свет 2. Не хватит прав 3. Мы что-то случайно удалим и захотим все восстановить 4. Кончится место. И так далее, список может быть большим. Во всех этих ситуациях понадобится повторный запуск и тут бах, он начинает падать с file exists. Соответственно придется вообще все удалять и запускать скрипт так, как будто его раньше не запускали. Мягко говоря это неудобно. Но мы можем обеспечить идемпотентность самостоятельно. Для команды mkdir достаточно добавить флаг -p и повторный запуск перестанет падать с ошибкой Не все команды имеют флаги идемпотентности, местами нужно прямо писать код с условиями. В конечном итоге подобные sh скрипты превращаются в ад. Именно поэтому появились инструменты управления конфигурацией типа Ansible, одна из основных задач, которых обеспечивать идемпотентность. Докер тоже решает эту задачу. Так, при сборке образа на основе Dockerfile нам не важно что было раньше, то идемпотентность обеспечивается автоматически. Именно поэтому bash команды внутри Dockerfile это не тоже самое что и реальные bash скрипты. А сборка легко кешируется Теперь про идемпотентность в HTTP. Там она закреплена прямо на уровне спецификации: https://datatracker.ietf.org/doc/html/rfc7231#section-4.2.2… Например GET, по спецификации, является идемпотентным методом, а POST нет. Тут стоит оговориться что, сам по себе, HTTP этого обеспечить не может. Все зависит от разработчиков. И не знание этих особенностей или игнорирование может приводит к довольно серьезным последствиям. Из доки: For example, if a client sends a PUT request and the underlying connection is closed before any response is received, then the client can establish a new connection and retry the idempotent request. Идемпотентность позволяет безопасно делать ретраи и кешировать запросы А вот то, что POST не идемпотентный нам подсказывает даже браузер. Помните когда после POST-запроса пытаешься сделать f5, то браузер предупреждает о повторной отправке данных и что это не безопасно. Если пройдет валидация, то что-то случится два раза, например выполнится оплата Тут мы приходим к интересному моменту. Представьте что вы работаете с платежным сервисом типа Stipe. Как обезопасить себя и клиентов от повторных списаний денег при отправке запросов? Это легко случается, когда возникают сетевые ошибки при повторных запросах. Стандартный способ – добавления ключа идемпотентности. То есть при отправке запроса на списание денег, мы указываем специальный параметр, идентификатор транзакции. Обычно это номер заказа. А платежный сервис на его основе обеспечивает идемпотентность. https://stripe.com/docs/api/idempotent_requests Идемпотентность особенно важна при работе с очередьми, типа rabbitmq. В этой части ретраи неизбежны и возникает скорее обратная проблема, как остановить то что надо остановить. Тут могут помочь автоматы и превращение at-least-once в at-most-once. Как все это ложиться на код? Многое из того что я описал, обеспечивается кодом, который мы пишем. Каждый раз когда вы создаете код, выполняющий побочные эффекты на уровне ввода/вывода (фс, сеть), задумайтесь об идемпотентности. Вполне вероятно она тут очень в тему. Ссылки: Телеграм | Youtube | VK p.s. Является ли метод DELETE в HTTP идемпотентным
2 года назад
​Пополняем словарный запас. Что такое идемпотентность и какие HTTP методы можно считать таковыми?
Идемпотентность кажется запутанной концепцией, по крайней мере, если судить по академическому определению. Но если говорить простыми словами, то это просто операция, многократное выполнение которой приводит к тому же результату, что и однократное выполнение. Например, умножение на 1 — идемпотентная операция (x * 1 == x * 1 * 1 * 1). HTTP-методы могут быть идемпотентными или нет. Рассмотрим примеры. GET /pageX HTTP/1.1 идемпотентен. Вызвавший несколько раз подряд этот запрос, клиент получит тот же результат: GET /pageX HTTP/1...