Files
avandClaude Opus 4.8 b8657120fe Приём: усыновление присутствующего в 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>
2026-07-10 18:36:47 +03:00

2.7 KiB
Raw Permalink Blame History

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-read source_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.