From ae3603e26adb635380d530b84cb9d6f1284066ef Mon Sep 17 00:00:00 2001 From: Sam Wilkins Date: Wed, 11 Dec 2019 13:54:28 -0500 Subject: process factory refactor --- src/server/ChildProcessUtilities/ProcessFactory.ts | 67 ++++++++++ .../daemon/persistence_daemon.ts | 137 +++++++++++++++++++++ 2 files changed, 204 insertions(+) create mode 100644 src/server/ChildProcessUtilities/ProcessFactory.ts create mode 100644 src/server/ChildProcessUtilities/daemon/persistence_daemon.ts (limited to 'src/server/ChildProcessUtilities') diff --git a/src/server/ChildProcessUtilities/ProcessFactory.ts b/src/server/ChildProcessUtilities/ProcessFactory.ts new file mode 100644 index 000000000..745b1479a --- /dev/null +++ b/src/server/ChildProcessUtilities/ProcessFactory.ts @@ -0,0 +1,67 @@ +import { existsSync, mkdirSync } from "fs"; +import { pathFromRoot, log_execution, fileDescriptorFromStream } from '../ActionUtilities'; +import { red, green } from "colors"; +import rimraf = require("rimraf"); +import { ChildProcess, spawn, StdioOptions } from "child_process"; +import { Stream } from "stream"; +import { resolve } from "path"; + +export namespace ProcessFactory { + + export type Sink = "pipe" | "ipc" | "ignore" | "inherit" | Stream | number | null | undefined; + + export async function createWorker(command: string, args?: readonly string[], stdio?: StdioOptions | "logfile", detached = true): Promise { + if (stdio === "logfile") { + const log_fd = await Logger.create(command, args); + stdio = ["ignore", log_fd, log_fd]; + } + const child = spawn(command, args, { detached, stdio }); + child.unref(); + return child; + } + + export namespace NamedAgents { + + export async function persistenceDaemon() { + await log_execution({ + startMessage: "\ninitializing persistence daemon", + endMessage: ({ result, error }) => { + const success = error === null && result !== undefined; + if (!success) { + console.log(red("failed to initialize the persistance daemon")); + console.log(error); + process.exit(0); + } + return "failsafe daemon process successfully spawned"; + }, + action: () => createWorker('npx', ['ts-node', resolve(__dirname, "./daemon/persistence_daemon.ts")], ["ignore", "inherit", "inherit"]), + color: green + }); + console.log(); + } + } + +} + +export namespace Logger { + + const logPath = pathFromRoot("./logs"); + + export async function initialize() { + if (existsSync(logPath)) { + if (!process.env.SPAWNED) { + await new Promise(resolve => rimraf(logPath, resolve)); + } + } + mkdirSync(logPath); + } + + export async function create(command: string, args?: readonly string[]): Promise { + return fileDescriptorFromStream(generate_log_path(command, args)); + } + + function generate_log_path(command: string, args?: readonly string[]) { + return pathFromRoot(`./logs/${command}-${args?.length}-${new Date().toUTCString()}.log`); + } + +} \ No newline at end of file diff --git a/src/server/ChildProcessUtilities/daemon/persistence_daemon.ts b/src/server/ChildProcessUtilities/daemon/persistence_daemon.ts new file mode 100644 index 000000000..888cf38b8 --- /dev/null +++ b/src/server/ChildProcessUtilities/daemon/persistence_daemon.ts @@ -0,0 +1,137 @@ +import * as request from "request-promise"; +import { log_execution } from "../../ActionUtilities"; +import { red, yellow, cyan, green, Color } from "colors"; +import * as nodemailer from "nodemailer"; +import { MailOptions } from "nodemailer/lib/json-transport"; +import { writeFileSync, appendFileSync, existsSync, mkdirSync } from "fs"; +import { resolve } from 'path'; +import { ChildProcess } from "child_process"; +import { ProcessFactory } from "../ProcessFactory"; + +const identifier = yellow("__daemon__:"); + +process.on('SIGINT', () => current_backup?.kill("SIGTERM")); + +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_${timestamp()}.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); +} + +const LOCATION = "http://localhost"; +const recipient = "samuel_wilkins@brown.edu"; +const frequency = 10; +const { pid } = process; +let restarting = false; + +identifiedLog("Initializing daemon..."); + +writeLocalPidLog("daemon", 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()}`; +} + +let current_backup: ChildProcess | undefined = undefined; + +async function listen() { + identifiedLog(yellow(`Beginning to poll server heartbeat every ${frequency} seconds...\n`)); + if (!LOCATION) { + identifiedLog(red("No location specified for persistence daemon. Please include as a command line environment variable or in a .env file.")); + process.exit(0); + } + const heartbeat = `${LOCATION}:1050/serverHeartbeat`; + // if this is on our remote server, the server must be run in release mode + // const suffix = LOCATION.includes("localhost") ? "" : "-release"; + setInterval(async () => { + let error: any; + try { + await request.get(heartbeat); + if (restarting) { + addLogEntry("Backup server successfully restarted", green); + } + restarting = false; + } catch (e) { + error = e; + } finally { + if (error) { + if (!restarting) { + restarting = true; + addLogEntry("Detected a server crash", red); + current_backup?.kill(); + 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 + }); + current_backup = await log_execution({ + startMessage: identifier + " Initiating server restart", + endMessage: ({ result, error }) => { + const success = error === null && result !== undefined; + return identifier + success ? " Child process spawned..." : ` An error occurred while attempting to restart the server:\n${error}`; + }, + action: () => ProcessFactory.createWorker('npm', ['run', 'start-spawn'], "inherit"), + color: green + }); + writeLocalPidLog("server", `${(current_backup?.pid ?? -2) + 1} created ${timestamp()}`); + } else { + identifiedLog(yellow(`Callback ignored because restarting already initiated ${timestamp()}`)); + } + } + } + }, 1000 * 10); +} + +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(resolve => { + smtpTransport.sendMail(mailOptions, (dispatchError: Error | null) => resolve(dispatchError === null)); + }); +} + +listen(); \ No newline at end of file -- cgit v1.2.3-70-g09d2 From e01499153fdd335493973dc79d80ccc4ae8df95c Mon Sep 17 00:00:00 2001 From: Sam Wilkins Date: Wed, 11 Dec 2019 19:43:37 -0500 Subject: first steps toward restructure of session daemon --- package.json | 2 +- .../daemon/persistence_daemon.ts | 137 --------------------- src/server/ChildProcessUtilities/daemon/session.ts | 137 +++++++++++++++++++++ src/server/index.ts | 14 --- 4 files changed, 138 insertions(+), 152 deletions(-) delete mode 100644 src/server/ChildProcessUtilities/daemon/persistence_daemon.ts create mode 100644 src/server/ChildProcessUtilities/daemon/session.ts (limited to 'src/server/ChildProcessUtilities') diff --git a/package.json b/package.json index 97563e137..77a521e27 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,7 @@ "main": "index.js", "scripts": { "start-release": "cross-env RELEASE=true NODE_OPTIONS=--max_old_space_size=4096 ts-node-dev -- src/server/index.ts", - "start-spawn": "cross-env SPAWNED=true NODE_OPTIONS=--max_old_space_size=4096 ts-node-dev -- src/server/index.ts", + "session": "npx ts-node ./src/server/ChildProcessUtilities/daemon/session.ts", "start": "cross-env NODE_OPTIONS=--max_old_space_size=4096 ts-node-dev -- src/server/index.ts", "debug": "cross-env NODE_OPTIONS=--max_old_space_size=8192 ts-node-dev --inspect -- src/server/index.ts", "build": "cross-env NODE_OPTIONS=--max_old_space_size=8192 webpack --env production", diff --git a/src/server/ChildProcessUtilities/daemon/persistence_daemon.ts b/src/server/ChildProcessUtilities/daemon/persistence_daemon.ts deleted file mode 100644 index 888cf38b8..000000000 --- a/src/server/ChildProcessUtilities/daemon/persistence_daemon.ts +++ /dev/null @@ -1,137 +0,0 @@ -import * as request from "request-promise"; -import { log_execution } from "../../ActionUtilities"; -import { red, yellow, cyan, green, Color } from "colors"; -import * as nodemailer from "nodemailer"; -import { MailOptions } from "nodemailer/lib/json-transport"; -import { writeFileSync, appendFileSync, existsSync, mkdirSync } from "fs"; -import { resolve } from 'path'; -import { ChildProcess } from "child_process"; -import { ProcessFactory } from "../ProcessFactory"; - -const identifier = yellow("__daemon__:"); - -process.on('SIGINT', () => current_backup?.kill("SIGTERM")); - -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_${timestamp()}.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); -} - -const LOCATION = "http://localhost"; -const recipient = "samuel_wilkins@brown.edu"; -const frequency = 10; -const { pid } = process; -let restarting = false; - -identifiedLog("Initializing daemon..."); - -writeLocalPidLog("daemon", 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()}`; -} - -let current_backup: ChildProcess | undefined = undefined; - -async function listen() { - identifiedLog(yellow(`Beginning to poll server heartbeat every ${frequency} seconds...\n`)); - if (!LOCATION) { - identifiedLog(red("No location specified for persistence daemon. Please include as a command line environment variable or in a .env file.")); - process.exit(0); - } - const heartbeat = `${LOCATION}:1050/serverHeartbeat`; - // if this is on our remote server, the server must be run in release mode - // const suffix = LOCATION.includes("localhost") ? "" : "-release"; - setInterval(async () => { - let error: any; - try { - await request.get(heartbeat); - if (restarting) { - addLogEntry("Backup server successfully restarted", green); - } - restarting = false; - } catch (e) { - error = e; - } finally { - if (error) { - if (!restarting) { - restarting = true; - addLogEntry("Detected a server crash", red); - current_backup?.kill(); - 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 - }); - current_backup = await log_execution({ - startMessage: identifier + " Initiating server restart", - endMessage: ({ result, error }) => { - const success = error === null && result !== undefined; - return identifier + success ? " Child process spawned..." : ` An error occurred while attempting to restart the server:\n${error}`; - }, - action: () => ProcessFactory.createWorker('npm', ['run', 'start-spawn'], "inherit"), - color: green - }); - writeLocalPidLog("server", `${(current_backup?.pid ?? -2) + 1} created ${timestamp()}`); - } else { - identifiedLog(yellow(`Callback ignored because restarting already initiated ${timestamp()}`)); - } - } - } - }, 1000 * 10); -} - -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(resolve => { - smtpTransport.sendMail(mailOptions, (dispatchError: Error | null) => resolve(dispatchError === null)); - }); -} - -listen(); \ No newline at end of file diff --git a/src/server/ChildProcessUtilities/daemon/session.ts b/src/server/ChildProcessUtilities/daemon/session.ts new file mode 100644 index 000000000..c41657cc9 --- /dev/null +++ b/src/server/ChildProcessUtilities/daemon/session.ts @@ -0,0 +1,137 @@ +import * as request from "request-promise"; +import { log_execution } from "../../ActionUtilities"; +import { red, yellow, cyan, green, Color } from "colors"; +import * as nodemailer from "nodemailer"; +import { MailOptions } from "nodemailer/lib/json-transport"; +import { writeFileSync, appendFileSync, existsSync, mkdirSync } from "fs"; +import { resolve } from 'path'; +import { ChildProcess } from "child_process"; +import { ProcessFactory } from "../ProcessFactory"; + +const identifier = yellow("__daemon__:"); + +process.on('SIGINT', () => current_backup?.kill("SIGTERM")); + +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_${timestamp()}.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); +} + +const LOCATION = "http://localhost"; +const recipient = "samuel_wilkins@brown.edu"; +const frequency = 10; +const { pid } = process; +let restarting = false; + +identifiedLog("Initializing daemon..."); + +writeLocalPidLog("daemon", 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()}`; +} + +let current_backup: ChildProcess | undefined = undefined; + +async function listen() { + identifiedLog(yellow(`Beginning to poll server heartbeat every ${frequency} seconds...\n`)); + if (!LOCATION) { + identifiedLog(red("No location specified for persistence daemon. Please include as a command line environment variable or in a .env file.")); + process.exit(0); + } + const heartbeat = `${LOCATION}:1050/serverHeartbeat`; + // if this is on our remote server, the server must be run in release mode + // const suffix = LOCATION.includes("localhost") ? "" : "-release"; + setInterval(async () => { + let error: any; + try { + await request.get(heartbeat); + if (restarting) { + addLogEntry("Backup server successfully restarted", green); + } + restarting = false; + } catch (e) { + error = e; + } finally { + if (error) { + if (!restarting) { + restarting = true; + addLogEntry("Detected a server crash", red); + current_backup?.kill(); + 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 + }); + current_backup = await log_execution({ + startMessage: identifier + " Initiating server restart", + endMessage: ({ result, error }) => { + const success = error === null && result !== undefined; + return identifier + success ? " Child process spawned..." : ` An error occurred while attempting to restart the server:\n${error}`; + }, + action: () => ProcessFactory.createWorker('npm', ['run', 'start'], "inherit"), + color: green + }); + writeLocalPidLog("server", `${(current_backup?.pid ?? -2) + 1} created ${timestamp()}`); + } else { + identifiedLog(yellow(`Callback ignored because restarting already initiated ${timestamp()}`)); + } + } + } + }, 1000 * 10); +} + +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(resolve => { + smtpTransport.sendMail(mailOptions, (dispatchError: Error | null) => resolve(dispatchError === null)); + }); +} + +listen(); \ No newline at end of file diff --git a/src/server/index.ts b/src/server/index.ts index bebb9b365..bc481e579 100644 --- a/src/server/index.ts +++ b/src/server/index.ts @@ -121,20 +121,6 @@ function routeSetter({ isRelease, addSupervisedRoute, logRegistrationOutcome }: } }); - let daemonInitialized = false; - const { SPAWNED, RELEASE } = process.env; - addSupervisedRoute({ - method: Method.GET, - subscription: "/persist", - onValidation: ({ res }) => { - if (RELEASE && !SPAWNED && !daemonInitialized) { - daemonInitialized = true; - ProcessFactory.NamedAgents.persistenceDaemon(); - } - res.redirect("/home"); - } - }); - logRegistrationOutcome(); // initialize the web socket (bidirectional communication: if a user changes -- cgit v1.2.3-70-g09d2 From b55ce381c905e87421bf011f5cd0cf423f858bb8 Mon Sep 17 00:00:00 2001 From: Sam Wilkins <35748010+samwilkins333@users.noreply.github.com> Date: Thu, 12 Dec 2019 10:51:47 -0500 Subject: session --- src/server/ChildProcessUtilities/daemon/session.ts | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) (limited to 'src/server/ChildProcessUtilities') diff --git a/src/server/ChildProcessUtilities/daemon/session.ts b/src/server/ChildProcessUtilities/daemon/session.ts index c41657cc9..9e082e665 100644 --- a/src/server/ChildProcessUtilities/daemon/session.ts +++ b/src/server/ChildProcessUtilities/daemon/session.ts @@ -5,7 +5,7 @@ import * as nodemailer from "nodemailer"; import { MailOptions } from "nodemailer/lib/json-transport"; import { writeFileSync, appendFileSync, existsSync, mkdirSync } from "fs"; import { resolve } from 'path'; -import { ChildProcess } from "child_process"; +import { ChildProcess, exec } from "child_process"; import { ProcessFactory } from "../ProcessFactory"; const identifier = yellow("__daemon__:"); @@ -21,11 +21,11 @@ if (!existsSync(crashPath)) { mkdirSync(crashPath); } -const crashLogPath = resolve(crashPath, `./session_crashes_${timestamp()}.log`); +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`); + // appendFileSync(crashLogPath, `${formatted}\n`); } function identifiedLog(message?: any, ...optionalParams: any[]) { @@ -88,13 +88,24 @@ async function listen() { action: async () => notify(error || "Hmm, no error to report..."), color: cyan }); - current_backup = await log_execution({ + await log_execution({ startMessage: identifier + " Initiating server restart", endMessage: ({ result, error }) => { const success = error === null && result !== undefined; return identifier + success ? " Child process spawned..." : ` An error occurred while attempting to restart the server:\n${error}`; }, - action: () => ProcessFactory.createWorker('npm', ['run', 'start'], "inherit"), + action: async () => { + return new Promise(resolve => { + exec('"C:\\Program Files\\Git\\git-bash.exe" -c "npm run start-release"', err => { + if (err) { + identifiedLog(err.message); + return; + } + resolve(); + }); + + }); + }, color: green }); writeLocalPidLog("server", `${(current_backup?.pid ?? -2) + 1} created ${timestamp()}`); -- cgit v1.2.3-70-g09d2 From 85e7ca251beefa0b5417c8e6e6d28f9aaa5d886c Mon Sep 17 00:00:00 2001 From: Sam Wilkins Date: Thu, 12 Dec 2019 11:05:36 -0500 Subject: killport --- package.json | 3 ++- src/server/ChildProcessUtilities/daemon/session.ts | 25 ++++------------------ src/typings/index.d.ts | 1 + 3 files changed, 7 insertions(+), 22 deletions(-) (limited to 'src/server/ChildProcessUtilities') diff --git a/package.json b/package.json index 77a521e27..c58f542fc 100644 --- a/package.json +++ b/package.json @@ -161,6 +161,7 @@ "js-datepicker": "^4.6.6", "jsonwebtoken": "^8.5.0", "jsx-to-string": "^1.4.0", + "kill-port": "^1.6.0", "lodash": "^4.17.15", "mobile-detect": "^1.4.3", "mobx": "^5.15.0", @@ -231,4 +232,4 @@ "xoauth2": "^1.2.0", "youtube": "^0.1.0" } -} \ No newline at end of file +} diff --git a/src/server/ChildProcessUtilities/daemon/session.ts b/src/server/ChildProcessUtilities/daemon/session.ts index 9e082e665..41eb6976e 100644 --- a/src/server/ChildProcessUtilities/daemon/session.ts +++ b/src/server/ChildProcessUtilities/daemon/session.ts @@ -6,7 +6,7 @@ import { MailOptions } from "nodemailer/lib/json-transport"; import { writeFileSync, appendFileSync, existsSync, mkdirSync } from "fs"; import { resolve } from 'path'; import { ChildProcess, exec } from "child_process"; -import { ProcessFactory } from "../ProcessFactory"; +import * as killport from "kill-port"; const identifier = yellow("__daemon__:"); @@ -79,6 +79,7 @@ async function listen() { restarting = true; addLogEntry("Detected a server crash", red); current_backup?.kill(); + await killport(1050, 'tcp'); await log_execution({ startMessage: identifier + " Sending crash notification email", endMessage: ({ error, result }) => { @@ -88,26 +89,8 @@ async function listen() { action: async () => notify(error || "Hmm, no error to report..."), color: cyan }); - await log_execution({ - startMessage: identifier + " Initiating server restart", - endMessage: ({ result, error }) => { - const success = error === null && result !== undefined; - return identifier + success ? " Child process spawned..." : ` An error occurred while attempting to restart the server:\n${error}`; - }, - action: async () => { - return new Promise(resolve => { - exec('"C:\\Program Files\\Git\\git-bash.exe" -c "npm run start-release"', err => { - if (err) { - identifiedLog(err.message); - return; - } - resolve(); - }); - - }); - }, - color: green - }); + identifiedLog(green("Initiating server restart...")); + current_backup = exec('"C:\\Program Files\\Git\\git-bash.exe" -c "npm run start-release"', err => identifiedLog(err?.message || "Previous server process exited.")); writeLocalPidLog("server", `${(current_backup?.pid ?? -2) + 1} created ${timestamp()}`); } else { identifiedLog(yellow(`Callback ignored because restarting already initiated ${timestamp()}`)); diff --git a/src/typings/index.d.ts b/src/typings/index.d.ts index 9e8ace962..674278126 100644 --- a/src/typings/index.d.ts +++ b/src/typings/index.d.ts @@ -2,6 +2,7 @@ declare module 'googlephotos'; declare module 'react-image-lightbox-with-rotate'; +declare module 'kill-port'; declare module '@react-pdf/renderer' { import * as React from 'react'; -- cgit v1.2.3-70-g09d2 From 2a3a9c641da29e92ddd321f6c1f6c62ffe3c040d Mon Sep 17 00:00:00 2001 From: Sam Wilkins <35748010+samwilkins333@users.noreply.github.com> Date: Thu, 12 Dec 2019 11:40:56 -0500 Subject: functional session --- src/server/ChildProcessUtilities/daemon/session.ts | 39 ++++++++++++---------- 1 file changed, 22 insertions(+), 17 deletions(-) (limited to 'src/server/ChildProcessUtilities') diff --git a/src/server/ChildProcessUtilities/daemon/session.ts b/src/server/ChildProcessUtilities/daemon/session.ts index 41eb6976e..d6c8ddb64 100644 --- a/src/server/ChildProcessUtilities/daemon/session.ts +++ b/src/server/ChildProcessUtilities/daemon/session.ts @@ -6,7 +6,7 @@ import { MailOptions } from "nodemailer/lib/json-transport"; import { writeFileSync, appendFileSync, existsSync, mkdirSync } from "fs"; import { resolve } from 'path'; import { ChildProcess, exec } from "child_process"; -import * as killport from "kill-port"; +const killport = require("kill-port"); const identifier = yellow("__daemon__:"); @@ -37,6 +37,7 @@ const recipient = "samuel_wilkins@brown.edu"; const frequency = 10; const { pid } = process; let restarting = false; +let count = 0; identifiedLog("Initializing daemon..."); @@ -68,7 +69,8 @@ async function listen() { try { await request.get(heartbeat); if (restarting) { - addLogEntry("Backup server successfully restarted", green); + addLogEntry("Backup server successfully " + count ? "restarted" : "started", green); + count++; } restarting = false; } catch (e) { @@ -77,23 +79,26 @@ async function listen() { if (error) { if (!restarting) { restarting = true; - addLogEntry("Detected a server crash", red); - current_backup?.kill(); - await killport(1050, 'tcp'); - 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...")); + if (count) { + addLogEntry("Detected a server crash", red); + current_backup?.kill("SIGTERM"); + identifiedLog(yellow("Cleaning up previous connections...")); + await killport(1050, 'tcp').catch((error: any) => identifiedLog(red(error))); + await killport(4321, 'tcp').catch((error: any) => identifiedLog(red(error))); + identifiedLog(yellow("Connections cleared.")); + 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...")); + } current_backup = exec('"C:\\Program Files\\Git\\git-bash.exe" -c "npm run start-release"', err => identifiedLog(err?.message || "Previous server process exited.")); writeLocalPidLog("server", `${(current_backup?.pid ?? -2) + 1} created ${timestamp()}`); - } else { - identifiedLog(yellow(`Callback ignored because restarting already initiated ${timestamp()}`)); } } } -- cgit v1.2.3-70-g09d2 From d8cac4f0c1d425ef3fd263ae8d488ee62232f1d3 Mon Sep 17 00:00:00 2001 From: Sam Wilkins Date: Thu, 12 Dec 2019 15:00:42 -0500 Subject: platform dependent --- src/server/ActionUtilities.ts | 5 ++++- src/server/ChildProcessUtilities/daemon/session.ts | 23 +++++++++++++++++----- 2 files changed, 22 insertions(+), 6 deletions(-) (limited to 'src/server/ChildProcessUtilities') diff --git a/src/server/ActionUtilities.ts b/src/server/ActionUtilities.ts index 2e62443c6..053576a92 100644 --- a/src/server/ActionUtilities.ts +++ b/src/server/ActionUtilities.ts @@ -6,7 +6,10 @@ import * as rimraf from "rimraf"; import { yellow, Color } from 'colors'; const projectRoot = path.resolve(__dirname, "../../"); -export function pathFromRoot(relative: string) { +export function pathFromRoot(relative?: string) { + if (!relative) { + return projectRoot; + } return path.resolve(projectRoot, relative); } diff --git a/src/server/ChildProcessUtilities/daemon/session.ts b/src/server/ChildProcessUtilities/daemon/session.ts index 41eb6976e..1a3ce61af 100644 --- a/src/server/ChildProcessUtilities/daemon/session.ts +++ b/src/server/ChildProcessUtilities/daemon/session.ts @@ -1,12 +1,12 @@ import * as request from "request-promise"; -import { log_execution } from "../../ActionUtilities"; +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, appendFileSync, existsSync, mkdirSync } from "fs"; +import { writeFileSync, existsSync, mkdirSync } from "fs"; import { resolve } from 'path'; import { ChildProcess, exec } from "child_process"; -import * as killport from "kill-port"; +// import * as killport from "kill-port"; const identifier = yellow("__daemon__:"); @@ -32,12 +32,25 @@ 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 onWindows = process.platform === "win32"; const LOCATION = "http://localhost"; const recipient = "samuel_wilkins@brown.edu"; const frequency = 10; const { pid } = process; let restarting = false; +function startCommand() { + 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'`; +} + identifiedLog("Initializing daemon..."); writeLocalPidLog("daemon", pid); @@ -79,7 +92,7 @@ async function listen() { restarting = true; addLogEntry("Detected a server crash", red); current_backup?.kill(); - await killport(1050, 'tcp'); + // await killport(1050, 'tcp'); await log_execution({ startMessage: identifier + " Sending crash notification email", endMessage: ({ error, result }) => { @@ -90,7 +103,7 @@ async function listen() { color: cyan }); identifiedLog(green("Initiating server restart...")); - current_backup = exec('"C:\\Program Files\\Git\\git-bash.exe" -c "npm run start-release"', err => identifiedLog(err?.message || "Previous server process exited.")); + current_backup = exec(startCommand(), err => identifiedLog(err?.message || "Previous server process exited.")); writeLocalPidLog("server", `${(current_backup?.pid ?? -2) + 1} created ${timestamp()}`); } else { identifiedLog(yellow(`Callback ignored because restarting already initiated ${timestamp()}`)); -- cgit v1.2.3-70-g09d2 From 1050212f66f9a906e9f2847e6d6171f488ba2179 Mon Sep 17 00:00:00 2001 From: Sam Wilkins Date: Thu, 12 Dec 2019 16:09:20 -0500 Subject: small changes --- src/server/ChildProcessUtilities/daemon/session.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/server/ChildProcessUtilities') diff --git a/src/server/ChildProcessUtilities/daemon/session.ts b/src/server/ChildProcessUtilities/daemon/session.ts index 833e90581..d51240349 100644 --- a/src/server/ChildProcessUtilities/daemon/session.ts +++ b/src/server/ChildProcessUtilities/daemon/session.ts @@ -81,8 +81,7 @@ async function checkHeartbeat() { try { await request.get(heartbeat); if (restarting) { - addLogEntry(`Backup server successfully ${count ? "restarted" : "started"}`, green); - count++; + addLogEntry(count++ ? "Backup server successfully restarted" : "Server successfully started", green); } restarting = false; } catch (e) { @@ -98,7 +97,8 @@ async function checkHeartbeat() { identifiedLog(yellow("Cleaning up previous connections...")); await clear_ports(1050, 4321); - identifiedLog(yellow("Finished attempting to clear all ports. Any failures will be printed in red immediately above.")); + identifiedLog(yellow("Finished attempting to clear all ports.")); + identifiedLog(yellow("Any failures will be printed in red immediately above.")); await log_execution({ startMessage: identifier + " Sending crash notification email", -- cgit v1.2.3-70-g09d2 From 551eccb37f9dad21886a85f0e91571aa588ea505 Mon Sep 17 00:00:00 2001 From: Sam Wilkins Date: Thu, 12 Dec 2019 17:41:53 -0500 Subject: read write --- src/server/ChildProcessUtilities/daemon/session.ts | 51 +++++++++++++++------- 1 file changed, 35 insertions(+), 16 deletions(-) (limited to 'src/server/ChildProcessUtilities') diff --git a/src/server/ChildProcessUtilities/daemon/session.ts b/src/server/ChildProcessUtilities/daemon/session.ts index d51240349..3ae14e894 100644 --- a/src/server/ChildProcessUtilities/daemon/session.ts +++ b/src/server/ChildProcessUtilities/daemon/session.ts @@ -5,12 +5,33 @@ 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 } from "child_process"; +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__:"); -process.on('SIGINT', () => current_backup?.kill("SIGTERM")); +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...")); + endPrevious(); + break; + case "exit": + identifiedLog(cyan("Initializing session end")); + await endPrevious(); + identifiedLog("Cleanup complete. Exiting session..."); + execSync("killall -9 node"); + break; + default: + identifiedLog(red("commands: { exit, restart }")); + return; + } +}); const logPath = resolve(__dirname, "./logs"); const crashPath = resolve(logPath, "./crashes"); @@ -37,6 +58,7 @@ if (!["win32", "darwin"].includes(process.platform)) { process.exit(1); } +const ports = [1050, 4321]; const onWindows = process.platform === "win32"; const LOCATION = "http://localhost"; const heartbeat = `${LOCATION}:1050/serverHeartbeat`; @@ -67,11 +89,14 @@ function timestamp() { return `@ ${new Date().toISOString()}`; } -async function clear_ports(...targets: number[]) { - return Promise.all(targets.map(port => { +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; @@ -80,26 +105,20 @@ async function checkHeartbeat() { let error: any; try { await request.get(heartbeat); - if (restarting) { + if (restarting || manualRestartActive) { addLogEntry(count++ ? "Backup server successfully restarted" : "Server successfully started", green); + restarting = false; } - restarting = false; } catch (e) { error = e; } finally { if (error) { - if (!restarting) { + if (!restarting || manualRestartActive) { restarting = true; - if (count) { + if (count && !manualRestartActive) { console.log(); addLogEntry("Detected a server crash", red); - current_backup?.kill("SIGTERM"); - - identifiedLog(yellow("Cleaning up previous connections...")); - await clear_ports(1050, 4321); - identifiedLog(yellow("Finished attempting to clear all ports.")); - identifiedLog(yellow("Any failures will be printed in red immediately above.")); - + await endPrevious(); await log_execution({ startMessage: identifier + " Sending crash notification email", endMessage: ({ error, result }) => { @@ -109,9 +128,9 @@ async function checkHeartbeat() { 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()}`); } -- cgit v1.2.3-70-g09d2 From 5aaaf39260cf998008403fdb6f408f7c27469edc Mon Sep 17 00:00:00 2001 From: Sam Wilkins Date: Thu, 12 Dec 2019 17:44:59 -0500 Subject: kill all for windows --- src/server/ChildProcessUtilities/daemon/session.ts | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'src/server/ChildProcessUtilities') diff --git a/src/server/ChildProcessUtilities/daemon/session.ts b/src/server/ChildProcessUtilities/daemon/session.ts index 3ae14e894..4a62381f8 100644 --- a/src/server/ChildProcessUtilities/daemon/session.ts +++ b/src/server/ChildProcessUtilities/daemon/session.ts @@ -24,8 +24,8 @@ createInterface(process.stdin, process.stdout).on('line', async line => { case "exit": identifiedLog(cyan("Initializing session end")); await endPrevious(); - identifiedLog("Cleanup complete. Exiting session..."); - execSync("killall -9 node"); + identifiedLog("Cleanup complete. Exiting session...\n"); + execSync(killAllCommand()); break; default: identifiedLog(red("commands: { exit, restart }")); @@ -75,6 +75,13 @@ function startServerCommand() { 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); -- cgit v1.2.3-70-g09d2 From 634475c34cdc49672edebb722e469ed627d495c2 Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Thu, 12 Dec 2019 20:08:05 -0500 Subject: slight changes to session heartbeat --- src/server/ChildProcessUtilities/daemon/session.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'src/server/ChildProcessUtilities') diff --git a/src/server/ChildProcessUtilities/daemon/session.ts b/src/server/ChildProcessUtilities/daemon/session.ts index 4a62381f8..f3d9b42c3 100644 --- a/src/server/ChildProcessUtilities/daemon/session.ts +++ b/src/server/ChildProcessUtilities/daemon/session.ts @@ -111,12 +111,15 @@ let current_backup: ChildProcess | undefined = undefined; async function checkHeartbeat() { let error: any; try { + identifiedLog(green("request Heartbeat...")); await request.get(heartbeat); + identifiedLog(green("got Heartbeat...")); if (restarting || manualRestartActive) { addLogEntry(count++ ? "Backup server successfully restarted" : "Server successfully started", green); restarting = false; } } catch (e) { + identifiedLog(red("failed Heartbeat..." + e)); error = e; } finally { if (error) { @@ -142,6 +145,8 @@ async function checkHeartbeat() { writeLocalPidLog("server", `${(current_backup?.pid ?? -2) + 1} created ${timestamp()}`); } } + identifiedLog(green("restarting heartbeater")); + setTimeout(checkHeartbeat, 1000 * frequency); } } @@ -152,7 +157,6 @@ async function startListening() { process.exit(0); } await checkHeartbeat(); - setInterval(checkHeartbeat, 1000 * frequency); } function emailText(error: any) { -- cgit v1.2.3-70-g09d2 From 27a124671155f5178691707a4fff73aa071cd741 Mon Sep 17 00:00:00 2001 From: Sam Wilkins Date: Thu, 12 Dec 2019 20:44:30 -0500 Subject: small session changes --- src/server/ChildProcessUtilities/daemon/session.ts | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) (limited to 'src/server/ChildProcessUtilities') diff --git a/src/server/ChildProcessUtilities/daemon/session.ts b/src/server/ChildProcessUtilities/daemon/session.ts index f3d9b42c3..35c23b525 100644 --- a/src/server/ChildProcessUtilities/daemon/session.ts +++ b/src/server/ChildProcessUtilities/daemon/session.ts @@ -58,12 +58,12 @@ if (!["win32", "darwin"].includes(process.platform)) { 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 frequency = 10; const { pid } = process; let restarting = false; let count = 0; @@ -111,15 +111,18 @@ let current_backup: ChildProcess | undefined = undefined; async function checkHeartbeat() { let error: any; try { - identifiedLog(green("request Heartbeat...")); + count && identifiedLog(green("Requesting heartbeat")); await request.get(heartbeat); - identifiedLog(green("got Heartbeat...")); + count && identifiedLog(green("Received heartbeat")); if (restarting || manualRestartActive) { addLogEntry(count++ ? "Backup server successfully restarted" : "Server successfully started", green); restarting = false; } } catch (e) { - identifiedLog(red("failed Heartbeat..." + e)); + if (count) { + identifiedLog(red("Heartbeat failed...")); + identifiedLog(red(e.message)); + } error = e; } finally { if (error) { @@ -145,13 +148,12 @@ async function checkHeartbeat() { writeLocalPidLog("server", `${(current_backup?.pid ?? -2) + 1} created ${timestamp()}`); } } - identifiedLog(green("restarting heartbeater")); - setTimeout(checkHeartbeat, 1000 * frequency); + setTimeout(checkHeartbeat, 1000 * latency); } } async function startListening() { - identifiedLog(yellow(`After initialization, will poll server heartbeat every ${frequency} seconds...\n`)); + 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); -- cgit v1.2.3-70-g09d2 From 84f4cb0fcbf63ada120624526207ce3cefa68c3d Mon Sep 17 00:00:00 2001 From: Sam Wilkins Date: Thu, 12 Dec 2019 21:15:03 -0500 Subject: heartbeat --- src/server/ChildProcessUtilities/daemon/session.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/server/ChildProcessUtilities') diff --git a/src/server/ChildProcessUtilities/daemon/session.ts b/src/server/ChildProcessUtilities/daemon/session.ts index 35c23b525..5155305ce 100644 --- a/src/server/ChildProcessUtilities/daemon/session.ts +++ b/src/server/ChildProcessUtilities/daemon/session.ts @@ -111,9 +111,9 @@ let current_backup: ChildProcess | undefined = undefined; async function checkHeartbeat() { let error: any; try { - count && identifiedLog(green("Requesting heartbeat")); + count && !restarting && process.stdout.write(green(`${identifier} <`)); await request.get(heartbeat); - count && identifiedLog(green("Received heartbeat")); + count && !restarting && console.log(green("3")); if (restarting || manualRestartActive) { addLogEntry(count++ ? "Backup server successfully restarted" : "Server successfully started", green); restarting = false; -- cgit v1.2.3-70-g09d2 From 22f2f7dd970f70bd8151762e31613029fdbb2f29 Mon Sep 17 00:00:00 2001 From: Sam Wilkins Date: Thu, 12 Dec 2019 21:18:34 -0500 Subject: heartbeat --- src/server/ChildProcessUtilities/daemon/session.ts | 1 + 1 file changed, 1 insertion(+) (limited to 'src/server/ChildProcessUtilities') diff --git a/src/server/ChildProcessUtilities/daemon/session.ts b/src/server/ChildProcessUtilities/daemon/session.ts index 5155305ce..e2c72c1d5 100644 --- a/src/server/ChildProcessUtilities/daemon/session.ts +++ b/src/server/ChildProcessUtilities/daemon/session.ts @@ -120,6 +120,7 @@ async function checkHeartbeat() { } } catch (e) { if (count) { + console.log(); identifiedLog(red("Heartbeat failed...")); identifiedLog(red(e.message)); } -- cgit v1.2.3-70-g09d2 From c79923651eab568ec1be6eb542f937041c6e897c Mon Sep 17 00:00:00 2001 From: Sam Wilkins Date: Thu, 12 Dec 2019 22:03:39 -0500 Subject: heartbeat --- src/server/ChildProcessUtilities/daemon/session.ts | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) (limited to 'src/server/ChildProcessUtilities') diff --git a/src/server/ChildProcessUtilities/daemon/session.ts b/src/server/ChildProcessUtilities/daemon/session.ts index e2c72c1d5..8d2845cf3 100644 --- a/src/server/ChildProcessUtilities/daemon/session.ts +++ b/src/server/ChildProcessUtilities/daemon/session.ts @@ -111,19 +111,15 @@ let current_backup: ChildProcess | undefined = undefined; async function checkHeartbeat() { let error: any; try { - count && !restarting && process.stdout.write(green(`${identifier} <`)); + count && !restarting && process.stdout.write(`${identifier} 👂 `); await request.get(heartbeat); - count && !restarting && console.log(green("3")); + count && !restarting && console.log('⇠ 💚'); if (restarting || manualRestartActive) { addLogEntry(count++ ? "Backup server successfully restarted" : "Server successfully started", green); restarting = false; } } catch (e) { - if (count) { - console.log(); - identifiedLog(red("Heartbeat failed...")); - identifiedLog(red(e.message)); - } + count && !restarting && console.log("⇠ 💔"); error = e; } finally { if (error) { @@ -132,6 +128,7 @@ async function checkHeartbeat() { 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", -- cgit v1.2.3-70-g09d2 From a3a654ae509c03508916235664217731f5a91db2 Mon Sep 17 00:00:00 2001 From: Sam Wilkins <35748010+samwilkins333@users.noreply.github.com> Date: Fri, 13 Dec 2019 00:31:02 -0500 Subject: await end previous --- src/server/ChildProcessUtilities/daemon/session.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/server/ChildProcessUtilities') diff --git a/src/server/ChildProcessUtilities/daemon/session.ts b/src/server/ChildProcessUtilities/daemon/session.ts index 8d2845cf3..fb2b3551e 100644 --- a/src/server/ChildProcessUtilities/daemon/session.ts +++ b/src/server/ChildProcessUtilities/daemon/session.ts @@ -19,7 +19,7 @@ createInterface(process.stdin, process.stdout).on('line', async line => { case "restart": manualRestartActive = true; identifiedLog(cyan("Initializing manual restart...")); - endPrevious(); + await endPrevious(); break; case "exit": identifiedLog(cyan("Initializing session end")); -- cgit v1.2.3-70-g09d2