Повторный вебхук не должен создавать второй заказ, платеж и задачу
Смотрим в тело запроса: идемпотентность начинается не с базы, а с ключа события. Если источник умеет прислать event_id, external_id или delivery_id — используйте его как primary key для дедупликации. Если не умеет, собирайте составной ключ из критичных полей: тип события + объект + timestamp + payload hash. Главное — не путать одинаковые запросы с одинаковыми последствиями.
Схема простая: входящий запрос кладём в очередь, но перед обработкой проверяем запись в хранилище. Таблица или Redis-set фиксируют статус: received, processing, done, failed. На повторный запрос отвечаем 200/202, но бизнес-операцию не дублируем. Если обработчик упал после записи в БД, ретрай-политика решает всё: повторяем до тех пор, пока не увидим done, а не пока «кажется, прошло».
Не используйте проверку вида «если записи нет — вставить». Без транзакции это классическая гонка. Нужен уникальный индекс по idempotency_key и атомарная вставка: либо insert-on-conflict-do-nothing, либо upsert с сохранением первого результата. Смотрим в тело запроса: если payload может приезжать битым, валидируйте до постановки в очередь, иначе будете дедуплицировать мусор.
Идемпотентность — это не роскошь, а база. Если интеграция без ключа и без уникального ограничения, она будет ломаться при любом ретрае, любом таймауте и любом 5xx на ровном месте.
Автоматизация на вебхуках
@webhook_automation_hub_arb
Повторный вебхук не должен создавать второй заказ, платеж и задачу
Этот пост опубликован в Telegram-канале Автоматизация на вебхуках. Подписаться можно по ссылке: @webhook_automation_hub_arb.