Владение целевым путём при повторной раскладке (state-reconciliation)
Завершённая загрузка ложно «воскресала» из deleted в orphaned, когда её целевой путь переиспользовала другая загрузка (повторная закачка того же фильма в другом качестве): сверка проверяла лишь существование пути, не проверяя, что файл по нему — наша раскладка. Вводим инвариант «один целевой путь — один владелец»: - при успешной раскладке на освободившийся чужой путь владение переходит к новой загрузке — прежние file_link на этот путь помечаются статусом superseded и перестают считаться целью при сверке; - deleted исключён из desyncStates — терминальное состояние больше не переоценивается (источник к нему не вернётся из-за идемпотентности, цель отбирается переходом владения); - Undo снимает только реально свои разложенные ссылки (superseded пропускает — файл по пути теперь чужой хардлинк); - ошибку перехода владения трактуем как некритичную (WARN-and-continue): файлы уже разложены, рассинхрон чужих задач исправит следующий тик. Без миграции схемы (status — TEXT). Дельта влита в основную спеку, обновлены workflow.md и jellyfin-layout.md. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -51,6 +51,19 @@ inode общий — диск не дублируется.
|
||||
же inode → готово; другой файл → коллизия → review). Инварианты и undo —
|
||||
в [architecture.md](architecture.md) → «Раскладка файлов».
|
||||
|
||||
## Владение целевым путём
|
||||
|
||||
Целевой путь принадлежит **одной** загрузке. Когда новая раскладка
|
||||
успешно ложится на путь, который раньше занимала другая загрузка (путь к
|
||||
этому моменту **свободен** — иначе была бы коллизия → review, чужой файл
|
||||
не перезаписываем), владение переходит к новой загрузке: прежние записи
|
||||
`file_link` на этот путь помечаются статусом `superseded` и перестают
|
||||
считаться целью прежней загрузки. Это нужно сверке с реальностью: иначе
|
||||
повторная закачка того же фильма (например, в другом качестве) по тому же
|
||||
пути ложно «воскрешала» бы удалённую задачу — см.
|
||||
[workflow.md](workflow.md) → «Сверка с реальностью». `superseded`-ссылки
|
||||
не считаются целью при сверке и не снимаются в `Undo`.
|
||||
|
||||
Желательно: целевой и исходный каталоги — на одной ФС/одном mount'е
|
||||
(внутри контейнера это обеспечивает единая песочница `/srv/media`), тогда
|
||||
работает дешёвый хардлинк. Если хардлинк невозможен (разные ФС или ФС без
|
||||
|
||||
+12
-5
@@ -107,12 +107,19 @@ stateDiagram-v2
|
||||
«Привязать заново» (`→ recognizing`); авто-действий нет.
|
||||
- **orphaned** — источник пропал, цель (последняя копия данных) на месте.
|
||||
Команд вперёд нет; `Undo` запрещён (снял бы единственную копию).
|
||||
- **deleted** — нет ни источника, ни цели; терминально.
|
||||
- **deleted** — нет ни источника, ни цели; **терминально**: сверка его
|
||||
больше не переоценивает (см. ниже).
|
||||
|
||||
Сверка трогает только `done`/`target_missing`/`orphaned`/`deleted` —
|
||||
активные и пользовательски-терминальные (`reverted`/`cancelled`/`failed`/
|
||||
`stuck`) состояния не задевает. Реальность «лечится» сама: при возврате
|
||||
источника/цели задача переходит обратно (вплоть до `done`). Пропажа
|
||||
Сверка трогает только `done`/`target_missing`/`orphaned` — терминальный
|
||||
`deleted`, активные и пользовательски-терминальные (`reverted`/`cancelled`/
|
||||
`failed`/`stuck`) состояния не задевает. Реальность «лечится» сама: при
|
||||
возврате источника/цели задача переходит обратно (вплоть до `done`) — но
|
||||
**не из `deleted`**: к терминальной задаче источник не вернётся
|
||||
(идемпотентность снимается только для активных), а её бывший целевой путь, если
|
||||
его заняла другая загрузка, отбирается переходом владения (см.
|
||||
[jellyfin-layout.md](jellyfin-layout.md) → «Владение целевым путём»).
|
||||
Без этого правила переиспользование пути ложно «воскрешало» бы удалённую
|
||||
задачу в `orphaned`. Пропажа
|
||||
**источника** дебаунсится (`[worker].source_missing_threshold` подряд идущих
|
||||
тиков), пропажа цели проверяется немедленно (локальная ФС надёжна). Команды,
|
||||
которым нужен источник (relink/распознать/применить/undo), проверяют его
|
||||
|
||||
Reference in New Issue
Block a user