Приём: усыновление присутствующего в qBittorrent торрента вместо дубль-Add (409)
processCatched перед Add проверяет присутствие торрента в qBittorrent (один листинг на тик): если раздача уже есть — усыновляем (promote catched→downloading без повторного Add и без LLM-namer, имя из раздачи), иначе добавляем как раньше. Это убирает бесконечный цикл дубль-Add → 409 → ретрай и лишние вызовы LLM. Инвариант приёма «одна активная на infohash» делает различие «наш/чужой» ненужным. source_type перечитывается под замком (сужение гонки апгрейда F6); при недоступности qBittorrent тик пропускается без вызова LLM. Дедуп на приёме (дубль на уже активную задачу) теперь отражается явным ответом бота «дубль уже активной #id — добавление отменено». Спека download-tracking обновлена (OpenSpec change заархивирован); закрыта задача беклога review-f2-promote-without-add. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,37 @@
|
||||
## 1. Усыновление в processCatched
|
||||
|
||||
- [x] 1.1 В начале `processCatched` один раз получить листинг `qbt.Torrents("")`
|
||||
и построить `byHash` (по `Hash`/`InfohashV1`/`InfohashV2`, lowercase); провал
|
||||
листинга → WARN и ранний выход (пойманные не трогаем этот тик, namer не зовём).
|
||||
- [x] 1.2 Для каждой catched-задачи: `torrentFor(d, byHash)`. Присутствует →
|
||||
усыновление БЕЗ namer/Add: под замком с ре-валидацией `state='catched'`
|
||||
`PromoteCatched(id, t.Name)` (`catched → downloading`, имя из раздачи снимка).
|
||||
- [x] 1.3 Отсутствует в `byHash` — прежний путь, но с re-read записи под `w.mu`
|
||||
перед сбором `addReq` (свежий `source_type`, ре-валидация `state='catched'`);
|
||||
тяжёлые вызовы (`GetTorrentData`, namer, `qbt.Add`) — вне замка.
|
||||
- [x] 1.4 Убедиться, что namer и `qbt.Add` не вызываются на ветке присутствия и
|
||||
при провале листинга.
|
||||
|
||||
## 2. Сообщение о дубле на приёме
|
||||
|
||||
- [x] 2.1 В `internal/tgbot/bot.go` (`ingestAndReply`) на `res.Deduplicated`
|
||||
отвечать явным «♻️ Дубль уже активной загрузки #id — добавление отменено»
|
||||
(вместо «Уже в работе #id»). Лог дедупа в `ingest` уже есть.
|
||||
|
||||
## 3. Тесты
|
||||
|
||||
- [x] 3.1 `catched_test.go`: торрент присутствует в снимке qBittorrent →
|
||||
`downloading` без `Add` и без namer; `display_name` = имя раздачи. (Фейк qBit
|
||||
отдаёт торрент в снимке ДО обработки задачи.)
|
||||
- [x] 3.2 `catched_test.go`: листинг qBittorrent провалился → задача осталась
|
||||
`catched`, namer/Add не вызывались.
|
||||
- [x] 3.3 `catched_test.go`: торрента нет в снимке → обычный путь (namer + Add +
|
||||
promote) остаётся зелёным; re-read `source_type` под замком берёт актуальный тип.
|
||||
- [x] 3.4 Регресс: catch_timeout-предохранитель, отмена во время добавления.
|
||||
|
||||
## 4. Проверки и ревью
|
||||
|
||||
- [x] 4.1 `task test` и `task lint` зелёные.
|
||||
- [x] 4.2 Ревью кода (чекпоинт перед archive): jellybit-review-code +
|
||||
jellybit-review-specs (сверка со спекой download-tracking).
|
||||
- [x] 4.3 `openspec validate --strict catched-promote-without-readd`.
|
||||
Reference in New Issue
Block a user