api9nin / src /lib /db /adapters /betterSqliteAdapter.js
github-actions[bot]
deploy from github actions 2026-06-18
c8ae75d
Raw
History Blame Contribute Delete
1.83 kB
import Database from "better-sqlite3";
import { PRAGMA_SQL } from "../schema.js";
// Periodic checkpoint to keep WAL file small (avoid huge -wal/-shm growth)
const CHECKPOINT_INTERVAL_MS = 60 * 1000;
export function createBetterSqliteAdapter(filePath) {
const db = new Database(filePath);
db.exec(PRAGMA_SQL);
// Schema is created/synced by migrate.js after adapter init
const stmtCache = new Map();
function prepare(sql) {
let stmt = stmtCache.get(sql);
if (!stmt) {
stmt = db.prepare(sql);
stmtCache.set(sql, stmt);
}
return stmt;
}
// Truncate WAL periodically so file stays small for backup/copy
const checkpointTimer = setInterval(() => {
try { db.pragma("wal_checkpoint(TRUNCATE)"); } catch {}
}, CHECKPOINT_INTERVAL_MS);
if (typeof checkpointTimer.unref === "function") checkpointTimer.unref();
function gracefulClose() {
try { db.pragma("wal_checkpoint(TRUNCATE)"); } catch {}
try { stmtCache.clear(); } catch {}
try { db.close(); } catch {}
}
// Ensure WAL is flushed and -wal/-shm files removed on shutdown
const onShutdown = () => gracefulClose();
process.once("beforeExit", onShutdown);
process.once("SIGINT", () => { onShutdown(); process.exit(0); });
process.once("SIGTERM", () => { onShutdown(); process.exit(0); });
return {
driver: "better-sqlite3",
run(sql, params = []) { return prepare(sql).run(params); },
get(sql, params = []) { return prepare(sql).get(params); },
all(sql, params = []) { return prepare(sql).all(params); },
exec(sql) { return db.exec(sql); },
transaction(fn) { return db.transaction(fn)(); },
checkpoint() { try { db.pragma("wal_checkpoint(TRUNCATE)"); } catch {} },
close() {
clearInterval(checkpointTimer);
gracefulClose();
},
raw: db,
};
}