Files
TREK/server/src/db/durability.ts
T
Maurice 98ad2450a2 feat(db): make the SQLite journal mode configurable (#1675)
WAL was hardcoded, and on network-backed storage — Azure App Service Linux,
SMB/NFS volumes on NAS and PaaS — SQLite documents it as unsafe, because the
coordination runs through the -shm file and mmap. Operators had no way out.

TREK_DB_JOURNAL_MODE and TREK_DB_SYNCHRONOUS now set both pragmas, defaulting
to today's behaviour. The mode lives in the file header, so all three
processes that open travel.db read the same configuration — the server,
reset-admin.js and migrate-encryption.ts, which used to hard-set WAL and would
have silently reverted a deliberate DELETE setup on the first key rotation.

An invalid value falls back and warns rather than refusing to start, and the
mode that actually took effect is read back and logged, so an operator can see
whether the setting landed.
2026-07-29 17:02:56 +02:00

37 lines
1.5 KiB
TypeScript

import type Database from 'better-sqlite3';
import { readEnv } from '../app-config';
import { synchronousName } from '../app-config/parsers';
export interface ActiveDurability {
journalMode: string;
synchronous: string;
}
/**
* Applies the configured journal_mode / synchronous pragmas to a freshly opened
* connection and reports back what SQLite actually settled on.
*
* journal_mode is stored in the database file header, so it is not a per-process
* setting: whichever process opened the file last decides the mode for all of
* them. reset-admin.js and scripts/migrate-encryption.ts open the same file and
* therefore read the same two variables — they cannot import this module (they
* are standalone scripts and src/ is not in the image), so keep the three in
* sync when the defaults change.
*
* The returned values are read back from the engine rather than echoed from the
* config, so a mode SQLite refused shows up as what it really is — an in-memory
* database stays MEMORY however hard you ask for WAL.
*/
export function applyDurabilityPragmas(db: Database.Database): ActiveDurability {
const { journalMode, synchronous, durabilityWarnings } = readEnv().db;
durabilityWarnings.forEach(warning => console.warn(`[DB] ${warning}`));
db.exec(`PRAGMA journal_mode = ${journalMode}`);
db.exec(`PRAGMA synchronous = ${synchronous}`);
return {
journalMode: String(db.pragma('journal_mode', { simple: true })).toUpperCase(),
synchronous: synchronousName(db.pragma('synchronous', { simple: true })),
};
}