diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/server/Session/session.ts | 42 | ||||
-rw-r--r-- | src/server/index.ts | 5 |
2 files changed, 28 insertions, 19 deletions
diff --git a/src/server/Session/session.ts b/src/server/Session/session.ts index 2ff4ef0d2..049a37b04 100644 --- a/src/server/Session/session.ts +++ b/src/server/Session/session.ts @@ -30,7 +30,7 @@ export namespace Session { * Validates and reads the configuration file, accordingly builds a child process factory * and spawns off an initial process that will respawn as predecessors die. */ - export async function initializeMaster() { + export async function initializeMaster(): Promise<Repl> { let activeWorker: Worker; // read in configuration .json file only once, in the master thread @@ -43,10 +43,9 @@ export namespace Session { heartbeat, showServerOutput, pollingIntervalSeconds - } = function loadConfiguration() { + } = function loadConfiguration(): any { try { - const raw = readFileSync('./session.config.json', 'utf8'); - const configuration = JSON.parse(raw); + const configuration = JSON.parse(readFileSync('./session.config.json', 'utf8')); const options = { throwError: true, allowUnknownAttributes: false @@ -72,17 +71,21 @@ export namespace Session { } }(); - // this sends a random guid to the configuration's recipients, allowing them alone + // this sends a pseudorandomly generated guid to the configuration's recipients, allowing them alone // to kill the server via the /kill/:password route const key = Utils.GenerateGuid(); const timestamp = new Date().toUTCString(); const content = `The key for this session (started @ ${timestamp}) is ${key}.\n\n${signature}`; - await Email.dispatchAll(recipients, "Server Termination Key", content); - - console.log(masterIdentifier, "distributed session key to recipients"); + const results = await Email.dispatchAll(recipients, "Server Termination Key", content); + if (results.some(success => !success)) { + console.log(masterIdentifier, red("distribution of session key failed")); + } else { + console.log(masterIdentifier, green("distributed session key to recipients")); + } // handle exceptions in the master thread - there shouldn't be many of these - // the IPC (inter process communication) channel closed exception can't seem to be caught in a try catch, and is inconsequential, so it is ignored + // the IPC (inter process communication) channel closed exception can't seem + // to be caught in a try catch, and is inconsequential, so it is ignored process.on("uncaughtException", ({ message, stack }) => { if (message !== "Channel closed") { console.log(masterIdentifier, red(message)); @@ -96,7 +99,7 @@ export namespace Session { setupMaster({ silent: !showServerOutput }); // attempts to kills the active worker ungracefully - const tryKillActiveWorker = () => { + const tryKillActiveWorker = (): boolean => { if (activeWorker && !activeWorker.isDead()) { activeWorker.process.kill(); return true; @@ -104,8 +107,9 @@ export namespace Session { return false; }; - // kills the current active worker and proceeds to spawn a new worker, feeding in configuration information as environment variables - const spawn = () => { + // kills the current active worker and proceeds to spawn a new worker, + // feeding in configuration information as environment variables + const spawn = (): void => { tryKillActiveWorker(); activeWorker = fork({ heartbeat, @@ -150,10 +154,9 @@ export namespace Session { }); // builds the repl that allows the following commands to be typed into stdin of the master thread - const { registerCommand } = new Repl({ 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", [], () => { + const repl = new Repl({ identifier: masterIdentifier }); + repl.registerCommand("exit", [], () => execSync(onWindows ? "taskkill /f /im node.exe" : "killall -9 node")); + repl.registerCommand("restart", [], () => { // indicate to the worker that we are 'expecting' this restart activeWorker.send({ setListening: false }); tryKillActiveWorker(); @@ -161,6 +164,9 @@ export namespace Session { // finally, set things in motion by spawning off the first child (server) process spawn(); + + // returned to allow the caller to add custom commands + return repl; } /** @@ -180,7 +186,7 @@ export namespace Session { // called whenever the process has a reason to terminate, either through an uncaught exception // in the process (potentially inconsistent state) or the server cannot be reached - const activeExit = (error: Error) => { + const activeExit = (error: Error): void => { if (!listening) { return; } @@ -210,7 +216,7 @@ export namespace Session { // this monitors the health of the server by submitting a get request to whatever port / route specified // by the configuration every n seconds, where n is also given by the configuration. - const checkHeartbeat = async () => { + const checkHeartbeat = async (): Promise<void> => { await new Promise<void>(resolve => { setTimeout(async () => { try { diff --git a/src/server/index.ts b/src/server/index.ts index 0a5b4afae..287725537 100644 --- a/src/server/index.ts +++ b/src/server/index.ts @@ -25,9 +25,12 @@ import { Logger } from "./ProcessFactory"; import { yellow } from "colors"; import { Session } from "./Session/session"; import { isMaster } from "cluster"; +import { execSync } from "child_process"; if (isMaster) { - Session.initializeMaster(); + Session.initializeMaster().then(repl => { + repl.registerCommand("pull", [], () => execSync("git pull", { stdio: ["ignore", "inherit", "inherit"] })); + }); } else { Session.initializeWorker(launch); } |