Уточнение деталей архитектуры
This commit is contained in:
+53
-14
@@ -26,7 +26,8 @@ qBittorrent, определяет содержимое (фильм или сер
|
||||
| `ingest` | use-case приёма загрузки, общий для всех транспортов |
|
||||
| `qbt` | клиент qBittorrent WebUI API |
|
||||
| `worker` | фоновый цикл: машина состояний, поллинг завершения |
|
||||
| `recognize` | пред-парс имени + LLM + модель уверенности |
|
||||
| `recognize` | пред-парс имени + вызов LLM + модель уверенности |
|
||||
| `llm` | провайдер LLM за интерфейсом (дискриминатор `type`) |
|
||||
| `metadata` | интерфейс баз метаданных + TMDB/TVDB (опц.) |
|
||||
| `layout` | конвенции Jellyfin + хардлинкер |
|
||||
| `store` | SQLite: загрузки, распознавание, ссылки |
|
||||
@@ -44,10 +45,12 @@ ingest → downloading → completed → recognizing ─┬─ уверенно
|
||||
|
||||
- **ingest** — приняли источник + контекст, поставили в qBittorrent
|
||||
(категория `jellybit`), записали в БД.
|
||||
- **downloading / completed** — `worker` поллит qBittorrent по категории.
|
||||
- **downloading / completed** — `worker` поллит qBittorrent по категории
|
||||
(интервал `worker.poll_interval`, по умолчанию 5 с).
|
||||
- **recognizing** — `recognize` строит план раскладки и оценку
|
||||
уверенности (см. [recognition.md](recognition.md)).
|
||||
- **review** — план уходит человеку (веб-UI / Telegram), ждём решения.
|
||||
- **review** — план уходит человеку (веб-UI / Telegram), ждём решения;
|
||||
сценарии — в [review-ux.md](review-ux.md).
|
||||
- **linking** — `layout` создаёт хардлинки в библиотеке.
|
||||
- **done** — опционально дёргаем скан библиотеки Jellyfin.
|
||||
|
||||
@@ -77,7 +80,10 @@ SQLite, минимум таблиц:
|
||||
|
||||
## Конфигурация
|
||||
|
||||
TOML, секреты — placeholder'ы; реальный конфиг не коммитим. Пример:
|
||||
TOML. В репозитории — `config.example.toml` с placeholder'ами; реальный
|
||||
`config.toml` рендерится при деплое Ansible-шаблоном из переменных umbar
|
||||
(секреты — в `vars/secrets.yml` под ansible-vault) и не коммитится.
|
||||
Пример:
|
||||
|
||||
```toml
|
||||
[qbittorrent]
|
||||
@@ -92,9 +98,11 @@ movies = "/srv/media/movies"
|
||||
series = "/srv/media/series"
|
||||
|
||||
[llm]
|
||||
provider = "anthropic"
|
||||
model = "claude-sonnet-4-6" # сложные случаи — claude-opus-4-8
|
||||
# type — дискриминатор реализации; пока поддерживается "openai-compat"
|
||||
type = "openai-compat"
|
||||
base_url = "http://127.0.0.1:1234/v1"
|
||||
api_key = ""
|
||||
model = "qwen2.5-32b-instruct"
|
||||
|
||||
[metadata.tmdb]
|
||||
enabled = true
|
||||
@@ -104,6 +112,9 @@ api_key = ""
|
||||
enabled = false
|
||||
api_key = ""
|
||||
|
||||
[worker]
|
||||
poll_interval = "5s" # как часто опрашивать qBittorrent
|
||||
|
||||
[recognition]
|
||||
auto_confidence_threshold = 0.85
|
||||
|
||||
@@ -126,20 +137,39 @@ format = "json"
|
||||
сквозным идентификатором; решения распознавания (почему авто/ревью)
|
||||
логируются явно.
|
||||
|
||||
## Деплой
|
||||
|
||||
Jellybit работает в **docker** — в одной среде с qBittorrent и Jellyfin
|
||||
(они тоже в контейнерах на umbar). Единая среда запуска перевешивает
|
||||
простоту нативного systemd.
|
||||
|
||||
Сборка — дёшево и сердито: статический бинарь собирается здесь; на сервер
|
||||
во временную build-папку кладутся бинарь + `Dockerfile` (он просто
|
||||
копирует бинарь в минимальный образ), образ собирается прямо на сервере и
|
||||
запускается. Go-тулчейн на сервере не нужен — только docker.
|
||||
|
||||
Разделение ответственности:
|
||||
|
||||
- **jellybit** (этот репозиторий) — производит статический бинарь и
|
||||
`Dockerfile`.
|
||||
- **umbar** — оркестрация деплоя: доставка артефактов, `docker build` и
|
||||
запуск через docker compose (`playbook-jellybit.yml`).
|
||||
|
||||
## Раскладка файлов
|
||||
|
||||
Хардлинки в `paths.movies` / `paths.series` по конвенциям Jellyfin.
|
||||
Детали и крайние случаи — в [jellyfin-layout.md](jellyfin-layout.md).
|
||||
Требование: `downloads` и `media` на одной ФС (иначе хардлинк
|
||||
невозможен). Если jellybit в docker — смонтировать общего родителя,
|
||||
чтобы хардлинк работал внутри контейнера.
|
||||
`/srv/downloads` и `/srv/media` — одна ФС (подтверждено), поэтому
|
||||
хардлинки применимы. Так как jellybit в docker (см. «Деплой»), контейнеру
|
||||
монтируем общего родителя `/srv` — чтобы внутри оба каталога остались на
|
||||
одной ФС и хардлинк проходил.
|
||||
|
||||
## Предполагаемая структура репозитория
|
||||
|
||||
```
|
||||
cmd/jellybit/ точка входа, сборка зависимостей
|
||||
internal/
|
||||
ingest/ qbt/ worker/ recognize/ metadata/
|
||||
ingest/ qbt/ worker/ recognize/ llm/ metadata/
|
||||
layout/ store/ httpapi/ tgbot/ config/
|
||||
migrations/ миграции SQLite
|
||||
web/templates/ шаблоны веб-UI
|
||||
@@ -147,9 +177,18 @@ docs/ specs / adr / drafts
|
||||
config.example.toml
|
||||
```
|
||||
|
||||
## Решённые вопросы
|
||||
|
||||
- `/srv/downloads` и `/srv/media` — одна ФС (подтверждено); хардлинки
|
||||
применимы.
|
||||
- Детект завершения — поллинг qBittorrent раз в несколько секунд
|
||||
(`worker.poll_interval`). Webhook — возможная оптимизация на будущее
|
||||
([drafts/ideas.md](../drafts/ideas.md)).
|
||||
- Секреты — в переменных umbar; `config.toml` рендерится Ansible-шаблоном
|
||||
при деплое.
|
||||
- Форма запуска — **docker**, образ собирается на сервере из готового
|
||||
бинаря (см. «Деплой»).
|
||||
|
||||
## Открытые вопросы
|
||||
|
||||
- Подтвердить, что `/srv/downloads` и `/srv/media` — одна ФС.
|
||||
- Способ детекта завершения: поллинг (старт) или webhook qBittorrent
|
||||
«run on completion» (позже).
|
||||
- Где хранить секреты при деплое (шаблонизация из umbar).
|
||||
Существенных пока нет.
|
||||
|
||||
Reference in New Issue
Block a user