aboutsummaryrefslogtreecommitdiff
path: root/src/server/ChildProcessUtilities/daemon/session.ts
diff options
context:
space:
mode:
authorBob Zeleznik <zzzman@gmail.com>2019-12-14 21:50:27 -0500
committerBob Zeleznik <zzzman@gmail.com>2019-12-14 21:50:27 -0500
commit24a9257a0dadaed4a6e31a54b5936668f2d34e6f (patch)
tree6919ddbbad04c2a5c06a18c09b4f39bae13cdf32 /src/server/ChildProcessUtilities/daemon/session.ts
parent7edce1af91621b7724e4763a5afabb4ab86d183c (diff)
parent50940d2f1680aabbadcf9dd6e5455b7c7517115a (diff)
Merge branch 'master' of https://github.com/browngraphicslab/Dash-Web
Diffstat (limited to 'src/server/ChildProcessUtilities/daemon/session.ts')
-rw-r--r--src/server/ChildProcessUtilities/daemon/session.ts190
1 files changed, 0 insertions, 190 deletions
diff --git a/src/server/ChildProcessUtilities/daemon/session.ts b/src/server/ChildProcessUtilities/daemon/session.ts
deleted file mode 100644
index fb2b3551e..000000000
--- a/src/server/ChildProcessUtilities/daemon/session.ts
+++ /dev/null
@@ -1,190 +0,0 @@
-import * as request from "request-promise";
-import { log_execution, pathFromRoot } from "../../ActionUtilities";
-import { red, yellow, cyan, green, Color } from "colors";
-import * as nodemailer from "nodemailer";
-import { MailOptions } from "nodemailer/lib/json-transport";
-import { writeFileSync, existsSync, mkdirSync } from "fs";
-import { resolve } from 'path';
-import { ChildProcess, exec, execSync } from "child_process";
-import { createInterface } from "readline";
-const killport = require("kill-port");
-
-process.on('SIGINT', endPrevious);
-const identifier = yellow("__session_manager__:");
-
-let manualRestartActive = false;
-createInterface(process.stdin, process.stdout).on('line', async line => {
- const prompt = line.trim().toLowerCase();
- switch (prompt) {
- case "restart":
- manualRestartActive = true;
- identifiedLog(cyan("Initializing manual restart..."));
- await endPrevious();
- break;
- case "exit":
- identifiedLog(cyan("Initializing session end"));
- await endPrevious();
- identifiedLog("Cleanup complete. Exiting session...\n");
- execSync(killAllCommand());
- break;
- default:
- identifiedLog(red("commands: { exit, restart }"));
- return;
- }
-});
-
-const logPath = resolve(__dirname, "./logs");
-const crashPath = resolve(logPath, "./crashes");
-if (!existsSync(logPath)) {
- mkdirSync(logPath);
-}
-if (!existsSync(crashPath)) {
- mkdirSync(crashPath);
-}
-
-const crashLogPath = resolve(crashPath, `./session_crashes_${new Date().toISOString()}.log`);
-function addLogEntry(message: string, color: Color) {
- const formatted = color(`${message} ${timestamp()}.`);
- identifiedLog(formatted);
- // appendFileSync(crashLogPath, `${formatted}\n`);
-}
-
-function identifiedLog(message?: any, ...optionalParams: any[]) {
- console.log(identifier, message, ...optionalParams);
-}
-
-if (!["win32", "darwin"].includes(process.platform)) {
- identifiedLog(red("Invalid operating system: this script is supported only on Mac and Windows."));
- process.exit(1);
-}
-
-const latency = 10;
-const ports = [1050, 4321];
-const onWindows = process.platform === "win32";
-const LOCATION = "http://localhost";
-const heartbeat = `${LOCATION}:1050/serverHeartbeat`;
-const recipient = "samuel_wilkins@brown.edu";
-const { pid } = process;
-let restarting = false;
-let count = 0;
-
-function startServerCommand() {
- if (onWindows) {
- return '"C:\\Program Files\\Git\\git-bash.exe" -c "npm run start-release"';
- }
- return `osascript -e 'tell app "Terminal"\ndo script "cd ${pathFromRoot()} && npm run start-release"\nend tell'`;
-}
-
-function killAllCommand() {
- if (onWindows) {
- return "taskkill /f /im node.exe";
- }
- return "killall -9 node";
-}
-
-identifiedLog("Initializing session...");
-
-writeLocalPidLog("session_manager", pid);
-
-function writeLocalPidLog(filename: string, contents: any) {
- const path = `./logs/current_${filename}_pid.log`;
- identifiedLog(cyan(`${contents} written to ${path}`));
- writeFileSync(resolve(__dirname, path), `${contents}\n`);
-}
-
-function timestamp() {
- return `@ ${new Date().toISOString()}`;
-}
-
-async function endPrevious() {
- identifiedLog(yellow("Cleaning up previous connections..."));
- current_backup?.kill("SIGTERM");
- await Promise.all(ports.map(port => {
- const task = killport(port, 'tcp');
- return task.catch((error: any) => identifiedLog(red(error)));
- }));
- identifiedLog(yellow("Done. Any failures will be printed in red immediately above."));
-}
-
-let current_backup: ChildProcess | undefined = undefined;
-
-async function checkHeartbeat() {
- let error: any;
- try {
- count && !restarting && process.stdout.write(`${identifier} 👂 `);
- await request.get(heartbeat);
- count && !restarting && console.log('⇠ 💚');
- if (restarting || manualRestartActive) {
- addLogEntry(count++ ? "Backup server successfully restarted" : "Server successfully started", green);
- restarting = false;
- }
- } catch (e) {
- count && !restarting && console.log("⇠ 💔");
- error = e;
- } finally {
- if (error) {
- if (!restarting || manualRestartActive) {
- restarting = true;
- if (count && !manualRestartActive) {
- console.log();
- addLogEntry("Detected a server crash", red);
- identifiedLog(red(error.message));
- await endPrevious();
- await log_execution({
- startMessage: identifier + " Sending crash notification email",
- endMessage: ({ error, result }) => {
- const success = error === null && result === true;
- return identifier + ` ${(success ? `Notification successfully sent to` : `Failed to notify`)} ${recipient} ${timestamp()}`;
- },
- action: async () => notify(error || "Hmm, no error to report..."),
- color: cyan
- });
- identifiedLog(green("Initiating server restart..."));
- }
- manualRestartActive = false;
- current_backup = exec(startServerCommand(), err => identifiedLog(err?.message || count ? "Previous server process exited." : "Spawned initial server."));
- writeLocalPidLog("server", `${(current_backup?.pid ?? -2) + 1} created ${timestamp()}`);
- }
- }
- setTimeout(checkHeartbeat, 1000 * latency);
- }
-}
-
-async function startListening() {
- identifiedLog(yellow(`After initialization, will poll server heartbeat repeatedly...\n`));
- if (!LOCATION) {
- identifiedLog(red("No location specified for session manager. Please include as a command line environment variable or in a .env file."));
- process.exit(0);
- }
- await checkHeartbeat();
-}
-
-function emailText(error: any) {
- return [
- `Hey ${recipient.split("@")[0]},`,
- "You, as a Dash Administrator, are being notified of a server crash event. Here's what we know:",
- `Location: ${LOCATION}\nError: ${error}`,
- "The server should already be restarting itself, but if you're concerned, use the Remote Desktop Connection to monitor progress."
- ].join("\n\n");
-}
-
-async function notify(error: any) {
- const smtpTransport = nodemailer.createTransport({
- service: 'Gmail',
- auth: {
- user: 'brownptcdash@gmail.com',
- pass: 'browngfx1'
- }
- });
- const mailOptions = {
- to: recipient,
- from: 'brownptcdash@gmail.com',
- subject: 'Dash Server Crash',
- text: emailText(error)
- } as MailOptions;
- return new Promise<boolean>(resolve => {
- smtpTransport.sendMail(mailOptions, (dispatchError: Error | null) => resolve(dispatchError === null));
- });
-}
-
-startListening(); \ No newline at end of file