Владение целевым путём при повторной раскладке (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:
@@ -99,6 +99,18 @@ func TestReconcilePartialTargetLoss(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestReconcileSkipsDeleted(t *testing.T) {
|
||||
// deleted терминально: сверка его не переоценивает, даже если по бывшему
|
||||
// пути снова появился файл (его забрала другая загрузка) и источника нет.
|
||||
f := newReconcileFixture(t, store.StateDeleted, false, true)
|
||||
if err := f.w.Poll(context.Background()); err != nil {
|
||||
t.Fatalf("Poll: %v", err)
|
||||
}
|
||||
if got := f.st.downloads[1].State; got != store.StateDeleted {
|
||||
t.Errorf("state = %q, want deleted (сверка не трогает терминальное)", got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestReconcileDebounce(t *testing.T) {
|
||||
// Порог 3: первые два промаха не помечают, третий — помечает orphaned;
|
||||
// возврат источника лечит обратно и сбрасывает счётчик.
|
||||
|
||||
Reference in New Issue
Block a user