diff options
Diffstat (limited to 'src/server/session/utilities')
-rw-r--r-- | src/server/session/utilities/ipc.ts | 52 | ||||
-rw-r--r-- | src/server/session/utilities/session_config.ts | 129 | ||||
-rw-r--r-- | src/server/session/utilities/utilities.ts | 31 |
3 files changed, 212 insertions, 0 deletions
diff --git a/src/server/session/utilities/ipc.ts b/src/server/session/utilities/ipc.ts new file mode 100644 index 000000000..b20f3d337 --- /dev/null +++ b/src/server/session/utilities/ipc.ts @@ -0,0 +1,52 @@ +import { isMaster } from "cluster"; +import { Utils } from "../../../Utils"; + +export namespace IPC { + + export const suffix = isMaster ? Utils.GenerateGuid() : process.env.ipc_suffix; + const ipc_id = `ipc_id_${suffix}`; + const response_expected = `response_expected_${suffix}`; + const is_response = `is_response_${suffix}`; + + export async function dispatchMessage(target: NodeJS.EventEmitter & { send?: Function }, message: any, expectResponse = false): Promise<Error | undefined> { + if (!target.send) { + return new Error("Cannot dispatch when send is undefined."); + } + message[response_expected] = expectResponse; + if (expectResponse) { + return new Promise(resolve => { + const messageId = Utils.GenerateGuid(); + message[ipc_id] = messageId; + const responseHandler: (args: any) => void = response => { + const { error } = response; + if (response[is_response] && response[ipc_id] === messageId) { + target.removeListener("message", responseHandler); + resolve(error); + } + }; + target.addListener("message", responseHandler); + target.send!(message); + }); + } else { + target.send(message); + } + } + + export function addMessagesHandler(target: NodeJS.EventEmitter & { send?: Function }, handler: (message: any) => void | Promise<void>): void { + target.addListener("message", async incoming => { + let error: Error | undefined; + try { + await handler(incoming); + } catch (e) { + error = e; + } + if (incoming[response_expected] && target.send) { + const response: any = { error }; + response[ipc_id] = incoming[ipc_id]; + response[is_response] = true; + target.send(response); + } + }); + } + +}
\ No newline at end of file diff --git a/src/server/session/utilities/session_config.ts b/src/server/session/utilities/session_config.ts new file mode 100644 index 000000000..b0e65dde4 --- /dev/null +++ b/src/server/session/utilities/session_config.ts @@ -0,0 +1,129 @@ +import { Schema } from "jsonschema"; +import { yellow, red, cyan, green, blue, magenta, Color, grey, gray, white, black } from "colors"; + +const colorPattern = /black|red|green|yellow|blue|magenta|cyan|white|gray|grey/; + +const identifierProperties: Schema = { + type: "object", + properties: { + text: { + type: "string", + minLength: 1 + }, + color: { + type: "string", + pattern: colorPattern + } + } +}; + +const portProperties: Schema = { + type: "number", + minimum: 1024, + maximum: 65535 +}; + +export const configurationSchema: Schema = { + id: "/configuration", + type: "object", + properties: { + showServerOutput: { type: "boolean" }, + ports: { + type: "object", + properties: { + server: portProperties, + socket: portProperties + }, + required: ["server"], + additionalProperties: true + }, + identifiers: { + type: "object", + properties: { + master: identifierProperties, + worker: identifierProperties, + exec: identifierProperties + } + }, + polling: { + type: "object", + additionalProperties: false, + properties: { + intervalSeconds: { + type: "number", + minimum: 1, + maximum: 86400 + }, + route: { + type: "string", + pattern: /\/[a-zA-Z]*/g + }, + failureTolerance: { + type: "number", + minimum: 0, + } + } + }, + } +}; + +type ColorLabel = "yellow" | "red" | "cyan" | "green" | "blue" | "magenta" | "grey" | "gray" | "white" | "black"; + +export const colorMapping: Map<ColorLabel, Color> = new Map([ + ["yellow", yellow], + ["red", red], + ["cyan", cyan], + ["green", green], + ["blue", blue], + ["magenta", magenta], + ["grey", grey], + ["gray", gray], + ["white", white], + ["black", black] +]); + +interface Identifier { + text: string; + color: ColorLabel; +} + +export interface Identifiers { + master: Identifier; + worker: Identifier; + exec: Identifier; +} + +export interface Configuration { + showServerOutput: boolean; + identifiers: Identifiers; + ports: { [description: string]: number }; + polling: { + route: string; + intervalSeconds: number; + failureTolerance: number; + }; +} + +export const defaultConfig: Configuration = { + showServerOutput: false, + identifiers: { + master: { + text: "__monitor__", + color: "yellow" + }, + worker: { + text: "__server__", + color: "magenta" + }, + exec: { + text: "__exec__", + color: "green" + } + }, + ports: { server: 3000 }, + polling: { + route: "/", + intervalSeconds: 30, + failureTolerance: 0 + } +};
\ No newline at end of file diff --git a/src/server/session/utilities/utilities.ts b/src/server/session/utilities/utilities.ts new file mode 100644 index 000000000..ac8a6590a --- /dev/null +++ b/src/server/session/utilities/utilities.ts @@ -0,0 +1,31 @@ +export namespace Utilities { + + /** + * At any arbitrary layer of nesting within the configuration objects, any single value that + * is not specified by the configuration is given the default counterpart. If, within an object, + * one peer is given by configuration and two are not, the one is preserved while the two are given + * the default value. + * @returns the composition of all of the assigned objects, much like Object.assign(), but with more + * granularity in the overwriting of nested objects + */ + export function preciseAssign(target: any, ...sources: any[]): any { + for (const source of sources) { + preciseAssignHelper(target, source); + } + return target; + } + + export function preciseAssignHelper(target: any, source: any) { + Array.from(new Set([...Object.keys(target), ...Object.keys(source)])).map(property => { + let targetValue: any, sourceValue: any; + if (sourceValue = source[property]) { + if (typeof sourceValue === "object" && typeof (targetValue = target[property]) === "object") { + preciseAssignHelper(targetValue, sourceValue); + } else { + target[property] = sourceValue; + } + } + }); + } + +}
\ No newline at end of file |