Практические разборы l3_builders

Webhook создаёт дубли: idempotency, retry и regression test

Практический выпуск CodeVibers: собираем FastAPI webhook, сохраняем idempotency key в SQLite, воспроизводим retry и блокируем конфликт payload.

Видео по теме

Открыть видео на YouTube

Практический выпуск CodeVibers: собираем FastAPI webhook, сохраняем idempotency key в SQLite, воспроизводим retry и блокируем конфликт payload.

Таймкоды

  • 00:00 Две доставки — одна запись
  • 00:45 Чистый проект
  • 01:30 UNIQUE и payload hash
  • 03:00 Retry и conflict 409
  • 04:25 Regression tests
  • 05:25 Browser proof

Shorts

Источники выпуска

Исходники проекта из выпуска

Это тот же воспроизводимый проект, который собирается и тестируется в видео.

  • requirements.txt — Pinned runtime dependencies.
  • app.py — Webhook endpoint, SQLite contract and result UI.
  • demo.py — Real first/retry/conflict execution and report.
  • tests/test_webhook.py — Positive, retry, conflict and missing-key regression tests.
  • README.md — Reproducible run instructions.

Команды запуска и проверки

.venv/bin/python demo.py
.venv/bin/python -W ignore -m pytest -q

Скачать проект ZIP

Практический материал из выпуска

Артефакт: Runnable FastAPI webhook service with SQLite idempotency storage and browser dashboard.

Что должно получиться: Project ZIP, endpoint code, schema, demo report and regression tests.

Видимый результат: Two identical deliveries produce one record; conflicting payload is blocked with HTTP 409.

Вход для демо: Repeated lead.created payload with X-Idempotency-Key evt_demo_42.

Выход демо: SQLite database, reports/demo.json, reports/result.html and four passing tests.

Проверка результата: Same event_id on retry, database count one, conflict 409, pytest green.

Как собрать

  1. create endpoint
  2. create UNIQUE table
  3. send first event
  4. repeat same event
  5. send conflicting payload
  6. open browser dashboard

Чеклист перед пилотом

  • first created true
  • retry created false
  • one database row
  • conflict 409
  • four tests pass

Примеры команд, настроек или правил

CREATE TABLE ... idempotency_key UNIQUE
X-Idempotency-Key
payload hash
pytest -q
uvicorn app:app

Требования и рекомендации

Требования

  • уникальный индекс
  • стабильный key от источника
  • атомарная запись
  • 400 без ключа и 409 при конфликте

Рекомендации

  • хранить ключ в durable storage
  • связывать ключ с payload hash
  • возвращать исходный event id на retry
  • тестировать конфликт отдельно

Суть темы

Практический выпуск CodeVibers: собираем FastAPI webhook, сохраняем idempotency key в SQLite, воспроизводим retry и блокируем конфликт payload.

Что важно забрать

  • Добавить уникальный idempotency key, payload hash и отрицательные тесты в собственный webhook.
  • Рабочий webhook endpoint, SQLite contract, retry behavior and regression suite.
  • Не совет о retries, а две реальные доставки, одна durable запись и конфликт payload на экране.
  • Заменить blind retry на проверяемый exactly-once business effect.

Как применять на практике

Используйте материал как отправную точку: сформулируйте задачу, ограничьте область применения, выберите метрику качества и проверьте результат на небольшом сценарии до внедрения в production.

Практические шаги

  1. create endpoint
  2. create UNIQUE table
  3. send first event
  4. repeat same event
  5. send conflicting payload
  6. open browser dashboard

Рекомендации

  • хранить ключ в durable storage
  • связывать ключ с payload hash
  • возвращать исходный event id на retry
  • тестировать конфликт отдельно

Требования и ограничения

  • уникальный индекс
  • стабильный key от источника
  • атомарная запись
  • 400 без ключа и 409 при конфликте

Примеры

  • две доставки evt_demo_42 создают одну запись
  • тот же key с другой суммой получает 409

Антипримеры

  • проверять дубли только в памяти процесса

Как проверить готовность

  • database count equals one
  • retry event_id equals first event_id
  • conflict returns 409
  • four tests pass

Навигация по выпуску

  • 00:00 Две доставки — одна запись
  • 00:45 Чистый проект
  • 01:30 UNIQUE и payload hash
  • 03:00 Retry и conflict 409
  • 04:25 Regression tests
  • 05:25 Browser proof