docs(storage): Alist 使用与真机验收 runbook,整理 / 文件管理 / MP 对照更新
- 新增 docs/runbook/storage-alist.md:登记、行为要点、临时 OpenList 容器真机验收步骤、排查 - organize.md 加「Alist / OpenList 存储」;moviepilot-filemanager.md 末节改为已做; v3 对照保留 rclone 不照抄、网盘改为 Alist 已接;file-manager-v2 存储切换与目的存储两行更新 - 设计文档补实现落点与偏离;矩阵测试补原地整理与目标已存在替换 Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01Cxwgnn2pbzQ7rXv3rq7fei
This commit is contained in:
1 parent
fed2202e74
commit
adbb9b59a0
7 files changed
+225
-8
No files matched your search
@@ -253,6 +253,69 @@ describe.skipIf(skip)("整理矩阵:本地 ↔ Alist ↔ Alist", () => {
|
||||
a.mock.failNext(0);
|
||||
});
|
||||
|
||||
it("目标已存在选替换:旧文件移进 Alist 上的回收站,新文件上传到位", async () => {
|
||||
const f = await film("local");
|
||||
const first = await organize(f, "copy", alib.libraryRootId);
|
||||
const target = `/s1/library/${first.main.target_path}`;
|
||||
a.mock.put(target, "old-version-content");
|
||||
await writeFile(join(h.dl, f.path), `${f.body}-v2`);
|
||||
const items = [{ root: f.root, path: f.path, mediaEntityId: f.id }];
|
||||
const base = { items, action: "copy", targetLibraryRootId: alib.libraryRootId, onExisting: "replace_with_verify" };
|
||||
const dry = await h.api("POST", "/files/organize", { ...base, idempotencyKey: key(), dryRun: true });
|
||||
expect(dry.body.data.groups[0].files[0]).toMatchObject({ existing: "replace", action: "replace" });
|
||||
const exec = await h.api("POST", "/files/organize", {
|
||||
...base,
|
||||
idempotencyKey: key(),
|
||||
dryRun: false,
|
||||
planIds: [dry.body.data.groups[0].planId],
|
||||
});
|
||||
const recordId = exec.body.data.recordIds[0] as string;
|
||||
await executeRecord(h.module.deps().ao, recordId);
|
||||
const rec = await h.db
|
||||
.selectFrom("organization_record")
|
||||
.select("status")
|
||||
.where("id", "=", recordId)
|
||||
.executeTakeFirstOrThrow();
|
||||
expect(rec.status).toBe("succeeded");
|
||||
expect(text(a.mock.read(target))).toBe(`${f.body}-v2`);
|
||||
const trash = await h.db
|
||||
.selectFrom("trash_item")
|
||||
.select(["trash_path", "original_path"])
|
||||
.where("original_path", "=", first.main.target_path!)
|
||||
.executeTakeFirstOrThrow();
|
||||
expect(trash.trash_path.startsWith(a.v("/s1/library/.umt-trash/"))).toBe(true);
|
||||
const parked = trash.trash_path.replace(a.v(""), "");
|
||||
expect(text(a.mock.read(parked))).toBe("old-version-content");
|
||||
});
|
||||
|
||||
it("原地整理(Alist 媒体库里的文件):只登记,不动文件", async () => {
|
||||
n++;
|
||||
const id = await seedEntity(h.db, { kind: "movie", title: "In Place Film", year: 2015 });
|
||||
a.mock.put("/s1/library/In Place Film (2015)/In.Place.Film.2015.1080p.mkv", "in-place-video");
|
||||
const items = [{ root: alib.root, path: "In Place Film (2015)/In.Place.Film.2015.1080p.mkv", mediaEntityId: id }];
|
||||
const base = { items, action: "in_place", minSizeBytes: 0, scrapeAfterImport: false };
|
||||
const dry = await h.api("POST", "/files/organize", { ...base, idempotencyKey: key(), dryRun: true });
|
||||
expect(dry.body.data.groups[0].error, JSON.stringify(dry.body)).toBeNull();
|
||||
const exec = await h.api("POST", "/files/organize", {
|
||||
...base,
|
||||
idempotencyKey: key(),
|
||||
dryRun: false,
|
||||
planIds: [dry.body.data.groups[0].planId],
|
||||
});
|
||||
const recordId = exec.body.data.recordIds[0] as string;
|
||||
await executeRecord(h.module.deps().ao, recordId);
|
||||
const rec = await h.db
|
||||
.selectFrom("organization_record")
|
||||
.select(["status", "action"])
|
||||
.where("id", "=", recordId)
|
||||
.executeTakeFirstOrThrow();
|
||||
expect(rec).toEqual({ status: "succeeded", action: "in_place" });
|
||||
expect(text(a.mock.read("/s1/library/In Place Film (2015)/In.Place.Film.2015.1080p.mkv"))).toBe("in-place-video");
|
||||
expect((await assetAt(alib.libraryRootId, "In Place Film (2015)/In.Place.Film.2015.1080p.mkv"))?.status).toBe(
|
||||
"available",
|
||||
);
|
||||
});
|
||||
|
||||
it("撤销:删除整理记录连带媒体库文件 → Alist 上移进回收站(可还原)", async () => {
|
||||
const f = await film("local");
|
||||
const r = await organize(f, "copy", alib.libraryRootId);
|
||||
|
||||
Reference in new issue
Block a user