import sql from "mssql"; import { prodSqlConfig } from "../configs/prodSql.config.js"; import { createLogger } from "../logger/logger.controller.js"; import { checkHostnamePort } from "../utils/checkHost.utils.js"; import { returnFunc } from "../utils/returnHelper.utils.js"; export let pool: sql.ConnectionPool; export let connected: boolean = false; export let reconnecting = false; export const connectProdSql = async () => { const serverUp = await checkHostnamePort(`${process.env.PROD_SERVER}:1433`); if (!serverUp) { // we will try to reconnect connected = false; return returnFunc({ success: false, level: "error", module: "system", subModule: "db", message: "Prod server is offline or unreachable.", }); } // if we are trying to click restart from the api for some reason we want to kick back and say no if (connected) { return returnFunc({ success: false, level: "error", module: "system", subModule: "db", message: "The Sql server is already connected.", }); } // try to connect to the sql server try { pool = await sql.connect(prodSqlConfig); connected = true; return returnFunc({ success: true, level: "info", module: "system", subModule: "db", message: `${prodSqlConfig.server} is connected to ${prodSqlConfig.database}`, data: [], notify: false, }); } catch (error) { return returnFunc({ success: false, level: "error", module: "system", subModule: "db", message: "Failed to connect to the prod sql server.", data: [error], notify: false, }); } }; export const closePool = async () => { if (!connected) { return returnFunc({ success: false, level: "error", module: "system", subModule: "db", message: "There is no connection to the prod server currently.", }); } try { await pool.close(); connected = false; return returnFunc({ success: true, level: "info", module: "system", subModule: "db", message: "The sql connection has been closed.", }); } catch (error) { connected = false; return returnFunc({ success: false, level: "error", module: "system", subModule: "db", message: "There was an error closing the sql connection", data: [error], }); } }; export const reconnectToSql = async () => { const log = createLogger({ module: "system", subModule: "db", }); if (reconnecting) return; //set reconnecting to true while we try to reconnect reconnecting = true; // start the delay out as 2 seconds let delayStart = 2000; let attempt = 0; const maxAttempts = 10; while (!connected && attempt < maxAttempts) { attempt++; log.info( `Reconnect attempt ${attempt}/${maxAttempts} in ${delayStart / 1000}s ...`, ); await new Promise((res) => setTimeout(res, delayStart)); const serverUp = await checkHostnamePort(`${process.env.PROD_SERVER}:1433`); if (!serverUp) { delayStart = Math.min(delayStart * 2, 30000); // exponential backoff until up to 30000 return; } try { pool = await sql.connect(prodSqlConfig); reconnecting = false; connected = true; log.info( `${prodSqlConfig.server} is connected to ${prodSqlConfig.database}`, ); } catch (error) { delayStart = Math.min(delayStart * 2, 30000); return returnFunc({ success: false, level: "error", module: "system", subModule: "db", message: "Failed to reconnect to the prod sql server.", data: [error], notify: false, }); } } if (!connected) { log.error( { notify: true }, "Max reconnect attempts reached on the prodSql server. Stopping retries.", ); reconnecting = false; // exit alert someone here } };