import pg from 'pg' const { Pool } = pg let pool: pg.Pool | null = null /** * Obtiene o crea el pool de conexiones a PostgreSQL. * Usa variables de entorno para la configuración. */ export function getPool(): pg.Pool { if (!pool) { const config = { user: process.env.POSTGRES_USER || 'seguidor', password: process.env.POSTGRES_PASSWORD || 'seguidor_password', database: process.env.POSTGRES_DB || 'seguidor_lotes', host: process.env.POSTGRES_HOST || 'postgres', port: parseInt(process.env.POSTGRES_PORT || '5432'), max: 20, // máximo de conexiones en el pool idleTimeoutMillis: 30000, connectionTimeoutMillis: 10000, // Aumentado a 10s para la primera conexión } pool = new Pool(config) pool.on('error', (err) => { console.error('Error inesperado en el pool de PostgreSQL:', err) }) // Solo log en desarrollo para reducir ruido if (process.env.NODE_ENV !== 'production') { pool.on('connect', () => { console.log('Nueva conexión establecida con PostgreSQL') }) } } return pool } /** * Ejecuta una query SQL con parámetros. * Wrapper seguro para evitar inyección SQL. * * @param text - Query SQL con placeholders $1, $2, etc. * @param params - Parámetros para la query * @returns Resultado de la query */ export async function query( text: string, params?: any[] ): Promise> { const pool = getPool() const start = Date.now() try { const result = await pool.query(text, params) const duration = Date.now() - start // Log solo en desarrollo if (process.env.NODE_ENV !== 'production') { console.log('Query ejecutada:', { text, duration: `${duration}ms`, rows: result.rowCount }) } return result } catch (error) { console.error('Error ejecutando query:', { text, params, error }) throw error } } /** * Obtiene un cliente del pool para ejecutar transacciones. * IMPORTANTE: Debes llamar a client.release() al terminar. * * @returns Cliente de PostgreSQL */ export async function getClient(): Promise { const pool = getPool() return await pool.connect() } /** * Cierra el pool de conexiones. * Útil para tests o shutdown graceful. */ export async function closePool(): Promise { if (pool) { await pool.end() pool = null console.log('Pool de PostgreSQL cerrado') } } /** * Verifica que la conexión a la base de datos esté funcionando. * Útil para health checks. * * @returns true si la conexión está OK, false en caso contrario */ export async function checkConnection(): Promise { try { const result = await query('SELECT NOW() as now') return result.rows.length > 0 } catch (error) { console.error('Error verificando conexión a PostgreSQL:', error) return false } }