45 lines
1.3 KiB
TypeScript
45 lines
1.3 KiB
TypeScript
/**
|
|
* The database handle. Importing this module opens the database at
|
|
* {@link DB_PATH}, applies the pending migrations and runs the startup tasks.
|
|
*
|
|
* @module
|
|
*/
|
|
|
|
import { DatabaseSync } from "node:sqlite";
|
|
import { DB_PATH } from "../config.ts";
|
|
import { runMigrations } from "./migrate.ts";
|
|
import { runStartupTasks } from "./startup.ts";
|
|
|
|
/** The one connection every service queries through. */
|
|
export const db: DatabaseSync = new DatabaseSync(DB_PATH);
|
|
// WAL lets readers run alongside a writer, and with synchronous = NORMAL a
|
|
// commit no longer waits on an fsync (a crash can lose the last transactions,
|
|
// never corrupt the file). busy_timeout covers the init/migration scripts and
|
|
// the test harness opening the same file.
|
|
db.exec(`
|
|
PRAGMA journal_mode = WAL;
|
|
PRAGMA synchronous = NORMAL;
|
|
PRAGMA busy_timeout = 5000;
|
|
PRAGMA foreign_keys = ON;
|
|
`);
|
|
runMigrations(db);
|
|
await runStartupTasks(db);
|
|
|
|
/**
|
|
* Runs `fn` inside one transaction: several writes commit together (and cost
|
|
* one commit rather than one each), and a throw rolls them all back. Nested
|
|
* calls join the outer transaction.
|
|
*/
|
|
export function transaction<T>(fn: () => T): T {
|
|
if (db.isTransaction) return fn();
|
|
db.exec("BEGIN;");
|
|
try {
|
|
const result = fn();
|
|
db.exec("COMMIT;");
|
|
return result;
|
|
} catch (err) {
|
|
db.exec("ROLLBACK;");
|
|
throw err;
|
|
}
|
|
}
|