закрыта задача catched-source-type-refresh

This commit is contained in:
av
2026-08-06 14:45:01 +03:00
parent 30ee598547
commit 5a8c439899
2 changed files with 0 additions and 81 deletions
@@ -1,80 +0,0 @@
# 🧹 Уточнить в спеке требование о re-read `source_type` перед `Add`
- **Тип:** chore
- **Категория:** Ядро продукта
- **Зачем:** спека требует перечитывать source_type непосредственно перед добавлением, код перечитывает после тик-снимка — узкое namer-окно самоисцеляется через Retry и признано допустимым
Найдено аудитом capability **download-tracking** (сверка код↔спека после пачки
lifecycle-задач). Пред-существующее, вне scope задачи F3/cancel-cleanup — T4
осознанно вынес это за рамки и задокументировал в своём design.md.
## Суть
`processCatched` (`internal/worker/worker.go:442-517`) строит `addReq` из записи
`cur`, перечитанной под замком на `:447-455`, **до** вызова namer'а (LLM, секунды,
вне замка, `:463-478`). Затем на `:484-491` под замком перечитывается `before`,
но `addReq` из него **не пересобирается** — проверяется только `state == catched`.
Если апгрейд пойманной magnet-задачи до `.torrent`
(`UpgradeCatchedMagnetToTorrent`, `internal/store/download.go:392`) отработает
именно в окне namer'а (приём принял `.torrent` с тем же infohash, `state`
остаётся `catched`), воркер добавит **magnet-ссылку из устаревшего снимка**, хотя
в БД уже `source_type=torrent`.
Спека (`openspec/specs/download-tracking/spec.md`, раздел про добавление по
`source_type`) требует перечитывать `source_type` **под блокировкой переходов
непосредственно перед добавлением** — сейчас это требование в окне namer'а
нарушается.
## Насколько больно
Ограниченно и самоисцеляемо: на закрытом трекере magnet без метаданных зависнет
в `metaDL` → предохранитель `magnet_timeout``failed`; ручной `Retry`
перечитает актуальный `source_type` и добьёт. Данные не страдают, инвариант
«источник неприкосновенен» не задет. Окно узкое (апгрейд должен лечь ровно в
LLM-вызов по тому же infohash). Поэтому средний, не высокий.
## Решение (2026-08-06): B — привести спеку к коду
Рациональ требования — «не полагаться на снимок, снятый ранее вне блокировки» —
уже выполнен первым re-read под замком на `:447`. Требование переформулируется
как «перечитывать `source_type` под блокировкой после тик-снимка», а узкое
namer-окно принимается явно: оно самоисцеляется через `magnet_timeout`
`failed``Retry`.
Вариант A (пересобирать `addReq` из `before` под замком) отклонён: не
однострочник — `sourceAddParts` читает байты `.torrent`, держать это под
блокировкой нельзя, а при апгрейде корректно был бы и повторный вызов namer'а.
Заводить его отдельной задачей, только если узкое окно окажется реальной болью в
эксплуатации.
Кода задача не трогает: наблюдаемое поведение остаётся прежним, меняется
заявленное.
## Затрагивает
- `openspec/specs/download-tracking/spec.md` — требование про re-read
`source_type` перед добавлением, его формулировка и сценарии;
- дельта-спека change'а — новых сценариев с namer-окном может потребоваться два
(апгрейд до тик-снимка и апгрейд в окне namer'а);
- `internal/worker/worker.go` — только чтение, правок не предполагается.
## Критерии приёмки
- Требование спеки описывает фактическое поведение: re-read `source_type` под
блокировкой после тик-снимка, апгрейд в окне namer'а назван допустимым и
самоисцеляемым (оракул: `openspec validate --strict`).
- В спеке есть сценарий, покрывающий апгрейд в окне namer'а с исходом «magnet из
снимка, дальше `magnet_timeout``failed``Retry`» (оракул: тот же прогон
плюс существующий `TestProcessCatchedReReadsSourceTypeUnderLock` продолжает
проходить без правок).
- Ни один файл под `internal/` в диффе не изменён (оракул: `git diff --stat`
в отчёте ревью).
## Ссылки
- `internal/worker/worker.go:442-517``processCatched`
- `internal/store/download.go:392``UpgradeCatchedMagnetToTorrent`
- `openspec/specs/download-tracking/spec.md` — требование про `source_type`
- Тест `TestProcessCatchedReReadsSourceTypeUnderLock` покрывает апгрейд между
тик-снимком и re-read, но **не** окно namer'а.