Files
T
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

59 lines
4.0 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.
# download-tracking Specification
## ADDED Requirements
### Requirement: Пропажа источника у активной загрузки
Поллинг активных загрузок (`downloading`) SHALL обнаруживать пропажу источника:
если раздача, совпадающая с любым из известных хешей загрузки, отсутствует в
выдаче qBittorrent, система SHALL применять **тот же дебаунс пропажи источника**,
что и сверка рассинхрона (счётчик `source_miss_count`, порог
`[worker].source_missing_threshold`; см. `state-reconciliation` «Дебаунс пропажи
источника»). Любое обнаружение раздачи SHALL сбрасывать счётчик.
После `N` подряд идущих тиков без раздачи (`N =
[worker].source_missing_threshold`) система SHALL переводить загрузку
`downloading → failed` с `error_code` `source_gone` и уведомлять автора. До
достижения порога загрузка SHALL оставаться в `downloading` (транзиентная
недоступность qBittorrent, например рестарт демона, не должна ронять задачу).
`source_gone` система SHALL трактовать как отдельную причину, отличную от
`qbit_error` (реальная ошибка qBittorrent) и от `magnet_timeout`/`stalled` (наша
нетерпеливость). Восстановлению сверкой (`reconcileRecovery`) `source_gone`
подлежать SHALL NOT — удаление источника из qBittorrent намеренно, молча
воскрешать задачу нельзя. Задача SHALL оставаться штатно восстановимой вручную
(`Retry` заново отдаёт сохранённый источник в qBittorrent).
Состояние `catched` этим правилом затрагиваться SHALL NOT: у пойманной загрузки
раздачи в qBittorrent ещё нет по дизайну (см. «catched не считается пропажей
раздачи»), а цикл активных загрузок листает только `downloading`.
#### Scenario: Источник пропал у активной загрузки дольше порога
- **GIVEN** загрузка в `downloading`, чья раздача удалена из qBittorrent
- **WHEN** раздача отсутствует `source_missing_threshold` подряд идущих тиков
- **THEN** загрузка переходит в `failed` с `error_code` `source_gone`
- **AND** автор загрузки уведомляется
#### Scenario: Кратковременная пропажа источника не роняет задачу
- **GIVEN** загрузка в `downloading`
- **WHEN** раздача отсутствует в qBittorrent меньше `source_missing_threshold`
тиков подряд
- **THEN** загрузка остаётся в `downloading`
#### Scenario: Возврат раздачи сбрасывает счётчик
- **GIVEN** загрузка в `downloading` с накопленными промахами источника (меньше
порога)
- **WHEN** раздача снова обнаружена в qBittorrent
- **THEN** счётчик промахов сбрасывается в ноль и загрузка ведётся обычной
сверкой состояния
#### Scenario: source_gone не воскрешается сверкой
- **GIVEN** загрузка в `failed` с `error_code` `source_gone`
- **WHEN** её раздача снова появляется в qBittorrent и продвигается
- **THEN** сверка восстановления её не трогает — задача остаётся в `failed` до
ручного `Retry`