93 lines · 3.8 KB
import { describe, expect, mock, test } from "bun:test";
import { Database } from "bun:sqlite";

mock.module("../scoped-db/locators", () => ({ forgetLocator: async () => undefined }));

const { ACCOUNT_SCHEMA } = await import("../scoped-db/schema.gen");
const { ACCOUNT_SCHEMA_EXTRA } = await import("../scoped-db/schema-extra");
const { armsHousekeeping, mark, nextDue, registerAccountTasks, runAccountTasks, SESSION_IDLE_MS, sweepDue } =
  await import("./housekeeping");

const ran: string[] = [];
registerAccountTasks([
  {
    name: "digest",
    arms: /^\s*INSERT\s+INTO\s+notification_digest_items\b/i,
    due: (sql) =>
      (sql.exec<{ due: number | null }>("SELECT MIN(flush_after) AS due FROM notification_digest_items").toArray()[0]
        ?.due as number | null) ?? null,
    run: async () => void ran.push("digest"),
  },
  {
    name: "alerts",
    marks: /^\s*INSERT\s+INTO\s+usage_events\b/i,
    debounce: 60_000,
    run: async () => {
      ran.push("alerts");
      throw new Error("boom");
    },
  },
]);

function store() {
  const db = new Database(":memory:");
  for (const statement of [...ACCOUNT_SCHEMA, ...ACCOUNT_SCHEMA_EXTRA]) db.run(statement);
  const sql = {
    // Eager, like Durable Object SQL: a statement runs whether or not its rows are read.
    exec: (query: string, ...params: Array<string | number | null>) => {
      const rows = db.query(query).all(...params) as never[];
      return { toArray: () => rows };
    },