client.ts73 lines · main
1import { drizzle } from 'drizzle-orm/node-postgres';
2import pg from 'pg';
3
4import { env } from '../env.js';
5import { log } from '../lib/logger.js';
6
7import * as schema from './schema.js';
8
9/**
10 * Control-plane meta-DB pool — **Doltgres-first** (see repo `DOLTGRES-FIRST.md`).
11 *
12 * Talks to Doltgres database `briven_control` via `pg` (node-postgres).
13 * Never use `postgres` (postgres.js) against Doltgres — wire panics
14 * (`unhandled message "&{}"`). Same rule as the data plane.
15 *
16 * Lazy-initialised: `/ready` reports not_configured until BRIVEN_DATABASE_URL
17 * is set.
18 */
19let _pool: pg.Pool | null = null;
20let _db: ReturnType<typeof drizzle<typeof schema>> | null = null;
21
22export function getDb() {
23 if (!env.BRIVEN_DATABASE_URL) {
24 throw new Error('BRIVEN_DATABASE_URL is not configured');
25 }
26 if (!_db) {
27 _pool = new pg.Pool({
28 connectionString: env.BRIVEN_DATABASE_URL,
29 max: 10,
30 idleTimeoutMillis: 30_000,
31 connectionTimeoutMillis: 5_000,
32 });
33 _db = drizzle(_pool, { schema });
34 log.info('db_connected', { max: 10, driver: 'node-postgres' });
35 }
36 return _db;
37}
38
39export function getPool(): pg.Pool {
40 if (!_pool) {
41 getDb();
42 }
43 return _pool as pg.Pool;
44}
45
46/** @deprecated Prefer getDb() / getPool(). Kept for ping helper. */
47export function getSqlClient(): pg.Pool {
48 return getPool();
49}
50
51export async function pingDb(): Promise<boolean> {
52 if (!env.BRIVEN_DATABASE_URL) return false;
53 try {
54 const pool = getPool();
55 await pool.query('SELECT 1');
56 return true;
57 } catch (err) {
58 log.warn('db_ping_failed', {
59 message: err instanceof Error ? err.message : String(err),
60 });
61 return false;
62 }
63}
64
65export async function closeDb(): Promise<void> {
66 if (_pool) {
67 await _pool.end();
68 _pool = null;
69 _db = null;
70 }
71}
72
73export { schema };