Files
Checkmate/Server/index.js
T

208 lines
5.6 KiB
JavaScript
Raw Normal View History

2024-10-15 11:57:37 +08:00
import path from "path";
import fs from "fs";
import swaggerUi from "swagger-ui-express";
2024-09-24 13:56:58 +08:00
2024-10-15 11:57:37 +08:00
import express from "express";
import helmet from "helmet";
import cors from "cors";
import logger from "./utils/logger.js";
import { verifyJWT } from "./middleware/verifyJWT.js";
import { handleErrors } from "./middleware/handleErrors.js";
import authRouter from "./routes/authRoute.js";
import inviteRouter from "./routes/inviteRoute.js";
import monitorRouter from "./routes/monitorRoute.js";
import checkRouter from "./routes/checkRoute.js";
import maintenanceWindowRouter from "./routes/maintenanceWindowRoute.js";
import settingsRouter from "./routes/settingsRoute.js";
2024-11-11 12:18:05 +08:00
import statusPageRouter from "./routes/statusPageRoute.js";
2024-10-15 11:57:37 +08:00
import { fileURLToPath } from "url";
2024-10-15 11:57:37 +08:00
import queueRouter from "./routes/queueRoute.js";
2024-10-22 15:26:38 +08:00
//JobQueue service and dependencies
2024-10-15 11:57:37 +08:00
import JobQueue from "./service/jobQueue.js";
2024-10-22 15:26:38 +08:00
import { Queue, Worker } from "bullmq";
//Network service and dependencies
2024-10-15 11:57:37 +08:00
import NetworkService from "./service/networkService.js";
import axios from "axios";
import ping from "ping";
import http from "http";
2024-11-13 10:36:42 +08:00
import Docker from "dockerode";
2024-10-17 14:33:18 +08:00
// Email service and dependencies
2024-10-15 11:57:37 +08:00
import EmailService from "./service/emailService.js";
2024-10-17 14:33:18 +08:00
import nodemailer from "nodemailer";
import pkg from "handlebars";
const { compile } = pkg;
import mjml2html from "mjml";
2024-10-21 16:14:19 +08:00
// Settings Service and dependencies
2024-10-15 11:57:37 +08:00
import SettingsService from "./service/settingsService.js";
2024-10-22 15:26:38 +08:00
import AppSettings from "./db/models/AppSettings.js";
2024-10-21 16:14:19 +08:00
2024-10-28 14:21:11 +08:00
import StatusService from "./service/statusService.js";
import NotificationService from "./service/notificationService.js";
2024-10-15 11:57:37 +08:00
import db from "./db/mongo/MongoDB.js";
const SERVICE_NAME = "Server";
2024-11-13 10:36:42 +08:00
const SHUTDOWN_TIMEOUT = 1000;
2024-08-06 13:52:48 -07:00
let isShuttingDown = false;
2024-10-15 11:57:37 +08:00
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
2024-09-24 13:56:58 +08:00
const openApiSpec = JSON.parse(
2024-10-16 11:46:03 +08:00
fs.readFileSync(path.join(__dirname, "openapi.json"), "utf8")
2024-09-24 13:56:58 +08:00
);
const PORT = 5000;
// Need to wrap server setup in a function to handle async nature of JobQueue
const startApp = async () => {
2024-10-16 11:46:03 +08:00
const app = express();
// middlewares
app.use(
cors()
//We will add configuration later
);
app.use(express.json());
app.use(helmet());
// Add db, jobQueue, emailService, and settingsService to request object for easy access
2024-10-16 11:46:03 +08:00
app.use((req, res, next) => {
req.db = db;
req.jobQueue = jobQueue;
req.emailService = emailService;
req.settingsService = settingsService;
next();
});
// Swagger UI
app.use("/api-docs", swaggerUi.serve, swaggerUi.setup(openApiSpec));
//routes
app.use("/api/v1/auth", authRouter);
app.use("/api/v1/settings", verifyJWT, settingsRouter);
app.use("/api/v1/invite", inviteRouter);
app.use("/api/v1/monitors", verifyJWT, monitorRouter);
app.use("/api/v1/checks", verifyJWT, checkRouter);
app.use("/api/v1/maintenance-window", verifyJWT, maintenanceWindowRouter);
app.use("/api/v1/queue", verifyJWT, queueRouter);
2024-11-11 12:18:05 +08:00
app.use("/api/v1/status-page", statusPageRouter);
2024-10-16 11:46:03 +08:00
2024-11-19 16:01:28 +08:00
app.use("/api/v1/dummy-data", async (req, res) => {
try {
const response = await axios.get(
"https://gist.githubusercontent.com/ajhollid/9afa39410c7bbf52cc905f285a2225bf/raw/429a231a3559ebc95f6f488ed2c766bd7d6f46e5/dummyData.json",
{
headers: {
"Content-Type": "application/json",
"Cache-Control": "no-cache",
},
}
);
return res.status(200).json(response.data);
} catch (error) {
return res.status(500).json({ message: error.message });
}
});
2024-10-16 11:46:03 +08:00
//health check
app.use("/api/v1/healthy", (req, res) => {
try {
2024-10-24 15:28:13 +08:00
logger.info({ message: "Checking Health of the server." });
2024-10-16 11:46:03 +08:00
return res.status(200).json({ message: "Healthy" });
} catch (error) {
2024-10-24 15:28:13 +08:00
logger.error({
message: error.message,
service: SERVICE_NAME,
method: "healthCheck",
stack: error.stack,
});
2024-10-16 11:46:03 +08:00
return res.status(500).json({ message: error.message });
}
});
/**
* Error handler middleware
* Should be called last
*/
app.use(handleErrors);
// Create services
await db.connect();
const server = app.listen(PORT, () => {
2024-10-24 15:28:13 +08:00
logger.info({ message: `server started on port:${PORT}` });
});
2024-10-16 11:46:03 +08:00
const settingsService = new SettingsService(AppSettings);
2024-10-16 11:46:03 +08:00
await settingsService.loadSettings();
2024-10-17 14:33:18 +08:00
const emailService = new EmailService(
settingsService,
fs,
path,
compile,
mjml2html,
nodemailer,
logger
);
2024-11-13 10:36:42 +08:00
const networkService = new NetworkService(axios, ping, logger, http, Docker);
2024-10-28 14:21:11 +08:00
const statusService = new StatusService(db, logger);
const notificationService = new NotificationService(emailService, db, logger);
2024-10-22 15:26:38 +08:00
const jobQueue = await JobQueue.createJobQueue(
db,
networkService,
2024-10-28 14:21:11 +08:00
statusService,
notificationService,
2024-10-22 15:26:38 +08:00
settingsService,
logger,
Queue,
Worker
);
2024-10-16 11:46:03 +08:00
const shutdown = async () => {
if (isShuttingDown) {
return;
}
isShuttingDown = true;
logger.info({ message: "Attempting graceful shutdown" });
setTimeout(() => {
logger.error({
message: "Could not shut down in time, forcing shutdown",
service: SERVICE_NAME,
method: "shutdown",
});
process.exit(1);
2024-10-31 17:01:27 +08:00
}, SHUTDOWN_TIMEOUT);
2024-10-16 11:46:03 +08:00
try {
server.close();
2024-10-16 11:46:03 +08:00
await jobQueue.obliterate();
await db.disconnect();
logger.info({ message: "Graceful shutdown complete" });
process.exit(0);
2024-10-16 11:46:03 +08:00
} catch (error) {
2024-10-24 15:28:13 +08:00
logger.error({
message: error.message,
2024-10-16 11:46:03 +08:00
service: SERVICE_NAME,
method: "shutdown",
2024-10-24 15:28:13 +08:00
stack: error.stack,
2024-10-16 11:46:03 +08:00
});
}
};
process.on("SIGUSR2", shutdown);
process.on("SIGINT", shutdown);
process.on("SIGTERM", shutdown);
};
2024-05-27 11:57:25 -07:00
startApp().catch((error) => {
2024-10-24 15:28:13 +08:00
logger.error({
message: error.message,
service: SERVICE_NAME,
2024-10-24 15:28:13 +08:00
method: "startApp",
stack: error.stack,
});
process.exit(1);
});