import sql from "mssql"; import { checkHostnamePort } from "../utils/checkHostNamePort.js"; import { sqlConfig } from "./prodSqlConfig.js"; import { createLogger } from "../logger/logger.js"; import { returnFunc } from "../utils/return.js"; import { validateEnv } from "../utils/envValidator.js"; const env = validateEnv(process.env); export let pool: any; export let connected: boolean = false; let reconnecting = false; export const initializeProdPool = async () => { const log = createLogger({ module: "prodSql" }); const serverUp = await checkHostnamePort(`${env.PROD_SERVER}:1433`); if (!serverUp) { reconnectToSql(); return returnFunc({ success: false, module: "prodSql", level: "fatal", message: `The sql ${env.PROD_SERVER} is not reachable`, data: [], }); } // if you were restarting from the endpoint you get this lovely error if (connected) { return returnFunc({ success: false, module: "prodSql", level: "error", message: `There is already a connection to ${env.PROD_PLANT_TOKEN}`, data: [], }); } try { pool = await sql.connect(sqlConfig); log.info( `Connected to ${sqlConfig?.server}, using DB: ${sqlConfig?.database}` ); connected = true; } catch (error) { log.fatal( `${JSON.stringify( error )}, "There was an error connecting to the pool."` ); reconnectToSql(); // throw new Error("There was an error closing the sql connection"); } }; const reconnectToSql = async () => { const log = createLogger({ module: "prodSql" }); if (reconnecting) return; reconnecting = true; let delay = 2000; // start at 2s let attempts = 0; const maxAttempts = 10; // or limit by time, e.g. 2 min total while (!connected && attempts < maxAttempts) { attempts++; log.info( `Reconnect attempt ${attempts}/${maxAttempts} in ${ delay / 1000 }s...` ); await new Promise((res) => setTimeout(res, delay)); const serverUp = await checkHostnamePort(`${env.PROD_SERVER}:1433`); if (!serverUp) { delay = Math.min(delay * 2, 30000); // exponential backoff up to 30s continue; } try { pool = sql.connect(sqlConfig); log.info( `Connected to ${sqlConfig?.server}, and looking at ${sqlConfig?.database}` ); reconnecting = false; connected = true; } catch (error) { log.fatal( `${JSON.stringify( error )}, "There was an error connecting to the pool."` ); delay = Math.min(delay * 2, 30000); // exponential backoff up to 30s // throw new Error("There was an error closing the sql connection"); } } if (!connected) { log.fatal( { notify: true }, "Max reconnect attempts reached on the prodSql server. Stopping retries." ); reconnecting = false; // optional: exit process or alert someone here // process.exit(1); } }; export const closePool = async () => { const log = createLogger({ module: "prodSql" }); if (!connected) { log.error("There is no connection a connection."); return { success: false, message: "There is already a connection." }; } try { await pool.close(); log.info("Connection pool closed"); connected = false; return { success: true, message: "The sql server connection has been closed", }; } catch (error) { log.fatal( { notify: true }, `${JSON.stringify( error )}, "There was an error closing the sql connection"` ); } };