2023-01-13 05:40:33 +01:00
|
|
|
import cluster from "node:cluster";
|
|
|
|
import chalk from "chalk";
|
|
|
|
import Xev from "xev";
|
2019-04-07 14:50:36 +02:00
|
|
|
|
2023-01-13 05:40:33 +01:00
|
|
|
import Logger from "@/services/logger.js";
|
|
|
|
import { envOption } from "../env.js";
|
2019-04-07 14:50:36 +02:00
|
|
|
|
|
|
|
// for typeorm
|
2023-01-13 05:40:33 +01:00
|
|
|
import "reflect-metadata";
|
|
|
|
import { masterMain } from "./master.js";
|
|
|
|
import { workerMain } from "./worker.js";
|
2023-03-23 08:12:41 +01:00
|
|
|
import os from "node:os";
|
2019-04-07 14:50:36 +02:00
|
|
|
|
2023-01-13 05:40:33 +01:00
|
|
|
const logger = new Logger("core", "cyan");
|
|
|
|
const clusterLogger = logger.createSubLogger("cluster", "orange", false);
|
2022-04-17 07:42:13 +02:00
|
|
|
const ev = new Xev();
|
2019-04-07 14:50:36 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Init process
|
|
|
|
*/
|
2023-01-13 05:40:33 +01:00
|
|
|
export default async function () {
|
2023-07-22 17:15:14 +02:00
|
|
|
process.title = `Iceshrimp (${cluster.isPrimary ? "master" : "worker"})`;
|
2023-01-13 05:40:33 +01:00
|
|
|
|
|
|
|
if (cluster.isPrimary || envOption.disableClustering) {
|
2022-12-16 01:09:00 +01:00
|
|
|
await masterMain();
|
|
|
|
if (cluster.isPrimary) {
|
2023-01-13 05:40:33 +01:00
|
|
|
ev.mount();
|
2022-12-16 01:09:00 +01:00
|
|
|
}
|
2023-01-13 05:40:33 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if (cluster.isWorker || envOption.disableClustering) {
|
2022-12-16 01:09:00 +01:00
|
|
|
await workerMain();
|
2023-03-23 08:12:41 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if (cluster.isPrimary) {
|
|
|
|
// Leave the master process with a marginally lower priority but not too low.
|
|
|
|
os.setPriority(2);
|
|
|
|
}
|
|
|
|
if (cluster.isWorker) {
|
|
|
|
// Set workers to a much lower priority so that the master process will be
|
|
|
|
// able to respond to api calls even if the workers gank everything.
|
|
|
|
os.setPriority(10);
|
2023-01-13 05:40:33 +01:00
|
|
|
}
|
|
|
|
|
2023-07-22 17:15:14 +02:00
|
|
|
// For when Iceshrimp is started in a child process during unit testing.
|
2023-01-13 05:40:33 +01:00
|
|
|
// Otherwise, process.send cannot be used, so start it.
|
|
|
|
if (process.send) {
|
|
|
|
process.send("ok");
|
|
|
|
}
|
2019-04-07 14:50:36 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
//#region Events
|
|
|
|
|
|
|
|
// Listen new workers
|
2023-01-13 05:40:33 +01:00
|
|
|
cluster.on("fork", (worker) => {
|
|
|
|
clusterLogger.debug(`Process forked: [${worker.id}]`);
|
2019-04-07 14:50:36 +02:00
|
|
|
});
|
|
|
|
|
|
|
|
// Listen online workers
|
2023-01-13 05:40:33 +01:00
|
|
|
cluster.on("online", (worker) => {
|
|
|
|
clusterLogger.debug(`Process is now online: [${worker.id}]`);
|
2019-04-07 14:50:36 +02:00
|
|
|
});
|
|
|
|
|
|
|
|
// Listen for dying workers
|
2023-01-13 05:40:33 +01:00
|
|
|
cluster.on("exit", (worker) => {
|
|
|
|
// Replace the dead worker,
|
|
|
|
// we're not sentimental
|
|
|
|
clusterLogger.error(chalk.red(`[${worker.id}] died :(`));
|
|
|
|
cluster.fork();
|
2019-04-07 14:50:36 +02:00
|
|
|
});
|
|
|
|
|
|
|
|
// Display detail of unhandled promise rejection
|
2021-10-08 14:24:05 +02:00
|
|
|
if (!envOption.quiet) {
|
2023-01-13 05:40:33 +01:00
|
|
|
process.on("unhandledRejection", console.dir);
|
2019-04-07 14:50:36 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// Display detail of uncaught exception
|
2023-01-13 05:40:33 +01:00
|
|
|
process.on("uncaughtException", (err) => {
|
|
|
|
try {
|
2022-12-16 01:09:00 +01:00
|
|
|
logger.error(err);
|
2023-01-13 05:40:33 +01:00
|
|
|
} catch {}
|
2019-04-07 14:50:36 +02:00
|
|
|
});
|
|
|
|
|
|
|
|
// Dying away...
|
2023-01-13 05:40:33 +01:00
|
|
|
process.on("exit", (code) => {
|
|
|
|
logger.info(`The process is going to exit with code ${code}`);
|
2019-04-07 14:50:36 +02:00
|
|
|
});
|
|
|
|
|
|
|
|
//#endregion
|