Ревью: preflight готовности источника для команд ревью (MAJOR-5)
Команды ревью проверяли только наличие раздачи в qBittorrent, но не её готовность. Недокачанную задачу можно припарковать в deferred, затем «Распознать заново» → recognizing → авто-раскладка (Rerecognize/Refine/ SetType не ставят force_review) → хардлинки на неполные файлы. Даже ручной Apply не имел preflight завершённости. Вводим ensureSourceReady (classify(t.State)==classReady) вместо ensureSourcePresent во всех командах, которым нужен источник (Relink/ Rerecognize/Refine/SetType), и inline-проверку класса в Apply — последний рубеж перед хардлинками. Недокачанный источник → отдельный sentinel ErrNotReady (409) с actionable-текстом «торрент ещё качается» в web и Telegram, без reconcile (состояние deferred/review легитимно). Change review-readiness-preflight заархивирован, дельта влита в openspec/specs/review. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,45 @@
|
||||
## 1. Preflight готовности источника
|
||||
|
||||
- [x] 1.1 В `internal/worker/errors.go` добавить sentinel
|
||||
`var ErrNotReady = errors.New(...)` (отдельный от `ErrConflict`).
|
||||
- [x] 1.2 В `internal/worker/reconcile.go` добавить `ensureSourceReady(ctx, d, op)`:
|
||||
найти торрент через `torrentByInfohash`; нет источника →
|
||||
`reconcileToReality(false)` + `ErrConflict «источник удалён из qBittorrent»`;
|
||||
есть, но `classify(t.State) != classReady` → `ErrNotReady «op: торрент ещё
|
||||
качается»` без `reconcileToReality`.
|
||||
- [x] 1.3 Заменить `ensureSourcePresent` на `ensureSourceReady` в командах
|
||||
`Rerecognize`, `Refine`, `SetType`, `Relink` (`internal/worker/review.go`);
|
||||
удалить осиротевший `ensureSourcePresent`.
|
||||
- [x] 1.4 В `Apply` добавить проверку класса на уже полученном торренте
|
||||
(`classify(t.State) != classReady → ErrNotReady «торрент ещё качается»`),
|
||||
без второго запроса к qBittorrent.
|
||||
|
||||
## 2. Трансляция ошибки в транспортах
|
||||
|
||||
- [x] 2.1 `internal/httpapi` `classifyErr`: кейс
|
||||
`errors.Is(err, worker.ErrNotReady) → 409, «торрент ещё качается, дождитесь
|
||||
докачки»` (отдельно от генерик-`ErrConflict`).
|
||||
- [x] 2.2 `internal/tgbot`: в обработчике callback-действий ветка
|
||||
`errors.Is(err, worker.ErrNotReady)` → сообщение «Торрент ещё качается…»,
|
||||
иначе прежний `opErr(...)`.
|
||||
|
||||
## 3. Тесты
|
||||
|
||||
- [x] 3.1 Тест: недокачанный источник (`downloading`-класс) отклоняет
|
||||
`Rerecognize`/`Refine`/`SetType`/`Relink` с `ErrNotReady`, состояние задачи
|
||||
не меняется, авто-раскладка не запускается.
|
||||
- [x] 3.2 Тест: недокачанный источник отклоняет `Apply` — хардлинки не
|
||||
создаются, состояние не меняется.
|
||||
- [x] 3.3 Тест: готовый источник (`classReady`) пропускает те же команды как
|
||||
раньше (регресс не сломан); отсутствие источника по-прежнему приводит к
|
||||
реальности и отказывает.
|
||||
- [x] 3.4 Тест транспорта: `classifyErr(ErrNotReady) == 409` с конкретным
|
||||
текстом (`internal/httpapi`).
|
||||
|
||||
## 4. Ревью и сверка
|
||||
|
||||
- [x] 4.1 `task test` и `task lint` зелёные.
|
||||
- [x] 4.2 Ревью кода (второй чекпоинт) перед archive.
|
||||
- [x] 4.3 `openspec validate review-readiness-preflight --strict` зелёный;
|
||||
удалить `docs/backlog/review-major5-readiness-preflight.md` из беклога и
|
||||
строку из индекса (суть переехала в спеку).
|
||||
Reference in New Issue
Block a user