aboutsummaryrefslogtreecommitdiff
path: root/src/server/session.ts
diff options
context:
space:
mode:
Diffstat (limited to 'src/server/session.ts')
-rw-r--r--src/server/session.ts142
1 files changed, 0 insertions, 142 deletions
diff --git a/src/server/session.ts b/src/server/session.ts
deleted file mode 100644
index ec51b6e18..000000000
--- a/src/server/session.ts
+++ /dev/null
@@ -1,142 +0,0 @@
-import { yellow, red, cyan, magenta, green } from "colors";
-import { isMaster, on, fork, setupMaster, Worker } from "cluster";
-import InputManager from "./session_manager/input_manager";
-import { execSync } from "child_process";
-import { Email } from "./session_manager/email";
-import { get } from "request-promise";
-import { WebSocket } from "./Websocket/Websocket";
-import { Utils } from "../Utils";
-import { MessageStore } from "./Message";
-
-const onWindows = process.platform === "win32";
-const heartbeat = `http://localhost:1050/serverHeartbeat`;
-const admin = ["samuel_wilkins@brown.edu"];
-
-export namespace Session {
-
- export let key: string;
- export const signature = "Best,\nServer Session Manager";
- let activeWorker: Worker;
- let listening = false;
- const masterIdentifier = `${yellow("__master__")}:`;
- const workerIdentifier = `${magenta("__worker__")}:`;
-
- function log(message?: any, ...optionalParams: any[]) {
- const identifier = isMaster ? masterIdentifier : workerIdentifier;
- console.log(identifier, message, ...optionalParams);
- }
-
- export async function distributeKey() {
- key = Utils.GenerateGuid();
- const timestamp = new Date().toUTCString();
- const content = `The key for this session (started @ ${timestamp}) is ${key}.\n\n${signature}`;
- return Promise.all(admin.map(recipient => Email.dispatch(recipient, "Server Termination Key", content)));
- }
-
- function tryKillActiveWorker() {
- if (activeWorker && !activeWorker.isDead()) {
- activeWorker.process.kill();
- return true;
- }
- return false;
- }
-
- function logLifecycleEvent(lifecycle: string) {
- process.send?.({ lifecycle });
- }
-
- function messageHandler({ lifecycle, action }: any) {
- if (action) {
- console.log(`${workerIdentifier} action requested (${action})`);
- switch (action) {
- case "kill":
- log(red("An authorized user has ended the server from the /kill route"));
- tryKillActiveWorker();
- process.exit(0);
- }
- } else if (lifecycle) {
- console.log(`${workerIdentifier} lifecycle phase (${lifecycle})`);
- }
- }
-
- async function activeExit(error: Error) {
- if (!listening) {
- return;
- }
- listening = false;
- await Promise.all(admin.map(recipient => Email.dispatch(recipient, "Dash Web Server Crash", crashReport(error))));
- const { _socket } = WebSocket;
- if (_socket) {
- Utils.Emit(_socket, MessageStore.ConnectionTerminated, "Manual");
- }
- logLifecycleEvent(red(`Crash event detected @ ${new Date().toUTCString()}`));
- logLifecycleEvent(red(error.message));
- process.exit(1);
- }
-
- function crashReport({ name, message, stack }: Error) {
- return [
- "You, as a Dash Administrator, are being notified of a server crash event. Here's what we know:",
- `name:\n${name}`,
- `message:\n${message}`,
- `stack:\n${stack}`,
- "The server is already restarting itself, but if you're concerned, use the Remote Desktop Connection to monitor progress.",
- signature
- ].join("\n\n");
- }
-
- export async function initialize(work: Function) {
- if (isMaster) {
- process.on("uncaughtException", error => {
- if (error.message !== "Channel closed") {
- log(red(error.message));
- if (error.stack) {
- log(`\n${red(error.stack)}`);
- }
- }
- });
- setupMaster({ silent: true });
- const spawn = () => {
- tryKillActiveWorker();
- activeWorker = fork();
- activeWorker.on("message", messageHandler);
- };
- spawn();
- on("exit", ({ process: { pid } }, code, signal) => {
- const prompt = `Server worker with process id ${pid} has exited with code ${code}${signal === null ? "" : `, having encountered signal ${signal}`}.`;
- log(cyan(prompt));
- spawn();
- });
- const { registerCommand } = new InputManager({ identifier: masterIdentifier });
- registerCommand("exit", [], () => execSync(onWindows ? "taskkill /f /im node.exe" : "killall -9 node"));
- registerCommand("pull", [], () => execSync("git pull", { stdio: ["ignore", "inherit", "inherit"] }));
- registerCommand("restart", [], () => {
- listening = false;
- tryKillActiveWorker();
- });
- } else {
- logLifecycleEvent(green("initializing..."));
- process.on('uncaughtException', activeExit);
- const checkHeartbeat = async () => {
- await new Promise<void>(resolve => {
- setTimeout(async () => {
- try {
- await get(heartbeat);
- if (!listening) {
- logLifecycleEvent(green("listening..."));
- }
- listening = true;
- resolve();
- } catch (error) {
- await activeExit(error);
- }
- }, 1000 * 15);
- });
- checkHeartbeat();
- };
- work();
- checkHeartbeat();
- }
- }
-
-} \ No newline at end of file