portal-payment-be/src/lib/dbPools.ts

76 lines
1.8 KiB
TypeScript

import { Pool } from "pg";
import prisma from "../prisma";
import db from "../db";
type PoolEntry = {
pool: Pool;
lastUsed: number;
};
const poolCache = new Map<string, PoolEntry>();
const POOL_TTL_MS = 1000 * 60 * 30; // 30 minutes TTL for idle pools
function buildConnString(db: {
host: string;
port: number;
username: string;
password: string;
name: string;
ssl?: boolean;
}) {
// Use pg connection string
const { host, port, username, password, name, ssl } = db;
return `postgresql://${encodeURIComponent(username)}:${encodeURIComponent(
password
)}@${host}:${port}/${encodeURIComponent(name)}${
ssl ? "?sslmode=require" : ""
}`;
}
export async function getPoolForDbId(db_id: string) {
// const now = Date.now();
// const cached = poolCache.get(db_id);
// if (cached) {
// cached.lastUsed = now;
// return cached.pool;
// }
// load credentials from central metadata table (prisma database model)
const dbRec = await prisma.database.findUnique({ where: { db_id } });
if (!dbRec) throw new Error("database not found");
const connString = buildConnString({
host: dbRec.host,
port: Number(dbRec.port),
username: dbRec.username,
password: dbRec.password,
name: dbRec.db_name,
});
await db.activity_logs.create({
data: {
action: "GET",
status: "SUCCESS",
message: "connString: " + connString,
},
});
const pool = new Pool({
connectionString: connString,
max: 10,
idleTimeoutMillis: 3600000,
});
return pool;
}
// optional: background cleanup
setInterval(() => {
const now = Date.now();
for (const [key, entry] of poolCache.entries()) {
if (now - entry.lastUsed > POOL_TTL_MS) {
try {
entry.pool.end().catch(() => {});
} catch {}
poolCache.delete(key);
}
}
}, 1000 * 60 * 5);