Раздача активной (downloading) загрузки, исчезнувшая из qBittorrent (удалил пользователь/другой клиент), делала задачу вечным зомби: поллинг промахивался по torrentFor, писал Warn и continue каждый тик — состояние не менялось, уведомления и телеметрии не было, checkTimeouts без торрента не срабатывал. Пропажей источника у downloading не владел никто (сверка рассинхрона покрывает только done/target_missing/orphaned, восстановление — failed/stuck). Активный цикл Poll теперь применяет тот же дебаунс пропажи источника, что и сверка рассинхрона (source_miss_count / source_missing_threshold): после порога подряд идущих промахов задача уходит downloading → failed с distinct error_code source_gone и уведомлением. До порога транзиентная недоступность qBit (рестарт демона) задачу не роняет. source_gone восстановлению сверкой не подлежит (удаление намеренно), но штатно retriable — Retry заново отдаёт сохранённый источник; Retry сбрасывает source_miss_count, чтобы вернувшаяся задача получила полное грейс-окно, а не упала снова на ближайшем тике. Ребро downloading → failed уже было в графе, миграций/полей БД нет. Спека download-tracking дополнена требованием, диаграмма workflow.md — ребром. Change downloading-source-gone заархивирован. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2.4 KiB
2.4 KiB
Tasks — Пропажа источника у активной загрузки
1. Код воркера
- 1.1 Ввести
errCodeSourceGone = "source_gone"в блок кодов ошибок (internal/worker/worker.go) с комментарием: distinct-код, восстановлению сверкой не подлежит, retriable вручную. - 1.2 Перестроить активный цикл в
Poll: при промахеtorrentForпрогонятьdebounceSource; при исчерпании порога —transition downloading → failed(source_gone); до порога —continue; при наличии источника — сброс счётчика и обычная сверка (captureInfohashes/captureSourceAddedAt/reconcile). - 1.3 Убедиться, что
debounceSourceвызывается и при наличии источника (сброс накопленных промахов). - 1.4
Retryсбрасываетsource_miss_countв 0 (рядом сSetRetriedAt), чтобы retriedsource_gone-задача получила полное грейс-окно, а не падала сразу (см. design «Сброс source_miss_count при Retry»).
2. Тесты
- 2.1 Промах < порога → задача остаётся
downloading. - 2.2 Промах ≥ порога →
downloading → failed/source_gone+EventFailed. - 2.3 Возврат раздачи до порога → счётчик сброшен, задача ведётся обычной сверкой.
- 2.4
source_goneне воскрешаетсяreconcileRecovery(источник вернулся — задача остаётсяfailed). - 2.5
Retryзадачиsource_goneсбрасываетsource_miss_count: после retry с ещё-не-видимой раздачей задача остаётсяdownloadingполный порог тиков (грейс-окно не съедено).
3. Документация
- 3.1
docs/specs/workflow.md: добавить реброdownloading → failed(source_gone, пропажа источника) в диаграмму и список переходов.
4. Верификация
- 4.1
task test/task lintзелёные. - 4.2
openspec validate downloading-source-gone --strict.