Files
avandClaude Opus 4.8 2a5a65f2d5 Приём: пропажа источника у активной загрузки → failed(source_gone) (MAJOR-3)
Раздача активной (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>
2026-07-08 18:05:04 +03:00

39 lines
2.4 KiB
Markdown
Raw Permalink 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.
# Tasks — Пропажа источника у активной загрузки
## 1. Код воркера
- [x] 1.1 Ввести `errCodeSourceGone = "source_gone"` в блок кодов ошибок
(`internal/worker/worker.go`) с комментарием: distinct-код, восстановлению
сверкой не подлежит, retriable вручную.
- [x] 1.2 Перестроить активный цикл в `Poll`: при промахе `torrentFor` прогонять
`debounceSource`; при исчерпании порога — `transition downloading → failed`
(`source_gone`); до порога — `continue`; при наличии источника — сброс счётчика
и обычная сверка (`captureInfohashes`/`captureSourceAddedAt`/`reconcile`).
- [x] 1.3 Убедиться, что `debounceSource` вызывается и при наличии источника
(сброс накопленных промахов).
- [x] 1.4 `Retry` сбрасывает `source_miss_count` в 0 (рядом с `SetRetriedAt`),
чтобы retried `source_gone`-задача получила полное грейс-окно, а не падала
сразу (см. design «Сброс source_miss_count при Retry»).
## 2. Тесты
- [x] 2.1 Промах < порога → задача остаётся `downloading`.
- [x] 2.2 Промах ≥ порога → `downloading → failed`/`source_gone` + `EventFailed`.
- [x] 2.3 Возврат раздачи до порога → счётчик сброшен, задача ведётся обычной
сверкой.
- [x] 2.4 `source_gone` не воскрешается `reconcileRecovery` (источник вернулся —
задача остаётся `failed`).
- [x] 2.5 `Retry` задачи `source_gone` сбрасывает `source_miss_count`: после
retry с ещё-не-видимой раздачей задача остаётся `downloading` полный порог
тиков (грейс-окно не съедено).
## 3. Документация
- [x] 3.1 `docs/specs/workflow.md`: добавить ребро `downloading → failed`
(`source_gone`, пропажа источника) в диаграмму и список переходов.
## 4. Верификация
- [x] 4.1 `task test` / `task lint` зелёные.
- [x] 4.2 `openspec validate downloading-source-gone --strict`.