Восстановление зависших загрузок и уведомления о падении (state-reconciliation)
Долгий metaDL больше не убивается агрессивным таймаутом: дефолт magnet_timeout 30m → 24h (страховочный предохранитель), базис отсчёта — added_on из qBittorrent, а не created_at (переживает retry/усыновление). Авто-восстановление: фоновая сверка возвращает в поток задачи, упавшие по нашей нетерпеливости (magnet_timeout/stalled), когда источник ожил и продвинулся за условие падения (downloading/completed по статусу торрента); qbit_error не воскрешается. Конфликт idempotency (infohash занят другой активной задачей) — оставляем в failed. Уведомления: любой переход в failed/stuck пингует автора (включая приёмный qbit_add через ingest), с дебаунсом против спама при флаппинге stalled. Ручной retry добавлен в веб-UI и Telegram; Retry перецепляется к живому торренту вместо слепого Add. Дельта state-reconciliation влита в живые спеки; обновлён workflow.md. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
+32
-7
@@ -14,7 +14,7 @@ stateDiagram-v2
|
||||
|
||||
downloading --> completed: файлы на месте
|
||||
downloading --> stuck: stalledDL дольше stuck_after
|
||||
downloading --> failed: metaDL дольше magnet_timeout / error
|
||||
downloading --> failed: metaDL дольше magnet_timeout (страховка) / error
|
||||
|
||||
completed --> recognizing
|
||||
|
||||
@@ -36,8 +36,10 @@ stateDiagram-v2
|
||||
reverted --> recognizing: Привязать заново
|
||||
cancelled --> recognizing: Привязать заново
|
||||
|
||||
stuck --> downloading: Retry
|
||||
failed --> downloading: Retry
|
||||
stuck --> downloading: Retry / сверка (раздача ожила)
|
||||
failed --> downloading: Retry / сверка (метаданные пришли)
|
||||
failed --> completed: сверка (торрент уже готов)
|
||||
stuck --> completed: сверка (торрент уже готов)
|
||||
|
||||
done --> target_missing: сверка — цель удалена
|
||||
done --> orphaned: сверка — источник пропал
|
||||
@@ -147,10 +149,33 @@ SQLite; `worker` периодически сверяет qBittorrent с БД и
|
||||
проверку (готовность не объявляем, даже если флаги «UP»).
|
||||
- **ещё качается:** `downloading`/`stalledDL`/`metaDL`/`forcedMetaDL`/
|
||||
`queuedDL`/`checkingDL`/`forcedDL`/`pausedDL`/`stoppedDL`.
|
||||
- **застряло/ошибка по таймауту:** `metaDL`/`forcedMetaDL` дольше
|
||||
`magnet_timeout` → `failed`; `stalledDL` дольше `stuck_after` → `stuck`
|
||||
(восстановимо ретраем). Возраст считаем от создания задачи.
|
||||
- **ошибка:** `error`/`missingFiles` → `failed`.
|
||||
- **застряло по таймауту (страховка):** `metaDL`/`forcedMetaDL` дольше
|
||||
`magnet_timeout` → `failed`; `stalledDL` дольше `stuck_after` → `stuck`.
|
||||
`magnet_timeout` — **редкий страховочный предохранитель** (дефолт `24h`), а
|
||||
не рабочий механизм: долгий `metaDL` (медленные трекеры/мало пиров) — это
|
||||
норма, его не убиваем агрессивно. Возраст считаем от времени добавления
|
||||
торрента в qBittorrent (`added_on`), а не от создания задачи (базис
|
||||
переживает retry и усыновление).
|
||||
- **ошибка:** `error`/`missingFiles` → `failed` (`error_code` `qbit_error`) —
|
||||
это настоящий провал, в отличие от таймаута.
|
||||
|
||||
### Уведомление и восстановление
|
||||
|
||||
- Любой переход в `failed`/`stuck` **уведомляет** автора загрузки
|
||||
(`notifier`), чтобы падение не оставалось незамеченным — включая приёмное
|
||||
падение `qbit_add` (не удалось добавить в qBittorrent), которое идёт мимо
|
||||
поллинг-цикла. Повторные падения одной задачи в пределах окна дебаунса
|
||||
уведомляют лишь раз — чтобы мерцающий `stalled`-торрент
|
||||
(`stuck`↔`downloading`) не спамил.
|
||||
- `failed`/`stuck` из-за нашей нетерпеливости (`error_code` `magnet_timeout`/
|
||||
`stalled`) **не тупик**: фоновая сверка возвращает задачу в поток, как
|
||||
только источник в qBittorrent ожил и продвинулся за условие падения
|
||||
(получил метаданные → `downloading`; уже готов → `completed`). Пока торрент
|
||||
всё ещё в `metaDL`/`stalledDL`, задача остаётся упавшей (без зацикливания).
|
||||
Настоящие провалы (`qbit_error`) сверкой не воскрешаются.
|
||||
- Дополнительно доступен **ручной retry** из веб-UI и Telegram (не только
|
||||
REST): возвращает в `downloading`, перецепляясь к живому торренту без
|
||||
повторного `Add`.
|
||||
|
||||
Пути файлов берём из API (`save_path` + относительные имена из
|
||||
`/torrents/files`, уже включающие корневую папку торрента), не из
|
||||
|
||||
Reference in New Issue
Block a user