Команда Defer гардила только IsTerminal() и потому принимала catched (торрент ещё не добавлен в qBittorrent). Defer из catched уводил задачу в лимбо → необратимый deleted: processCatched листает только catched и больше её не подхватывал, а последующие команды через отсутствие источника выводили deleted (ноль исходящих рёбер), хотя байты .torrent лежат в download_torrent. - Worker.Defer отклоняет catched с ErrConflict (транслируется в 409 / редирект с сообщением); прочие не-терминальные состояния, где раздача уже есть, принимает как раньше. - Снято мёртвое ребро графа catched → deferred (allowedTransitions); инвариант «deferred из каждого не-терминального» уточнён: кроме пре-источникового catched. catched — единственное состояние без раздачи среди не-терминальных. - Тесты: Defer из catched отклоняется и не меняет состояние; инвариант графа обновлён + негативная проверка ребра. - OpenSpec: MODIFIED «Команды ревью и их эффекты» (review) с позитивным и негативным сценариями; change заархивирован, дельта влита в спеку. - Беклог: закрыта review-major6-defer-catched. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
31 lines
1.7 KiB
Markdown
31 lines
1.7 KiB
Markdown
## 1. Код
|
|
|
|
- [x] 1.1 `internal/worker/review.go` — в `Defer` после `GetDownload` добавить
|
|
гард: `d.State == store.StateCatched` → `ErrConflict` с понятным сообщением
|
|
(отложить можно только после добавления торрента в qBittorrent), не меняя
|
|
состояние. Существующий гард `IsTerminal()` оставить.
|
|
- [x] 1.2 `internal/store/download.go` — убрать `StateDeferred` из исходящих
|
|
`StateCatched` в `allowedTransitions`; уточнить комментарий инварианта
|
|
`deferred` («из КАЖДОГО не-терминального» → «кроме пре-источникового
|
|
`catched`»).
|
|
|
|
## 2. Тесты
|
|
|
|
- [x] 2.1 `internal/worker/review_test.go` — `Defer` из `catched` возвращает
|
|
`ErrConflict`, состояние остаётся `catched`; контроль — `Defer` из `review`
|
|
по-прежнему уводит в `deferred` (существующий `TestDefer`).
|
|
- [x] 2.2 `internal/store/transition_test.go` — обновить инвариант `deferred`:
|
|
легальная цель из каждого не-терминального состояния, КРОМЕ `catched` (и
|
|
самопереход `deferred`); добавить проверку, что `catched → deferred` не
|
|
легально.
|
|
|
|
## 3. Спека
|
|
|
|
- [x] 3.1 MODIFIED-требование «Команды ревью и их эффекты» в `review`;
|
|
`openspec validate --strict` зелёный.
|
|
|
|
## 4. Проверка
|
|
|
|
- [x] 4.1 `task test` и `task lint` зелёные; существующие тесты
|
|
worker/httpapi/store не сломаны.
|