fix(sf-db): write snapshots atomically
This commit is contained in:
parent
a8a28bd7c0
commit
15ae3d02b7
2 changed files with 18 additions and 1 deletions
|
|
@ -23,6 +23,8 @@ import {
|
|||
mkdirSync,
|
||||
readdirSync,
|
||||
readFileSync,
|
||||
renameSync,
|
||||
rmSync,
|
||||
statSync,
|
||||
unlinkSync,
|
||||
writeFileSync,
|
||||
|
|
@ -199,13 +201,25 @@ function createDatabaseSnapshot(rawDb, path) {
|
|||
if (latest > 0 && Date.now() - latest < DB_BACKUP_MIN_INTERVAL_MS) return;
|
||||
const stamp = new Date().toISOString().replace(/[:.]/g, "-");
|
||||
const backupPath = join(dir, `sf.db.${stamp}`);
|
||||
rawDb.exec(`VACUUM INTO ${sqliteStringLiteral(backupPath)}`);
|
||||
const tmpPath = `${backupPath}.tmp`;
|
||||
rmSync(tmpPath, { force: true });
|
||||
rawDb.exec(`VACUUM INTO ${sqliteStringLiteral(tmpPath)}`);
|
||||
renameSync(tmpPath, backupPath);
|
||||
pruneDatabaseBackups(dir);
|
||||
} catch (err) {
|
||||
logWarning(
|
||||
"sf-db",
|
||||
`database snapshot failed: ${getErrorMessage(err)}`,
|
||||
);
|
||||
try {
|
||||
for (const entry of readdirSync(dir)) {
|
||||
if (entry.startsWith("sf.db.") && entry.endsWith(".tmp")) {
|
||||
rmSync(join(dir, entry), { force: true });
|
||||
}
|
||||
}
|
||||
} catch {
|
||||
// Best-effort cleanup; preserve the original snapshot warning.
|
||||
}
|
||||
}
|
||||
}
|
||||
function performDatabaseMaintenance(rawDb, path) {
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ import {
|
|||
mkdtempSync,
|
||||
readdirSync,
|
||||
rmSync,
|
||||
statSync,
|
||||
} from "node:fs";
|
||||
import { tmpdir } from "node:os";
|
||||
import { join } from "node:path";
|
||||
|
|
@ -453,6 +454,8 @@ test("openDatabase_when_file_backed_creates_db_snapshot_and_maintenance_marker",
|
|||
name.startsWith("sf.db."),
|
||||
);
|
||||
assert.equal(backups.length, 1);
|
||||
assert.equal(backups[0].endsWith(".tmp"), false);
|
||||
assert.equal(statSync(join(backupDir, backups[0])).size > 0, true);
|
||||
assert.equal(existsSync(join(backupDir, "maintenance.json")), true);
|
||||
});
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue