monkeytype/backend/src/server.ts

108 lines
3.3 KiB
TypeScript

import "dotenv/config";
import * as db from "./init/db";
import jobs from "./jobs";
import {
getLiveConfiguration,
updateFromConfigurationFile,
} from "./init/configuration";
import app from "./app";
import { Server } from "http";
import { version } from "./version";
import { recordServerVersion } from "./utils/prometheus";
import * as RedisClient from "./init/redis";
import queues from "./queues";
import workers from "./workers";
import Logger from "./utils/logger";
import * as EmailClient from "./init/email-client";
import { init as initFirebaseAdmin } from "./init/firebase-admin";
import { createIndicies as leaderboardDbSetup } from "./dal/leaderboards";
import { createIndicies as blocklistDbSetup } from "./dal/blocklist";
import { getErrorMessage } from "./utils/error";
import { exit } from "process";
async function bootServer(port: number): Promise<Server> {
try {
Logger.info(`Starting server version ${version}`);
Logger.info(`Starting server in ${process.env["MODE"]} mode`);
process.on("unhandledRejection", (err) => {
const isDbError =
err instanceof Error && /ECONNREFUSED.*27017/i.test(err.message);
if (isDbError) {
Logger.error("Failed to connect to database, ignore error");
} else {
Logger.error("Unhandled rejection: " + getErrorMessage(err));
exit(-1);
}
});
Logger.info(`Connecting to database ${process.env["DB_NAME"]}...`);
await db.connect();
Logger.success("Connected to database");
Logger.info("Initializing Firebase app instance...");
initFirebaseAdmin();
Logger.info("Fetching live configuration...");
await getLiveConfiguration();
Logger.success("Live configuration fetched");
await updateFromConfigurationFile();
Logger.info("Initializing email client...");
await EmailClient.init();
Logger.info("Connecting to redis...");
await RedisClient.connect();
if (RedisClient.isConnected()) {
Logger.success("Connected to redis");
const connection = RedisClient.getConnection();
Logger.info("Initializing queues...");
queues.forEach((queue) => {
queue.init(connection ?? undefined);
});
Logger.success(
`Queues initialized: ${queues
.map((queue) => queue.queueName)
.join(", ")}`
);
Logger.info("Initializing workers...");
workers.forEach(async (worker) => {
await worker(connection ?? undefined).run();
});
Logger.success(
`Workers initialized: ${workers
.map((worker) => worker(connection ?? undefined).name)
.join(", ")}`
);
}
Logger.info("Starting cron jobs...");
jobs.forEach((job) => job.start());
Logger.success("Cron jobs started");
Logger.info("Setting up leaderboard indicies...");
await leaderboardDbSetup();
Logger.info("Setting up blocklist indicies...");
await blocklistDbSetup();
recordServerVersion(version);
} catch (error) {
Logger.error("Failed to boot server");
const message = getErrorMessage(error);
Logger.error(message ?? "Unknown error");
console.error(error);
return process.exit(1);
}
return app.listen(PORT, () => {
Logger.success(`API server listening on port ${port}`);
});
}
const PORT = parseInt(process.env["PORT"] ?? "5005", 10);
void bootServer(PORT);