закрыта задача 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
View File
@@ -10,7 +10,6 @@
- [✨ Брать у TVDB название на языке настройки и оригинальное название](items/tvdb-title-locale.md) — [general].language правит только TMDB и промпт LLM — TVDB отдаёт primary name, и при language=ru в карточку ревью и имя папки попадает 哪吒之魔童降世 вместо «Нэчжа» - [✨ Брать у TVDB название на языке настройки и оригинальное название](items/tvdb-title-locale.md) — [general].language правит только TMDB и промпт LLM — TVDB отдаёт primary name, и при language=ru в карточку ревью и имя папки попадает 哪吒之魔童降世 вместо «Нэчжа»
- [✨ Узаконить confidence-гейт авто-раскладки в спеке и сделать его выключаемым (дефолт 0.7)](items/auto-link-confidence-gate.md) — Решено (B): гейт оставляем как доп. проверку на ревью — выключаемый порог, дефолт 0.85→0.7, записать в спеку - [✨ Узаконить confidence-гейт авто-раскладки в спеке и сделать его выключаемым (дефолт 0.7)](items/auto-link-confidence-gate.md) — Решено (B): гейт оставляем как доп. проверку на ревью — выключаемый порог, дефолт 0.85→0.7, записать в спеку
- [🧹 Уточнить в спеке требование о re-read `source_type` перед `Add`](items/catched-source-type-refresh.md) — спека требует перечитывать source_type непосредственно перед добавлением, код перечитывает после тик-снимка — узкое namer-окно самоисцеляется через Retry и признано допустимым
- [🧹 Зафиксировать в спеке разделение Cancel и Dismiss по состояниям](items/dismiss-marker-lost.md) — спека обещает dismiss из любого состояния, код осознанно даёт Cancel для активных и Dismiss для терминальных — расходится буква, а не поведение - [🧹 Зафиксировать в спеке разделение Cancel и Dismiss по состояниям](items/dismiss-marker-lost.md) — спека обещает dismiss из любого состояния, код осознанно даёт Cancel для активных и Dismiss для терминальных — расходится буква, а не поведение
- [🐞 Тормозить опрос qBittorrent бэкоффом при недоступности и эскалировать устойчивый сбой](items/background-error-noise.md) — недоступный qBittorrent опрашивается каждые 5 с и даёт WARN на каждом тике: нужен экспоненциальный бэкофф до минутного потолка со сбросом по первому успеху и ERROR на устойчивой деградации - [🐞 Тормозить опрос qBittorrent бэкоффом при недоступности и эскалировать устойчивый сбой](items/background-error-noise.md) — недоступный qBittorrent опрашивается каждые 5 с и даёт WARN на каждом тике: нужен экспоненциальный бэкофф до минутного потолка со сбросом по первому успеху и ERROR на устойчивой деградации
- [🧹 Закрыть мелочи приёма: NoName в контексте, устаревшие комментарии, лог без причины, bencode-аллокации (N1, N3, N4, N5)](items/ingest-nits.md) — косметика приёма: NoName в контексте, устаревшие комментарии, лог, bencode-аллокации _(ревью 2026-07-08)_ - [🧹 Закрыть мелочи приёма: NoName в контексте, устаревшие комментарии, лог без причины, bencode-аллокации (N1, N3, N4, N5)](items/ingest-nits.md) — косметика приёма: NoName в контексте, устаревшие комментарии, лог, bencode-аллокации _(ревью 2026-07-08)_
@@ -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'а.