Files
avandClaude Opus 4.8 3a00fde058 Жизненный цикл: уборка торрента при отмене во время добавления (F3/NIT-13)
Отмена задачи (catched→cancelled) в окно, пока worker вне блокировки выводит
имя (LLM) и делает qbt.Add, оставляла добавленный торрент в qBittorrent без
задачи-владельца: PromoteCatched корректно пропускал переход, но источник уже
качался/сидировал вечно, а усыновить его назад нельзя (хеши принадлежат
отменённой задаче). Спека покрывала переход состояния, но не побочный эффект.

Комбинированная защита в processCatched:
- re-read состояния под w.mu прямо перед qbt.Add — при отмене источник не
  добавляется вовсе (сужает окно гонки);
- свежий листинг перед add подтверждает отсутствие infohash — признак «своего»
  торрента; при сбое листинга/присутствии add не делаем (усыновит следующий тик);
- при отмене в окне после add (промах PromoteCatched, подтверждённый re-read'ом
  state != catched) — уборка добавленного нами торрента qbt.Delete(_, true);
- WARN/ERROR-логи по этому пути с корреляцией по download_id, без секретов.

Гарантия «удаляем только своё»: удаление-с-данными достижимо ТОЛЬКО после
подтверждённого отсутствия infohash перед add, поэтому пред-существующий/чужой
торрент с тем же хешем никогда не сносится (негативный инвариант). Обоснование
по инварианту «источник неприкосновенен» — в design.md изменения.

Дельта — download-tracking (требование «Добавление пойманной загрузки в
qBittorrent»): re-read перед add, подтверждение отсутствия, уборка при отмене,
негативный сценарий. Тесты покрывают все ветки (skip-before-add, cleanup после
add, пред-существующий не удаляется, сбой БД не удаляет, сбой листинга не
добавляет).

Change archived: 2026-07-17-cancel-during-add-cleanup.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-17 22:10:21 +03:00

45 lines
3.6 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.
## 1. Код
- [x] 1.1 В `processCatched` (`internal/worker/worker.go`), на обычном пути
добавления, ПОСЛЕ вывода имени и НЕПОСРЕДСТВЕННО перед `qbt.Add`: под `w.mu`
перечитать запись и, если `state != catched`, `add` не делать и загрузку
пропустить (D1)
- [x] 1.2 Там же (вне `w.mu`) добавить свежий листинг присутствия любого из
infohash загрузки в qBittorrent перед `add` (переиспользовать `qbt.Torrents`);
при присутствии — `add` не делать, пропустить (усыновит следующий тик); при
СБОЕ листинга — `add` не делать, `WARN`, повтор на следующем тике (D2, Б1)
- [x] 1.3 При неуспехе `PromoteCatched` после успешного `add` — под `w.mu`
перечитать состояние: только если `state != catched` (подтверждённая отмена) —
удалить добавленный торрент с данными `qbt.Delete(ctx, HashList, true)`; `WARN`
об оставленном/удалённом торренте; `ERROR` при сбое удаления. Если `state ==
catched` (транзиентный сбой БД) или re-read упал — НЕ удалять, `WARN`
«promote failed, will retry» (D3, Б2). Решение по состоянию, не по тексту
ошибки (см. errors.md)
- [x] 1.4 Убедиться, что путь уборки достижим только после подтверждённого
отсутствия перед `add` (негативный инвариант «удаляем только своё»)
## 2. Тесты
- [x] 2.1 Обновить `TestProcessCatchedCancelledDuringAddSkipsPromote`: отмена во
время namer → `qbt.Add` НЕ вызывается (re-read перед add), состояние остаётся
`cancelled` (было: Add вызывался)
- [x] 2.2 Новый тест: отмена в окне ПОСЛЕ `add` (hook на `Add`, ставящий
`cancelled`) → `qbt.Delete` вызван с `deleteFiles=true` по infohash загрузки,
состояние `cancelled`
- [x] 2.3 Новый тест (негативный инвариант): infohash появился в qBittorrent во
время namer (hook на namer) → перед `add` листинг видит присутствие → `qbt.Add`
НЕ вызывается, `qbt.Delete` НЕ вызывается (чужие данные не трогаем)
- [x] 2.4 Новый тест (Б2): сбой `PromoteCatched` при `state == catched`
(транзиентная ошибка БД, без отмены) → торрент НЕ удаляется (`qbt.Delete` не
вызван)
- [x] 2.6 Новый тест (Б1, safety-critical): свежий листинг перед `add` упал
(второй вызов `Torrents`) → `Add`/`Delete` НЕ вызваны, остаётся `catched`
- [x] 2.5 Регрессия: штатный успех (нет отмены) по-прежнему добавляет и
промоутит (`TestProcessCatchedAddsToQbit`); усыновление присутствующего и сбой
листинга тика (`TestProcessCatchedListErrorKeepsCatched`) — без изменений
## 3. Спека
- [x] 3.1 MODIFIED-требование «Добавление пойманной загрузки в qBittorrent» в
`download-tracking`; `openspec validate cancel-during-add-cleanup --strict`