Приём: добавление загрузки по .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:
+12
-1
@@ -13,7 +13,7 @@
|
||||
> `0003_source_miss_count`, `0004_candidate_url`, `0005_display_name`,
|
||||
> `0006_ulid_identity` (Go-миграция: ULID-идентификаторы, `download_infohash`),
|
||||
> `0007_file_link_size`, `0008_rfc3339_time` (метки времени → RFC 3339 UTC,
|
||||
> `DEFAULT` убран).
|
||||
> `DEFAULT` убран), `0009_download_torrent` (байты `.torrent`-файла).
|
||||
|
||||
Назначение таблиц и почему так — [architecture.md](architecture.md) →
|
||||
«Хранилище». Значения `state` и переходы — [workflow.md](workflow.md).
|
||||
@@ -27,6 +27,7 @@
|
||||
```mermaid
|
||||
erDiagram
|
||||
download ||--o{ download_infohash : "инфохэши (v1/v2)"
|
||||
download ||--o| download_torrent : "байты .torrent (1:0..1)"
|
||||
download ||--o{ recognition : "распознавания"
|
||||
download ||--o{ hint : "подсказки"
|
||||
download ||--o{ override : "ручные правки"
|
||||
@@ -55,6 +56,11 @@ erDiagram
|
||||
TEXT created_at "NOT NULL; RFC 3339 UTC (Z), пишет приложение"
|
||||
}
|
||||
|
||||
download_torrent {
|
||||
TEXT download_id PK_FK "NOT NULL; ON DELETE CASCADE; байты source_type=torrent"
|
||||
BLOB data "NOT NULL; исходные байты .torrent для добавления файлом (миграция 0009)"
|
||||
}
|
||||
|
||||
recognition {
|
||||
TEXT id PK "ULID"
|
||||
TEXT download_id FK "NOT NULL; ON DELETE CASCADE"
|
||||
@@ -125,6 +131,11 @@ erDiagram
|
||||
более одной активной загрузки на infohash» держат guarded-методы store
|
||||
(`CreateDownloadIfNoActive`/`ActivateIfNoOtherActive`) в одной
|
||||
write-транзакции — на уровне схемы он не выражается (условие на `state`).
|
||||
- `download` 1 — 0..1 `download_torrent` — байты исходного `.torrent` (только
|
||||
у `source_type=torrent`); нужны воркеру для добавления раздачи файлом и для
|
||||
повторного добавления при retry, поэтому живут весь срок строки загрузки.
|
||||
`ON DELETE CASCADE` — страховка на будущий delete-путь (сейчас загрузки не
|
||||
удаляются).
|
||||
- `download` ↔ `file_link` — один источник (раздача) ко многим разложенным
|
||||
файлам; внутри строки `file_link` связь `src_path → dst_path` — 1:1. Не
|
||||
каждый файл раздачи попадает в `file_link` (только распознанные медиа и
|
||||
|
||||
Reference in New Issue
Block a user