27 lines
1.7 KiB
TypeScript
27 lines
1.7 KiB
TypeScript
import {Pool,type PoolClient} from 'pg';
|
|
export type Connection=Pool|PoolClient;
|
|
const runtime=globalThis as typeof globalThis & {coursesPool?:Pool;coursesReady?:Promise<void>};
|
|
async function inTransaction<T>(pool:Pool,work:(client:PoolClient)=>Promise<T>):Promise<T>{
|
|
const client=await pool.connect();
|
|
try{await client.query('BEGIN');const result=await work(client);await client.query('COMMIT');return result;}
|
|
catch(error){await client.query('ROLLBACK').catch(()=>{});throw error;}
|
|
finally{client.release();}
|
|
}
|
|
export async function database():Promise<Pool>{
|
|
if(!runtime.coursesPool){
|
|
if(!process.env.DATABASE_URL)throw new Error('DATABASE_URL is required');
|
|
runtime.coursesPool=new Pool({connectionString:process.env.DATABASE_URL,max:4,connectionTimeoutMillis:5000,idleTimeoutMillis:30000,statement_timeout:15000});
|
|
runtime.coursesPool.on('error',()=>console.error('PostgreSQL connection unavailable'));
|
|
}
|
|
const pool=runtime.coursesPool;
|
|
runtime.coursesReady??=inTransaction(pool,async client=>{
|
|
await client.query('SELECT pg_advisory_xact_lock(72847321)');
|
|
await client.query('CREATE TABLE IF NOT EXISTS records(key TEXT PRIMARY KEY NOT NULL,value TEXT NOT NULL)');
|
|
await client.query("CREATE TABLE IF NOT EXISTS scan(id INTEGER PRIMARY KEY,data TEXT NOT NULL,lease BIGINT NOT NULL DEFAULT 0,token TEXT NOT NULL DEFAULT '')");
|
|
});
|
|
try{await runtime.coursesReady;}catch(error){runtime.coursesReady=undefined;throw error;}
|
|
return pool;
|
|
}
|
|
export async function transaction<T>(work:(client:PoolClient)=>Promise<T>):Promise<T>{return inTransaction(await database(),work);}
|
|
export async function closeDatabase(){const pool=runtime.coursesPool;runtime.coursesPool=undefined;runtime.coursesReady=undefined;if(pool)await pool.end();}
|