import type { createPinboard } from "./server.js"; export namespace PostgresDurabilityStore { /** Structurally a pg Pool or Client; the deployment supplies the driver. */ export type Queryable = { query( text: string, values?: unknown[], ): Promise<{ rows: Record[]; rowCount: number | null }>; }; } /** DurabilityStore over the pinned host's `pinned_tray_index` table: a * `marked` row `(ns, id, tray_ns, tray_id)` means a tray has in-flight * work, so its instance needs waking; unmarked rows stay put. */ export class PostgresDurabilityStore implements createPinboard.DurabilityStore { private readonly db: PostgresDurabilityStore.Queryable; constructor(db: PostgresDurabilityStore.Queryable) { this.db = db; } async listMarked( cursor: string | null, limit: number, ): Promise<{ entries: { env: string; hostname: string; ns: string; id: string }[]; cursor: string | null; }> { if (!Number.isInteger(limit) || limit < 1) { throw new Error(`limit must be a positive integer: ${limit}`); } let after: [string, string, string] = ["", "", ""]; if (cursor !== null) { const parsed: unknown = JSON.parse(cursor); if ( !Array.isArray(parsed) || parsed.length !== 3 || parsed.some((part) => typeof part !== "string") ) { throw new Error(`malformed cursor: ${cursor}`); } after = parsed as [string, string, string]; } const { rows } = await this.db.query( "SELECT DISTINCT ON (env, ns, id) env, hostname, ns, id " + "FROM pinned_tray_index " + "WHERE marked AND (env, ns, id) > ($1, $2, $3) " + "ORDER BY env, ns, id, hostname LIMIT $4", [after[0], after[1], after[2], limit], ); const entries = rows.map((row) => ({ env: String(row["env"]), hostname: String(row["hostname"]), ns: String(row["ns"]), id: String(row["id"]), })); const last = entries[entries.length - 1]; return { entries, cursor: entries.length < limit || last === undefined ? null : JSON.stringify([last.env, last.ns, last.id]), }; } }