Идемпотентность, ключ идемпотентности

Допустим, мы оформляем заказ в интернет-магазине. Из браузера уходит запрос «создать заказ». Запрос может потеряться в пути, и тогда хорошая идея попробовать отправить его снова. Проблема в том, что возможно на самом деле потерялся не запрос, а ответ. Тогда в результате будет создано два заказа.

Поэтому для этой операции выдвигается требование идемпотентности. Это свойство означает, что сколько бы раз операция не была вызвана, эффект будет одинаковым. Ответ от сервера при этом может быть разный. В нашем примере, должно быть не важно, один раз был отправлен запрос или 10 – должен быть создан ровно один заказ.

Стандартный способ достичь этого свойства – генерация на стороне клиента ключа (токена) идемпотентности. Это просто некое уникальное значение. Например, может использоваться строка с точным текущим временем. Еще чаще просто генерируют уникальную UUID-строку. На стороне обработки запроса выполняется только та операция, ключ которой еще не встречался. Таким образом становится возможно делать retry безопасно.

Принципы REST API требуют чтобы все HTTP методы кроме POST и PATCH были идемпотентными. Однако реализация остается на совести разработчиков, а способ не ограничивается ключами идемпотентности. Со стороны клиента нельзя просто так добавить ключ идемпотентности к любому понравившемуся запросу.

На хабре есть интересная история про идемпотентность.