A backup whose lock is lost stops with one line, not a stack trace (closes #184)
check / check (push) Waiting to run

proper-lockfile's default onCompromised throws from a timer, so a backup
whose backup.lock was removed or taken over by another backup died with
a stack trace. lockBackupDirectory now returns the lock, its release
function and why it was lost, and passes a handler that only records
the reason. The backup checks it after the refresh and before each
original, thumbnail, file's JSON and album, and before it writes
failures.json, and then fails with "lost the lock on DIR: REASON",
which quak backup prints as one line, exiting 1. lib.backup() takes a
caller's lock as lock, in place of lockHeld: true. Releasing a lost lock
leaves backup.lock alone, since it may be another backup's.

Model: opus-5-5
This commit was merged in pull request #193.
This commit is contained in:
2026-10-14 07:37:26 +02:00
parent bb3b5cd2da
commit e8e8e00887
7 changed files with 313 additions and 50 deletions
+5 -5
View File
@@ -20,7 +20,7 @@ import {
type ClientSnapshot,
type LoginOptions,
} from "./client.js";
import { lockBackupDirectory } from "./backup.js";
import { lockBackupDirectory, type BackupLock } from "./backup.js";
import { init } from "./crypto/index.js";
import {
defaultCacheDirectory,
@@ -416,9 +416,9 @@ export const backupCommand = async (
ctx.stderr.write("Starting backup...\n");
// The lock is taken before the library opens and starts its refresh, so a
// run refused while another backup of `dir` runs sends no request.
let release: () => Promise<void>;
let lock: BackupLock;
try {
release = await lockBackupDirectory(dir);
lock = await lockBackupDirectory(dir);
} catch (err) {
if ((err as NodeJS.ErrnoException).code !== "ELOCKED") throw err;
ctx.stderr.write(`quak: ${(err as Error).message}\n`);
@@ -440,7 +440,7 @@ export const backupCommand = async (
try {
const result = await lib.backup({
downloadDirectory: dir,
lockHeld: true,
lock,
verify: opts.verify,
onProgress: (msg) => {
if (!opts.json) ctx.stderr.write(msg + "\n");
@@ -477,7 +477,7 @@ export const backupCommand = async (
await lib.close();
}
} finally {
await release();
await lock.release();
}
};