Жизненный цикл: claim-токен распознавания, индексация хешей, retry сломанного торрента
Три мелких фикса из docs/backlog/review-lifecycle-minor.md (ревью Fable 2026-07-08). MINOR-9 (I/O под глобальным w.mu) осознанно waive для one-user home-сервера — не трогаем. MINOR-8: claim-токен распознавания. recognizeOne фиксирует updated_at на момент claim (перечитывая запись после перехода в recognizing), а finishRecognition коммитит результат, только если токен совпал. Иначе за время LLM-вызова задачу увели из recognizing и вернули обратно (cancel → relink revive) — это уже другой эпизод, устаревший результат отбрасываем, задача остаётся в recognizing для перезапуска поллингом. NIT-11: lookup-мапы (byHash/live/torrentByInfohash) больше не индексируют усечённый 40-hex t.Hash v2-only торрентов. Новый хелпер torrentIndexHashes зеркалит выбор torrentHashes: t.Hash берём только при отсутствии обоих infohash_v1/v2. Убирает теоретический ложный матч по коллизии длины. NIT-12: retry живого, но сломанного торрента (error/missingFiles) теперь отклоняется с подсказкой починить раздачу (recheck) в qBittorrent, вместо бессмысленной переотдачи источника (сверка тут же вернула бы задачу в failed). Повторный Add — только когда раздачи в qBittorrent нет. Меняет спеку state-reconciliation → дельта openspec/changes/2026-07-17-retry-reject-broken-torrent (не архивировал). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,42 @@
|
||||
## Why
|
||||
|
||||
Retry задачи в `failed`/`stuck`, чей торрент ЖИВ в qBittorrent, но в состоянии
|
||||
ошибки (`error`/`missingFiles`), сейчас повторно отдаёт источник. На живом
|
||||
сломанном торренте это бесполезно: qBittorrent отвергает дубль, задача уходит в
|
||||
`downloading`, а на ближайшем тике сверки `classErrored` тут же возвращает её в
|
||||
`failed` (+ дебаунс уведомления). Пользователю retry выглядит сломанным, а
|
||||
реальное лекарство (перепроверка/`recheck`/восстановление файлов в qBittorrent)
|
||||
не подсказано (находка ревью NIT-12).
|
||||
|
||||
## What Changes
|
||||
|
||||
- **Retry сломанного живого торрента отклоняется**, а не переотдаёт источник.
|
||||
Отказ несёт понятное сообщение: починить раздачу (`recheck`/восстановить
|
||||
файлы) в qBittorrent и повторить. Состояние задачи не меняется, повторного
|
||||
`Add` не происходит.
|
||||
- Повторный `Add` при retry остаётся только для случая, когда раздачи в
|
||||
qBittorrent НЕТ (перецепка к здоровому живому торренту — без `Add`, как и
|
||||
раньше).
|
||||
|
||||
## Capabilities
|
||||
|
||||
### New Capabilities
|
||||
|
||||
Нет.
|
||||
|
||||
### Modified Capabilities
|
||||
|
||||
- `state-reconciliation`: требование «Ручной повтор зависшей/упавшей загрузки из
|
||||
транспортов» — ветка живого сломанного торрента меняет исход с «повторно отдать
|
||||
источник» на «отклонить с подсказкой про `recheck`». Прочие ветки retry (нет
|
||||
раздачи → `Add`; жив и здоров → перецепка без `Add`; сброс базиса `retried_at`)
|
||||
без изменений.
|
||||
|
||||
## Impact
|
||||
|
||||
- **Спеки:** дельта `state-reconciliation` (одно MODIFIED-требование).
|
||||
- **Код:** `internal/worker/worker.go` — `Retry` (ветка `alive && classErrored`
|
||||
→ отказ `ErrConflict` с сообщением вместо `reAdd`).
|
||||
- **Тесты:** `internal/worker/worker_test.go` — отклонение retry на живом
|
||||
сломанном торренте (`error`/`missingFiles`), контроль перецепки здорового.
|
||||
- **Миграции БД:** нет.
|
||||
Reference in New Issue
Block a user