feat: expand platform APIs, sources, and test coverage
Some checks failed
CI/CD Pipeline / Run Tests (pull_request) Successful in 1m53s
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) Failing after 2m54s
CI/CD Pipeline / Telegram Notify Success (pull_request) Has been skipped
Some checks failed
CI/CD Pipeline / Run Tests (pull_request) Successful in 1m53s
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) Failing after 2m54s
CI/CD Pipeline / Telegram Notify Success (pull_request) Has been skipped
This commit is contained in:
128
docs/adr/ADR-011: Idempotency and Retry Strategy.md
Normal file
128
docs/adr/ADR-011: Idempotency and Retry Strategy.md
Normal file
@@ -0,0 +1,128 @@
|
||||
# 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
|
||||
|
||||
Следующими связанными решениями должны быть:
|
||||
- политика дедупликации данных
|
||||
- модель частичной загрузки и фиксации прогресса
|
||||
- политика конкурентного запуска задач
|
||||
Reference in New Issue
Block a user