make the repository layer engine-agnostic (#1127)

DatabaseContext handed every repository a raw better-sqlite3 handle alongside
drizzle, and three of them used it for retention queries built on datetime('now',
?) — a SQLite-only function. That handle is the one thing standing between the
repository layer and a second engine.

Drop it. The two time-based prunes compute their cutoff in JS against the
CURRENT_TIMESTAMP text format, which every engine writes the same way and which
compares correctly as a string; the health-history prune becomes a select of the
rows to keep followed by a NOT IN delete. All three turn async, so their two
callers await them.

Name the dialect rather than repeating a string literal, so adding an engine is
one edit instead of a search.

Tests built their schema through context.sqlite?.exec(). Optional chaining meant
removing the field type-checked cleanly and then silently created no tables, so
the fixture now owns exec() and a raw handle for direct assertions — schema setup
belongs to the test harness, not to the interface repositories consume.

No behaviour change, and no Postgres yet: this only removes the coupling that
would have to be undone first.
This commit is contained in:
ZacharyZcR
2026-07-28 16:59:10 +08:00
committed by GitHub
parent cdb030dff1
commit 64a80f411a
50 changed files with 205 additions and 88 deletions
@@ -17,7 +17,7 @@ describe("AlertRepository", () => {
): Promise<AlertRepository> {
adapter = new TestSqliteDatabase();
const context = await adapter.connect();
context.sqlite?.exec(`
adapter.exec(`
CREATE TABLE users (
id TEXT PRIMARY KEY,
username TEXT NOT NULL,
@@ -229,7 +229,7 @@ describe("AlertRepository", () => {
expect(unacknowledged.total).toBe(0);
await repo.acknowledgeAllFirings("user-1");
repo.pruneFiringsOlderThan("user-1", 0);
await repo.pruneFiringsOlderThan("user-1", 0);
});
it("loads enabled rules and notification channels for the alert engine", async () => {