UNPKG

pg-cache

Version:
79 lines (78 loc) 3.86 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.getPgPool = void 0; const pg_1 = __importDefault(require("pg")); const pg_env_1 = require("pg-env"); const logger_1 = require("@pgpmjs/logger"); const lru_1 = require("./lru"); const log = new logger_1.Logger('pg-cache'); const getDbString = (user, password, host, port, database) => `postgres://${user}:${password}@${host}:${port}/${database}`; const getPgPool = (pgConfig) => { const config = (0, pg_env_1.getPgEnvOptions)(pgConfig); const { user, password, host, port, database, } = config; if (lru_1.pgCache.has(database)) { const cached = lru_1.pgCache.get(database); if (cached) return cached; } const connectionString = getDbString(user, password, host, port, database); const pgPool = new pg_1.default.Pool({ connectionString }); /** * IMPORTANT: Pool-level error handler for idle connection errors. * * WHY THIS EXISTS: * pg-pool maintains a pool of database connections. When a connection is idle * (not actively running a query) and the server terminates it (e.g., during * database cleanup via pg_terminate_backend), pg-pool emits an 'error' event * on the pool's EventEmitter. In Node.js, an EventEmitter 'error' event with * no listeners is FATAL and crashes the entire process with an unhelpful * stack trace showing internal pg-pool/pg-protocol objects. * * WHY THIS IS SAFE (does NOT swallow real errors): * This handler ONLY catches errors emitted on IDLE pooled connections via * the EventEmitter pattern. It does NOT intercept errors from active queries. * * Error paths in pg-pool: * 1. QUERY ERRORS (pool.query(), client.query()): * - Returned via Promise rejection * - Bubble up through async/await as normal exceptions * - NOT affected by this handler - they still throw as expected * - Examples: syntax errors, constraint violations, connection refused * * 2. IDLE CONNECTION ERRORS (this handler): * - Emitted via EventEmitter when server kills an idle connection * - Without a handler: crashes Node.js process * - With this handler: logged and process continues * - Examples: pg_terminate_backend during cleanup, server restart * * WHEN THIS FIRES: * - pgpm test-packages creates temp databases, deploys, then drops them * - Dropping requires pg_terminate_backend() to kill active connections * - Idle connections in the pool receive PostgreSQL error 57P01 * - This handler catches that expected cleanup error * * PostgreSQL error codes handled: * - 57P01: admin_shutdown (terminating connection due to administrator command) * This is EXPECTED during database teardown and logged at debug level. * * All other error codes are logged at error level for visibility but do not * crash the process, allowing the test harness to continue and report results. */ pgPool.on('error', (err) => { if (err.code === '57P01') { // Expected during database cleanup - log at debug level log.debug(`Pool ${database} connection terminated (expected during cleanup): ${err.message}`); } else { // Unexpected pool error - log at error level for visibility // Note: This does NOT swallow query errors - those still throw via Promise rejection log.error(`Pool ${database} unexpected idle connection error [${err.code || 'unknown'}]: ${err.message}`); } }); lru_1.pgCache.set(database, pgPool); return pgPool; }; exports.getPgPool = getPgPool;