Files
jellybit/openspec/changes/archive/2026-07-08-downloading-source-gone/tasks.md
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

2.4 KiB
Raw Blame History

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), чтобы retried source_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.