Потеря ответа не доказывает отсутствие результата
Представим вымышленный сервис резервирования наборов для настольной игры. Доступны три набора. Первый запрос зарезервировал один, но ответ не дошёл до клиента из-за разрыва связи. На сервере осталось два свободных набора, а пользователь пока не знает исход. Если просто создать новую заявку, резерв может появиться второй раз. Поэтому важно различать ошибку получения ответа и подтверждённый отказ выполнения операции.
Одна операция получает устойчивый идентификатор
В учебной модели первоначальному запросу назначен условный ключ К1. Сервер связывает его с параметрами и результатом резервирования. Повтор того же запроса с тем же ключом возвращает уже связанный результат, а свободных наборов остаётся два. Это описание выбранного контракта системы, а не свойство любого запроса автоматически. Поведение должно быть реализовано и документировано. Один интерфейсный запрет повторного нажатия не защищает от всех сетевых повторов.
Одинаковый ключ не должен скрывать другую задачу
Если под ключом К1 сначала просили один набор, а затем два, смысл операции изменился. В надёжно определённом контракте такое несовпадение параметров требуется обнаруживать, а не молча выдавать старый результат как подходящий новому запросу. При этом отдельная действительно новая операция получает собственную идентификацию. Полезно описать, сколько времени система помнит ключи и как ведёт себя при параллельных запросах. Эти детали влияют на границы защиты от дублей.
Идемпотентность не заменяет контроль состояния
Даже наличие ключа не освобождает продукт от обработки незавершённых состояний и ошибок. Важно понимать, началось ли выполнение, сохранён ли результат и что может безопасно показать интерфейс. В учебном сервисе полезны различимые состояния: заявка обрабатывается, резерв подтверждён, выполнение отклонено или исход требует уточнения. Нельзя объявлять успех только потому, что пользователь нажал кнопку. Технический механизм должен поддерживать понятное поведение продукта и проверяемый итог.
Попробуйте на практике
Смоделируйте два повтора одной операции на бумаге без обращения к реальному сервису.
- Нарисуйте три доступных игровых набора. Создайте запрос на резерв одного набора с условным ключом К1.
- Отметьте, что сервер выполнил резерв, но ответ потерялся. Запишите фактическое число свободных наборов и неизвестный для клиента исход.
- Повторите тот же запрос с К1 по правилам учебной модели. Укажите, что возвращается прежний результат и второй резерв не создаётся.
- Измените количество на два, сохранив К1. Объясните, почему это несовпадение параметров должно быть замечено.
- Составьте вопросы к контракту настоящей системы: срок хранения ключа, параллельные обращения, ошибки и способ проверки результата. Не считайте бумажную модель гарантией поведения любого API.
Как проверить результат. После корректного повтора свободны два набора. Вы различаете потерю ответа, повтор прежней операции и изменение её смысла, а ключ не используется как замена проверке состояния.
Частые вопросы
Достаточно ли отключить кнопку после нажатия?
Это может уменьшить случайные повторы в интерфейсе, но не описывает поведение сети и сервера. Защиту от дублирующего эффекта нужно обеспечивать на соответствующем уровне.
Любой API автоматически поддерживает такую схему?
Нет. Возможности и ограничения проверяют по документации конкретной операции. Идемпотентность нельзя предполагать только по удобному названию метода.
Самостоятельный разбор темы. Содержание конкретной обучающей программы здесь не представлено.