Files
mostovik-backend/docs/adr/ADR-011: Idempotency and Retry Strategy.md
Aleksandr Meshchriakov 25176f31b4
Some checks failed
CI/CD Pipeline / Telegram Notify Success (push) Has been cancelled
CI/CD Pipeline / Run Tests (push) Has been cancelled
CI/CD Pipeline / Code Quality Checks (push) Has been cancelled
CI/CD Pipeline / Code Quality Checks (pull_request) Successful in 1m42s
CI/CD Pipeline / Run Tests (pull_request) Successful in 2m25s
CI/CD Pipeline / Telegram Notify Success (pull_request) Successful in 1m34s
fix pre-commit
2026-03-17 13:55:34 +01:00

129 lines
7.6 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# ADR-011: Idempotency and Retry Strategy for Background Tasks
## Status
Accepted
## Context
Система активно использует фоновые задачи Celery для:
- загрузки данных из внешних источников
- инкрементальной синхронизации
- обработки файлов
- периодических сканирований и парсинга
Внешние источники и фоновые очереди не гарантируют:
- exactly-once delivery
- стабильность сети
- неизменность ответа источника
- отсутствие повторных запусков задач
- отсутствие ручных перезапусков оператором
Также возможны следующие сценарии:
- worker завершился после частичной записи данных
- задача была запущена повторно по retry
- beat и ручной запуск вызвали одинаковую задачу почти одновременно
- внешняя система ответила ошибкой после того, как часть данных уже была получена
- оператор повторно инициировал синхронизацию за тот же период
Для такого класса системы идемпотентность является не оптимизацией, а обязательным архитектурным требованием.
## Decision
Все фоновые задачи, изменяющие данные или взаимодействующие с нестабильными внешними источниками, должны проектироваться как idempotent-first.
### Основные правила
1. Повторный запуск одной и той же задачи не должен приводить к неконтролируемому дублированию данных.
2. Результат повторного выполнения должен быть либо:
- идентичен первому успешному выполнению,
- либо безопасно приводить систему к тому же целевому состоянию.
3. Retry рассматривается как нормальный сценарий эксплуатации, а не как исключение.
### Идемпотентность обеспечивается за счет
- уникальных ограничений на уровне БД для естественных бизнес-ключей
- upsert/update-or-create подходов там, где это возможно
- явной привязки загружаемых данных к периоду, источнику, типу выгрузки или внешнему идентификатору
- дедупликации на уровне сервисного слоя перед записью
- разделения этапов extract / transform / load
- фиксации статуса фоновой задачи и контекста её выполнения
- запрета на "append-only" запись без проверки уникальности для синхронизируемых сущностей
### Retry policy
Retry допускается только для временных ошибок:
- сетевые сбои
- временная недоступность внешнего источника
- rate limiting
- временные ошибки брокера или инфраструктуры
- временные проблемы с файловой системой или внешним сервисом
Retry не должен безусловно выполняться для:
- ошибок валидации входных данных
- ошибок схемы/контракта источника
- систематических ошибок парсинга
- нарушений инвариантов модели
- ошибок конфигурации
Для retry необходимо:
- использовать ограниченное число повторов
- использовать backoff
- логировать причину повтора
- сохранять контекст периода/источника/операции
### Concurrency policy
Для задач, работающих по одному и тому же периоду или источнику, должна применяться логическая защита от параллельного конкурентного запуска.
Предпочтительный порядок контроля:
1. блокировка на уровне бизнес-контракта задачи
2. проверка существующего job-run статуса
3. защита уникальными ограничениями БД
4. безопасное повторное выполнение как fallback
### Operational policy
Задача считается корректной, если после:
- retry
- повторного ручного запуска
- запуска за уже обработанный период
- частичного падения и повторного восстановления
данные остаются консистентными и не требуют ручной чистки в обычном сценарии эксплуатации.
## Consequences
### Positive
- система устойчива к повторным запускам и временным отказам
- снижается риск дублирования данных
- упрощается эксплуатация и ручной re-run задач
- Celery retry становится безопасным штатным механизмом
- упрощается восстановление после сбоев worker-процессов
### Negative
- усложняется реализация сервисного слоя и моделей
- требуется дисциплина в проектировании бизнес-ключей
- часть задач становится медленнее из-за дополнительных проверок
- нужны дополнительные ограничения и индексы в БД
- необходимо явно проектировать поведение при partial success
## Alternatives considered
### 1. At-most-once execution
Отклонено, так как не соответствует реальной природе фоновой обработки и нестабильных внешних интеграций.
### 2. Полагаться только на Celery retry без идемпотентности на уровне домена
Отклонено, так как это приводит к дублированию данных и хрупкому поведению при сбоях.
### 3. Полная ручная очистка данных перед каждым повторным запуском
Отклонено, так как не масштабируется и опасно в эксплуатации.
## Notes
Следующими связанными решениями должны быть:
- политика дедупликации данных
- модель частичной загрузки и фиксации прогресса
- политика конкурентного запуска задач