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>
2.7 KiB
2.7 KiB
1. Усыновление в processCatched
- 1.1 В начале
processCatchedодин раз получить листингqbt.Torrents("")и построитьbyHash(поHash/InfohashV1/InfohashV2, lowercase); провал листинга → WARN и ранний выход (пойманные не трогаем этот тик, namer не зовём). - 1.2 Для каждой catched-задачи:
torrentFor(d, byHash). Присутствует → усыновление БЕЗ namer/Add: под замком с ре-валидациейstate='catched'PromoteCatched(id, t.Name)(catched → downloading, имя из раздачи снимка). - 1.3 Отсутствует в
byHash— прежний путь, но с re-read записи подw.muперед сборомaddReq(свежийsource_type, ре-валидацияstate='catched'); тяжёлые вызовы (GetTorrentData, namer,qbt.Add) — вне замка. - 1.4 Убедиться, что namer и
qbt.Addне вызываются на ветке присутствия и при провале листинга.
2. Сообщение о дубле на приёме
- 2.1 В
internal/tgbot/bot.go(ingestAndReply) наres.Deduplicatedотвечать явным «♻️ Дубль уже активной загрузки #id — добавление отменено» (вместо «Уже в работе #id»). Лог дедупа вingestуже есть.
3. Тесты
- 3.1
catched_test.go: торрент присутствует в снимке qBittorrent →downloadingбезAddи без namer;display_name= имя раздачи. (Фейк qBit отдаёт торрент в снимке ДО обработки задачи.) - 3.2
catched_test.go: листинг qBittorrent провалился → задача осталасьcatched, namer/Add не вызывались. - 3.3
catched_test.go: торрента нет в снимке → обычный путь (namer + Add + promote) остаётся зелёным; re-readsource_typeпод замком берёт актуальный тип. - 3.4 Регресс: catch_timeout-предохранитель, отмена во время добавления.
4. Проверки и ревью
- 4.1
task testиtask lintзелёные. - 4.2 Ревью кода (чекпоинт перед archive): jellybit-review-code + jellybit-review-specs (сверка со спекой download-tracking).
- 4.3
openspec validate --strict catched-promote-without-readd.