Пересканирование Jellyfin: расширить триггер на reverted и deleted

Скан Jellyfin (POST /Library/Refresh) слался только при входе в done.
После Undo (reverted) и Delete (deleted) наши хардлинки сняты, а Jellyfin
держал битые записи до скана по расписанию.

Гейт скана в едином чекпоинте transitionErr переведён с state == done на
предикат triggersScan(state) по множеству {done, reverted, deleted}: гейт по
состоянию-цели естественно ловит пользовательские Undo/Delete и
reconcile-производный deleted, идемпотентно. target_missing/orphaned —
промежуточный рассинхрон (ждём relink/лечения) — исключены.

OpenSpec: заведена и влита дельта file-layout (требование
«Пересканирование Jellyfin после изменения библиотечных ссылок»); change
архивирован. Синк рукописных доков architecture.md/workflow.md. Тесты:
скан стреляет на reverted и deleted, молчит на входе вне множества.
Закрыта задача беклога jellyfin-skan-posle-udaleniya.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
av
2026-07-17 21:14:18 +03:00
co-authored by Claude Opus 4.8
parent 0354a8c96b
commit 1639ebfdd7
10 changed files with 303 additions and 72 deletions
+12 -7
View File
@@ -181,10 +181,15 @@ Jellyfin ([jellyfin-layout.md](jellyfin-layout.md)). Правила:
## Пересканирование Jellyfin
После успешной раскладки (вход в `done`) `worker` неблокирующе просит Jellyfin
пересканировать медиатеку, чтобы новые файлы быстрее появились в проигрывателе.
Включается конфигом `[jellyfin]` (по умолчанию выключено); без него скан не
дёргается.
Когда наши библиотечные хардлинки меняются, `worker` неблокирующе просит Jellyfin
пересканировать медиатеку, чтобы плеер не держал битые пути и быстрее подхватил
новые файлы. Триггерят входы в `done` (файлы разложены), `reverted` (Undo снял
ссылки) и `deleted` (Delete снял ссылки / сверка констатировала их отсутствие) —
гейт по состоянию-цели в едином чекпоинте перехода, поэтому ловит и
пользовательские Undo/Delete, и reconcile-производный `deleted`. Промежуточный
рассинхрон (`target_missing`/`orphaned`) не сканируем — задача ждёт
relink/лечения. Включается конфигом `[jellyfin]` (по умолчанию выключено); без
него скан не дёргается.
- **Один вызов — `POST /Library/Refresh`** (скан всех библиотек). Скан
инкрементальный, поэтому полный дёшев; точечный скан конкретной папки не
@@ -260,9 +265,9 @@ Dockerfile .dockerignore config.example.toml
задач (повторная закачка спустя время → новая задача).
- Состояние — на persistent-томе `/srv/applications/jellybit/data`.
- Детект завершения — поллинг; webhook — на будущее (drafts/ideas).
- Пересканирование Jellyfin после раскладки`POST /Library/Refresh` (скан
всех библиотек, инкрементальный), неблокирующе на входе в `done`; опц.,
включается `[jellyfin]`.
- Пересканирование Jellyfin при изменении наших ссылок`POST /Library/Refresh`
(скан всех библиотек, инкрементальный), неблокирующе на входе в `done`/
`reverted`/`deleted`; опц., включается `[jellyfin]`.
- Источник (magnet/URL/.torrent) отдаём в qBittorrent — без SSRF.
- Авто-раскладка требует подтверждённого матча в базе; иначе review.
- Веб-UI в v1 без авторизации (доверенная LAN, опц. allowlist подсетей).