diff options
author | Sam Wilkins <samwilkins333@gmail.com> | 2020-01-04 00:54:08 -0800 |
---|---|---|
committer | Sam Wilkins <samwilkins333@gmail.com> | 2020-01-04 00:54:08 -0800 |
commit | 9a3df8031b55a16ad55cef6975ff8bf4f681f14e (patch) | |
tree | de231fcb6ba4b591fd08cffadc798ea36312bcc0 /src | |
parent | b31d54b285236dc92f7d287af6a441878f429a34 (diff) |
config now not read by both parents and children, env used to pass from master to worker
Diffstat (limited to 'src')
-rw-r--r-- | src/server/Session/session.ts | 114 | ||||
-rw-r--r-- | src/server/index.ts | 6 |
2 files changed, 62 insertions, 58 deletions
diff --git a/src/server/Session/session.ts b/src/server/Session/session.ts index 6d8ce53c0..1ff4ce4de 100644 --- a/src/server/Session/session.ts +++ b/src/server/Session/session.ts @@ -15,7 +15,6 @@ const onWindows = process.platform === "win32"; export namespace Session { - const { masterIdentifier, workerIdentifier, recipients, signature, heartbeat, silentChildren } = loadConfiguration(); export let key: string; let activeWorker: Worker; let listening = false; @@ -47,16 +46,8 @@ export namespace Session { } } - 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(recipients.map((recipient: string) => Email.dispatch(recipient, "Server Termination Key", content))); + export async function email(recipients: string[], subject: string, content: string) { + return Promise.all(recipients.map((recipient: string) => Email.dispatch(recipient, subject, content))); } function tryKillActiveWorker() { @@ -67,70 +58,85 @@ export namespace Session { 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(recipients.map((recipient: string) => Email.dispatch(recipient, "Dash Web Server Crash", crashReport(error)))); + process.send?.({ + action: { + message: "notify_crash", + args: { 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.send?.({ lifecycle: red(`Crash event detected @ ${new Date().toUTCString()}`) }); + process.send?.({ lifecycle: 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)}`); + const { + masterIdentifier, + workerIdentifier, + recipients, + signature, + heartbeat, + silentChildren + } = loadConfiguration(); + await (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 email(recipients, "Server Termination Key", content); + })(); + console.log(masterIdentifier, "distributed session key to recipients"); + process.on("uncaughtException", ({ message, stack }) => { + if (message !== "Channel closed") { + console.log(masterIdentifier, red(message)); + if (stack) { + console.log(masterIdentifier, `\n${red(stack)}`); } } }); setupMaster({ silent: silentChildren }); const spawn = () => { tryKillActiveWorker(); - activeWorker = fork(); - activeWorker.on("message", messageHandler); + activeWorker = fork({ heartbeat, session_key: key }); + console.log(masterIdentifier, `spawned new server worker with process id ${activeWorker.process.pid}`); + activeWorker.on("message", ({ lifecycle, action }) => { + if (action) { + const { message, args } = action; + console.log(`${workerIdentifier} action requested (${cyan(message)})`); + switch (message) { + case "kill": + console.log(masterIdentifier, red("An authorized user has ended the server session from the /kill route")); + tryKillActiveWorker(); + process.exit(0); + case "notify_crash": + const { error: { name, message, stack } } = args; + email(recipients, "Dash Web Server Crash", [ + "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")); + } + } else if (lifecycle) { + console.log(`${workerIdentifier} lifecycle phase (${lifecycle})`); + } + }); }; 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)); + console.log(masterIdentifier, cyan(prompt)); spawn(); }); const { registerCommand } = new Repl({ identifier: masterIdentifier }); @@ -141,15 +147,15 @@ export namespace Session { tryKillActiveWorker(); }); } else { - logLifecycleEvent(green("initializing...")); + process.send?.({ lifecycle: green("initializing...") }); process.on('uncaughtException', activeExit); const checkHeartbeat = async () => { await new Promise<void>(resolve => { setTimeout(async () => { try { - await get(heartbeat); + await get(process.env.heartbeat!); if (!listening) { - logLifecycleEvent(green("listening...")); + process.send?.({ lifecycle: green("listening...") }); } listening = true; resolve(); diff --git a/src/server/index.ts b/src/server/index.ts index 88bab7dea..381496c20 100644 --- a/src/server/index.ts +++ b/src/server/index.ts @@ -24,7 +24,6 @@ import GooglePhotosManager from "./ApiManagers/GooglePhotosManager"; import { Logger } from "./ProcessFactory"; import { yellow } from "colors"; import { Session } from "./Session/session"; -import { Utils } from "../Utils"; export const publicDirectory = path.resolve(__dirname, "public"); export const filesDirectory = path.resolve(publicDirectory, "files"); @@ -35,7 +34,6 @@ export const filesDirectory = path.resolve(publicDirectory, "files"); * before clients can access the server should be run or awaited here. */ async function preliminaryFunctions() { - await Session.distributeKey(); await Logger.initialize(); await GoogleCredentialsLoader.loadCredentials(); GoogleApiServerUtils.processProjectCredentials(); @@ -92,8 +90,8 @@ function routeSetter({ isRelease, addSupervisedRoute, logRegistrationOutcome }: method: Method.GET, subscription: new RouteSubscriber("kill").add("password"), secureHandler: ({ req, res }) => { - if (req.params.password === Session.key) { - process.send!({ action: yellow("kill") }); + if (req.params.password === process.env.session_key) { + process.send!({ action: { message: "kill" } }); res.send("Server successfully killed."); } else { res.redirect("/home"); |