Make backup wait for the server refresh and fail when it fails (closes #99)
check / check (push) Successful in 1m11s

lib.backup() refreshed through the background loop's refresh, which returns
at once when one is already running and swallows a failure, so a backup
could run on the previous file list, or on an empty cache, and exit 0. It
now uses the refresh fresh() uses: it joins a running refresh or starts
one, and rejects before touching any file when it fails. The CLI's error
wrapper prints that as one line and exits 1.

Model: opus-5-5
This commit is contained in:
2026-09-23 05:45:00 +00:00
parent 36642f4448
commit 530ceeaf76
5 changed files with 137 additions and 10 deletions
+30
View File
@@ -20,6 +20,7 @@ import {
} from "node:fs";
import { join } from "node:path";
import { tmpdir } from "node:os";
import { PassThrough } from "node:stream";
import { describe, it, expect, beforeAll, beforeEach, afterEach } from "vitest";
import {
@@ -34,6 +35,7 @@ import {
backupCommand,
listMissingThumbnailsCommand,
} from "../../src/cli-commands.js";
import { run } from "../../src/cli-run.js";
import { loadSession } from "../../src/cli-session.js";
import type { Client, ClientSnapshot } from "../../src/client.js";
import type { ContentSource } from "../../src/library/content.js";
@@ -430,6 +432,34 @@ describe("backup", () => {
expect(result.errors[0].fileID).toBe(101);
expect(stderr.text).toBe("Starting backup...\n");
});
it("exits 1 with the error on one line when the refresh fails", async () => {
const client = {
...fakeClient(),
collectionsSince: async () => {
throw new Error("HTTP 401 from server");
},
} as unknown as Client;
const dir = join(root, "backup");
// Through `run`, as `bin/quak.ts` does, which prints a thrown error.
const runStderr = new PassThrough();
let runText = "";
runStderr.on("data", (chunk: Buffer) => {
runText += chunk.toString();
});
const code = await new Promise<number>((resolve) => {
void run(
backupCommand(context(client), dir, {}),
new PassThrough(),
runStderr,
resolve,
);
});
expect(code).toBe(1);
expect(runText).toBe("quak: HTTP 401 from server\n");
expect(stderr.text).toBe("Starting backup...\nRefreshing library...\n");
expect(existsSync(join(dir, "originals"))).toBe(false);
});
});
describe("helper list-missing-thumbnails", () => {