Приём: добавление загрузки по .torrent-файлу
Принимаем .torrent как загруженные байты — через файл-пикер в веб-форме и Telegram-документ, наряду с magnet. Файл несёт полные метаданные: работает там, где magnet не резолвится (закрытые трекеры, без DHT), и даёт максимум контекста для распознавания без сети. - internal/torrent: парсер поверх anacrolix/torrent/metainfo — инфохэш(и) (v1 SHA1 исходных байтов info; v2 BEP52 при наличии) + Context() из имени, дерева файлов, размера, трекеров. Извлечение файлов панико-безопасно (недоверенный вход). - Персистентность байтов: таблица-спутник download_torrent (миграция 0009); пишется в транзакции создания загрузки, только на ветке создания (не при дедупе). Байты живут весь срок строки — нужны для повторного добавления при retry. - ingest: Request.TorrentData/TorrentName, диспетч парсера; source_ref — человекочитаемый референс (имя раздачи/файла), не адрес добавления. - worker: общий sourceAddParts ветвит по source_type в ОБОИХ add-путях — processCatched и Retry (torrent добавляется файлом, не magnet-хешем). - Транспорты: multipart-форма с файл-пикером (деградация без JS) и приём Telegram-документа (скачивание с редактированием токена из ошибок — секрет не в логи; обработка до ветки pending/текста). Разработка по OpenSpec (SDD): change torrent-file-ingest, два чекпоинта ревью (дизайн до кода, код до архива) сабагентами; дельты влиты в спеки, change архивирован. Ручная проверка на живом qBittorrent (7.3) — за деплоем. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
+50
@@ -0,0 +1,50 @@
|
||||
## MODIFIED Requirements
|
||||
|
||||
### Requirement: Ручной повтор зависшей/упавшей загрузки из транспортов
|
||||
|
||||
Система SHALL предоставлять пользователю команду повторной попытки (retry)
|
||||
для задач в `failed`/`stuck` из веб-UI и Telegram (не только через REST API).
|
||||
Retry SHALL переводить задачу обратно в `downloading`, не вызывая её
|
||||
немедленного повторного падения по таймауту: базис отсчёта таймаута SHALL
|
||||
сбрасываться (отсчёт ведётся от факта в qBittorrent, а не от старого
|
||||
`created_at`).
|
||||
|
||||
Если источник задачи уже жив в qBittorrent, retry SHALL перецепляться к
|
||||
существующему торренту, а не добавлять источник повторно вслепую; повторный
|
||||
`Add` выполняется, только когда раздачи в qBittorrent нет.
|
||||
|
||||
Повторный `Add` при retry система SHALL выполнять **по типу источника**
|
||||
(`source_type`), как и добавление пойманной загрузки (см. `download-tracking`
|
||||
«Добавление пойманной загрузки в qBittorrent»): magnet/url — ссылкой; torrent —
|
||||
сохранёнными байтами `.torrent` файлом. Для torrent-источника retry БЕЗ живой
|
||||
раздачи система SHALL добавлять раздачу байтами и SHALL NOT активировать задачу
|
||||
в `downloading`, не добавив её (иначе задача повиснет как «нет в qBittorrent»).
|
||||
|
||||
#### Scenario: Retry упавшей magnet-загрузки из веб-UI
|
||||
|
||||
- **GIVEN** задача в `failed`, её торрент жив в qBittorrent
|
||||
- **WHEN** пользователь нажимает retry в веб-UI
|
||||
- **THEN** задача возвращается в `downloading` без повторного `Add`
|
||||
- **AND** не падает снова на ближайшем тике сверки по таймауту
|
||||
|
||||
#### Scenario: Retry доступен в Telegram
|
||||
|
||||
- **WHEN** для задачи в `failed`/`stuck` пользователь вызывает retry в
|
||||
Telegram-боте
|
||||
- **THEN** задача возвращается в `downloading`
|
||||
|
||||
#### Scenario: Retry без живого источника добавляет источник заново
|
||||
|
||||
- **GIVEN** задача в `failed`, раздачи в qBittorrent нет
|
||||
- **WHEN** пользователь инициирует retry
|
||||
- **THEN** источник добавляется в qBittorrent заново — magnet/url ссылкой,
|
||||
torrent сохранёнными байтами файлом
|
||||
- **AND** задача переходит в `downloading`
|
||||
|
||||
#### Scenario: Retry torrent-загрузки без живого источника
|
||||
|
||||
- **GIVEN** задача с `source_type = torrent` в `failed`, раздачи в qBittorrent
|
||||
нет, байты `.torrent` сохранены
|
||||
- **WHEN** пользователь инициирует retry
|
||||
- **THEN** сохранённые байты добавляются в qBittorrent файлом
|
||||
- **AND** задача переходит в `downloading` (не остаётся без раздачи)
|
||||
Reference in New Issue
Block a user