- Add modular DB layer (adapters, migrations, repos, helpers) - Replace localDb/usageDb/requestDetailsDb monoliths with repos - Add Tailscale tunnel integration & status check API - Add /api/cli-tools/all-statuses aggregated endpoint - Add settingsStore (Zustand) and mitm/dbReader - Add DB unit tests (benchmark, concurrent, migration, vs-lowdb)
55 lines
1.8 KiB
JavaScript
55 lines
1.8 KiB
JavaScript
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,
|
|
};
|
|
}
|