Приём: усыновление присутствующего в 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,57 @@
|
||||
## Why
|
||||
|
||||
Пойманная (`catched`) загрузка, чей торрент **уже присутствует в qBittorrent**
|
||||
(добавлен раньше вручную/другим клиентом или прошлой попыткой jellybit), уходит в
|
||||
бесконечный цикл: `processCatched` на каждом тике зовёт `qbt.Add`, qBittorrent
|
||||
отбивает дубль (`409 Conflict`), сбой трактуется как транзиентный → задача
|
||||
остаётся в `catched` → повтор, и на каждом безнадёжном тике впустую вызывается
|
||||
LLM-namer. Диагноз: `docs/backlog/review-f2-promote-without-add.md`.
|
||||
|
||||
Решение: перед добавлением проверять присутствие торрента в qBittorrent. Раз
|
||||
инвариант приёма гарантирует, что до воркера доходит лишь загрузка, для которой в
|
||||
jellybit нет другой активной задачи (дубль на активную отсекается ещё на приёме),
|
||||
присутствие торрента в qBittorrent означает «его надо **усыновить**» — довести до
|
||||
`downloading` без повторного `add` и разложить, а не пытаться добавить дубль и
|
||||
ловить 409.
|
||||
|
||||
Отдельно: повторное добавление торрента, который jellybit **уже ведёт активной
|
||||
задачей**, транспорт должен явно отражать как дубль (сообщение «добавление
|
||||
отменено»), а не молчаливым «уже в работе».
|
||||
|
||||
## What Changes
|
||||
|
||||
- В `processCatched` перед `qbt.Add` — **проверка присутствия торрента в
|
||||
qBittorrent** (один листинг на тик). Присутствует → `catched → downloading`
|
||||
**без `add`** (усыновление; `display_name` из имени раздачи, без LLM); нет →
|
||||
прежний путь добавления. Проверка — **до namer**, чтобы не жечь LLM.
|
||||
- При недоступности qBittorrent (листинг не удался) тик пропускается без вызова
|
||||
LLM; предел ретрая — существующий предохранитель `catch_timeout`.
|
||||
- Гонка апгрейда F6 сужается: `source_type` перечитывается под блокировкой
|
||||
переходов перед добавлением.
|
||||
- Транспорт Telegram на дедуп приёма (дубль на уже активную задачу) отвечает
|
||||
явным «дубль уже активной #id — добавление отменено» (+ лог), без создания
|
||||
новой записи.
|
||||
|
||||
## Capabilities
|
||||
|
||||
### New Capabilities
|
||||
|
||||
<!-- нет новых capability -->
|
||||
|
||||
### Modified Capabilities
|
||||
|
||||
- `download-tracking`: требование «Добавление пойманной загрузки в qBittorrent»
|
||||
дополняется проверкой присутствия и усыновлением (promote без повторного
|
||||
`add`) при наличии торрента, перечитыванием источника под замком и пропуском
|
||||
тика при недоступности qBittorrent.
|
||||
|
||||
## Impact
|
||||
|
||||
- Код: `internal/worker/worker.go` (`processCatched`, presence-check,
|
||||
усыновление вместо повторного `add`), `internal/tgbot/bot.go` (текст ответа на
|
||||
дедуп).
|
||||
- Внешние вызовы: убирает лишние `qbt.Add` (и 409) и `chat.completions`
|
||||
(LLM-namer) на повторах; добавляет один `qbt.Torrents`-листинг на тик в
|
||||
`processCatched`.
|
||||
- Тесты: `internal/worker/catched_test.go`.
|
||||
- **БД-миграции, новых состояний, конфигурации и внешнего API — нет.**
|
||||
Reference in New Issue
Block a user