157 lines
3.6 KiB
TypeScript
157 lines
3.6 KiB
TypeScript
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
|
|
}
|
|
};
|