aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore1
-rw-r--r--logs/npm-2-Wed, 11 Dec 2019 08:44:28 GMT.log274
-rw-r--r--logs/server_pids.txt1
-rw-r--r--src/server/ActionUtilities.ts9
-rw-r--r--src/server/ChildProcessUtilities/ProcessFactory.ts (renamed from src/server/ProcessManager.ts)67
-rw-r--r--src/server/ChildProcessUtilities/daemon/persistence_daemon.ts (renamed from src/server/daemon/persistence_daemon.ts)58
-rw-r--r--src/server/daemon/current_daemon_pid.txt1
-rw-r--r--src/server/daemon/session_crashes_@ 2019-12-11T08:31:56.281Z.log1
-rw-r--r--src/server/daemon/session_crashes_@ 2019-12-11T08:43:46.454Z.log2
-rw-r--r--src/server/index.ts11
10 files changed, 92 insertions, 333 deletions
diff --git a/.gitignore b/.gitignore
index cf4ed308b..38c619c52 100644
--- a/.gitignore
+++ b/.gitignore
@@ -6,3 +6,4 @@ ClientUtils.ts
solr-8.1.1/server/
src/server/public/files/
src/scraping/acm/package-lock.json
+src/server/ChildProcessUtilities/daemon/**/*.log
diff --git a/logs/npm-2-Wed, 11 Dec 2019 08:44:28 GMT.log b/logs/npm-2-Wed, 11 Dec 2019 08:44:28 GMT.log
deleted file mode 100644
index 37e232d48..000000000
--- a/logs/npm-2-Wed, 11 Dec 2019 08:44:28 GMT.log
+++ /dev/null
@@ -1,274 +0,0 @@
-
-> dash@1.0.0 start-spawn /Users/swilkinss2012/Documents/GitHub/Dash-Web
-> cross-env SPAWNED=true NODE_OPTIONS=--max_old_space_size=4096 ts-node-dev -- src/server/index.ts
-
-Using ts-node version 7.0.1, typescript version 3.7.2
-objc[9678]: Class GNotificationCenterDelegate is implemented in both /Users/swilkinss2012/Documents/GitHub/Dash-Web/node_modules/sharp/vendor/lib/libgio-2.0.0.dylib (0x10838d578) and /Users/swilkinss2012/Documents/GitHub/Dash-Web/node_modules/canvas/build/Release/libgio-2.0.0.dylib (0x10afd9578). One of the two will be used. Which one is undefined.
-
-starting execution of preliminary functions...
-(node:9678) DeprecationWarning: current URL string parser is deprecated, and will be removed in a future version. To use the new parser, pass option { useNewUrlParser: true } to MongoClient.connect.
-completed preliminary functions
-.
-Starting type checking and linting service...
-Using 1 worker with 2048MB memory limit
-
-running server in development mode
-
-registering server routes...
-all server routes have been successfully registered:
-/
-/activity
-/buxton
-/delete
-/deleteAll
-/deleteWithAux
-/deleteWithGoogleCredentials
-/doc/:docId
-/downloadId/:docId
-/environment/:key
-/getCurrentUser
-/getUserDocumentId
-/getUsers
-/googleDocs/:sector/:action
-/googlePhotosMediaDownload
-/googlePhotosMediaUpload
-/home
-/imageHierarchyExport/:docId
-/inspectImage
-/persist
-/pull
-/readGoogleAccessToken
-/search
-/serializeDoc/:docId
-/serverHeartbeat
-/shutdown
-/solr/:action
-/textsearch
-/thumbnail/:filename
-/upload
-/uploadDoc
-/uploadURI
-/version
-/writeGoogleAccessToken
-
-websocket listening on port 4321
-server listening on port 1050
-
-ℹ 「wdm」: wait until bundle finished: /serverHeartbeat
-user samuel_wilkins@brown.edu has connected to the web socket
-user samuel_wilkins@brown.edu has connected to the web socket
-ℹ 「wdm」: wait until bundle finished: /serverHeartbeat
-ℹ 「wdm」: wait until bundle finished: /serverHeartbeat
-ℹ 「wdm」: wait until bundle finished: /serverHeartbeat
-ℹ 「wdm」: wait until bundle finished: /serverHeartbeat
-user samuel_wilkins@brown.edu has connected to the web socket
-user samuel_wilkins@brown.edu has connected to the web socket
-Type checking and linting in progress...
-webpack built 8f6b743d91fd3862683b in 47419ms
-⚠ 「wdm」: Hash: 8f6b743d91fd3862683b
-Version: webpack 4.36.1
-Time: 47419ms
-Built at: 12/11/2019 3:45:31 AM
- Asset Size Chunks  Chunk Names
-275711e56bd1bc79fdff544a3d7dbfae.png 289 bytes  [emitted]
-32f1593298e6e7bee5673bf647328d72.png 429 bytes  [emitted]
-718c914a99a2136c01c84e01f63e505a.png 829 bytes  [emitted]
-906f1a1816c2a03b5c7612f6aa2ceece.png 281 bytes  [emitted]
- assets/downarrow.png 3.28 KiB  [emitted]
- assets/env.json 360 bytes  [emitted]
- assets/google_photos.png 114 KiB  [emitted]
- assets/google_tags.png 7.9 KiB  [emitted]
- assets/loading.gif 112 KiB  [emitted]
- assets/pdf.worker.js 1.55 MiB  [emitted]
- bundle.js 20.8 MiB bundle [emitted] bundle
- bundle.js.map 23.3 MiB bundle [emitted] bundle
- debug/repl.html 348 bytes  [emitted]
- debug/test.html 245 bytes  [emitted]
- debug/viewer.html 357 bytes  [emitted]
-e7a34b49f3c49ca0c25c76b30cd09e12.png 445 bytes  [emitted]
- imageUpload.js 20.8 MiB imageUpload [emitted] imageUpload
- imageUpload.js.map 23.3 MiB imageUpload [emitted] imageUpload
- index.html 593 bytes  [emitted]
- inkControls.js 116 KiB inkControls [emitted] inkControls
- inkControls.js.map 122 KiB inkControls [emitted] inkControls
- mobile/image.html 333 bytes  [emitted]
- mobile/ink.html 252 bytes  [emitted]
- repl.js 9.31 MiB repl [emitted] repl
- repl.js.map 10.5 MiB repl [emitted] repl
- test.js 1.2 MiB test [emitted] test
- test.js.map 1.42 MiB test [emitted] test
- test.pdf 53.6 KiB  [emitted]
- vendors~pdfjsWorker.js 1.55 MiB vendors~pdfjsWorker [emitted] vendors~pdfjsWorker
- vendors~pdfjsWorker.js.map 1.87 MiB vendors~pdfjsWorker [emitted] vendors~pdfjsWorker
- viewer.js 9.47 MiB viewer [emitted] viewer
- viewer.js.map 10.7 MiB viewer [emitted] viewer
-Entrypoint bundle = bundle.js bundle.js.map
-Entrypoint viewer = viewer.js viewer.js.map
-Entrypoint repl = repl.js repl.js.map
-Entrypoint test = test.js test.js.map
-Entrypoint inkControls = inkControls.js inkControls.js.map
-Entrypoint imageUpload = imageUpload.js imageUpload.js.map
-[19] multi ./src/client/views/Main.tsx webpack-hot-middleware/client?reload=true 40 bytes {bundle} [built]
-[20] multi ./src/debug/Viewer.tsx webpack-hot-middleware/client?reload=true 40 bytes {viewer} [built]
-[21] multi ./src/debug/Repl.tsx webpack-hot-middleware/client?reload=true 40 bytes {repl} [built]
-[22] multi ./src/debug/Test.tsx webpack-hot-middleware/client?reload=true 40 bytes {test} [built]
-[23] multi ./src/mobile/InkControls.tsx webpack-hot-middleware/client?reload=true 40 bytes {inkControls} [built]
-[24] multi ./src/mobile/ImageUpload.tsx webpack-hot-middleware/client?reload=true 40 bytes {imageUpload} [built]
- [./node_modules/mobx-react/index.module.js] 48.8 KiB {bundle} {viewer} {repl} {imageUpload} [built]
- [./node_modules/mobx/lib/mobx.module.js] 175 KiB {bundle} {viewer} {repl} {imageUpload} [built]
- [./node_modules/webpack-hot-middleware/client.js?reload=true] (webpack)-hot-middleware/client.js?reload=true 7.68 KiB {bundle} {viewer} {repl} {test} {inkControls} {imageUpload} [built]
- [./src/client/views/Main.tsx] 4.03 KiB {bundle} [built]
- [./src/debug/Repl.tsx] 6.87 KiB {repl} [built]
- [./src/debug/Test.tsx] 1.02 KiB {test} [built]
- [./src/debug/Viewer.tsx] 12.1 KiB {viewer} [built]
- [./src/mobile/ImageUpload.tsx] 9.97 KiB {imageUpload} [built]
- [./src/mobile/InkControls.tsx] 14 bytes {inkControls} [built]
- + 1494 hidden modules
-
-WARNING in ./node_modules/typescript/lib/typescript.js 5121:41-60
-Critical dependency: the request of a dependency is an expression
- @ ./src/client/util/Scripting.ts
- @ ./src/debug/Viewer.tsx
- @ multi ./src/debug/Viewer.tsx webpack-hot-middleware/client?reload=true
-ℹ 「wdm」: Compiled with warnings.
-ℹ 「wdm」: Compiling...
-webpack building...
-ℹ 「wdm」: wait until bundle finished: /login
-ℹ 「wdm」: wait until bundle finished: /login
-ℹ 「wdm」: wait until bundle finished: /login
-ℹ 「wdm」: wait until bundle finished: /login
-ℹ 「wdm」: wait until bundle finished: /login
-Type checking and linting in progress...
-webpack built 8f6b743d91fd3862683b in 615ms
-⚠ 「wdm」: Hash: 8f6b743d91fd3862683b
-Version: webpack 4.36.1
-Time: 615ms
-Built at: 12/11/2019 3:45:33 AM
- Asset Size Chunks Chunk Names
-275711e56bd1bc79fdff544a3d7dbfae.png 289 bytes  
-32f1593298e6e7bee5673bf647328d72.png 429 bytes  
-718c914a99a2136c01c84e01f63e505a.png 829 bytes  
-906f1a1816c2a03b5c7612f6aa2ceece.png 281 bytes  
- bundle.js 20.8 MiB bundle bundle
- bundle.js.map 23.3 MiB bundle bundle
-e7a34b49f3c49ca0c25c76b30cd09e12.png 445 bytes  
- imageUpload.js 20.8 MiB imageUpload imageUpload
- imageUpload.js.map 23.3 MiB imageUpload imageUpload
- inkControls.js 116 KiB inkControls inkControls
- inkControls.js.map 122 KiB inkControls inkControls
- repl.js 9.31 MiB repl repl
- repl.js.map 10.5 MiB repl repl
- test.js 1.2 MiB test test
- test.js.map 1.42 MiB test test
- vendors~pdfjsWorker.js 1.55 MiB vendors~pdfjsWorker vendors~pdfjsWorker
- vendors~pdfjsWorker.js.map 1.87 MiB vendors~pdfjsWorker vendors~pdfjsWorker
- viewer.js 9.47 MiB viewer viewer
- viewer.js.map 10.7 MiB viewer viewer
-Entrypoint bundle = bundle.js bundle.js.map
-Entrypoint viewer = viewer.js viewer.js.map
-Entrypoint repl = repl.js repl.js.map
-Entrypoint test = test.js test.js.map
-Entrypoint inkControls = inkControls.js inkControls.js.map
-Entrypoint imageUpload = imageUpload.js imageUpload.js.map
-[19] multi ./src/client/views/Main.tsx webpack-hot-middleware/client?reload=true 40 bytes {bundle}
-[20] multi ./src/debug/Viewer.tsx webpack-hot-middleware/client?reload=true 40 bytes {viewer}
-[21] multi ./src/debug/Repl.tsx webpack-hot-middleware/client?reload=true 40 bytes {repl}
-[22] multi ./src/debug/Test.tsx webpack-hot-middleware/client?reload=true 40 bytes {test}
-[23] multi ./src/mobile/InkControls.tsx webpack-hot-middleware/client?reload=true 40 bytes {inkControls}
-[24] multi ./src/mobile/ImageUpload.tsx webpack-hot-middleware/client?reload=true 40 bytes {imageUpload}
- [./node_modules/mobx-react/index.module.js] 48.8 KiB {bundle} {viewer} {repl} {imageUpload}
- [./node_modules/mobx/lib/mobx.module.js] 175 KiB {bundle} {viewer} {repl} {imageUpload}
- [./node_modules/webpack-hot-middleware/client.js?reload=true] (webpack)-hot-middleware/client.js?reload=true 7.68 KiB {bundle} {viewer} {repl} {test} {inkControls} {imageUpload}
- [./src/client/views/Main.tsx] 4.03 KiB {bundle}
- [./src/debug/Repl.tsx] 6.87 KiB {repl}
- [./src/debug/Test.tsx] 1.02 KiB {test}
- [./src/debug/Viewer.tsx] 12.1 KiB {viewer}
- [./src/mobile/ImageUpload.tsx] 9.97 KiB {imageUpload}
- [./src/mobile/InkControls.tsx] 14 bytes {inkControls}
- + 1494 hidden modules
-
-WARNING in ./node_modules/typescript/lib/typescript.js 5121:41-60
-Critical dependency: the request of a dependency is an expression
- @ ./src/client/util/Scripting.ts
- @ ./src/debug/Viewer.tsx
- @ multi ./src/debug/Viewer.tsx webpack-hot-middleware/client?reload=true
-ℹ 「wdm」: Compiled with warnings.
-WARNING in /Users/swilkinss2012/Documents/GitHub/Dash-Web/src/client/util/RichTextRules.ts(81,21):
-prefer-const: Identifier 'marks' is never reassigned; use 'const' instead of 'let'.
-WARNING in /Users/swilkinss2012/Documents/GitHub/Dash-Web/src/client/util/RichTextRules.ts(83,25):
-prefer-const: Identifier 'tr' is never reassigned; use 'const' instead of 'let'.
-WARNING in /Users/swilkinss2012/Documents/GitHub/Dash-Web/src/client/util/RichTextRules.ts(86,21):
-prefer-const: Identifier 'isValidColor' is never reassigned; use 'const' instead of 'let'.
-WARNING in /Users/swilkinss2012/Documents/GitHub/Dash-Web/src/client/util/RichTextRules.ts(87,25):
-prefer-const: Identifier 's' is never reassigned; use 'const' instead of 'var'.
-WARNING in /Users/swilkinss2012/Documents/GitHub/Dash-Web/src/client/util/RichTextRules.ts(89,36):
-triple-equals: == should be ===
-WARNING in /Users/swilkinss2012/Documents/GitHub/Dash-Web/src/client/util/RichTextRules.ts(90,18):
-semicolon: Missing semicolon
-WARNING in /Users/swilkinss2012/Documents/GitHub/Dash-Web/src/client/util/RichTextRules.ts(99,21):
-prefer-const: Identifier 'tr' is never reassigned; use 'const' instead of 'let'.
-WARNING in /Users/swilkinss2012/Documents/GitHub/Dash-Web/src/client/util/RichTextRules.ts(100,21):
-prefer-const: Identifier 'marks' is never reassigned; use 'const' instead of 'let'.
-WARNING in /Users/swilkinss2012/Documents/GitHub/Dash-Web/src/client/util/RichTextRules.ts(126,25):
-prefer-const: Identifier 'node' is never reassigned; use 'const' instead of 'let'.
-WARNING in /Users/swilkinss2012/Documents/GitHub/Dash-Web/src/client/util/RichTextRules.ts(141,25):
-prefer-const: Identifier 'node' is never reassigned; use 'const' instead of 'let'.
-WARNING in /Users/swilkinss2012/Documents/GitHub/Dash-Web/src/client/util/RichTextRules.ts(154,66):
-no-unnecessary-type-assertion: This assertion is unnecessary since it does not change the type of the expression.
-WARNING in /Users/swilkinss2012/Documents/GitHub/Dash-Web/src/client/util/RichTextRules.ts(155,25):
-prefer-const: Identifier 'node' is never reassigned; use 'const' instead of 'let'.
-WARNING in /Users/swilkinss2012/Documents/GitHub/Dash-Web/src/client/util/RichTextRules.ts(155,33):
-no-unnecessary-type-assertion: This assertion is unnecessary since it does not change the type of the expression.
-WARNING in /Users/swilkinss2012/Documents/GitHub/Dash-Web/src/client/util/RichTextRules.ts(160,25):
-prefer-const: Identifier 'node' is never reassigned; use 'const' instead of 'let'.
-WARNING in /Users/swilkinss2012/Documents/GitHub/Dash-Web/src/client/util/RichTextRules.ts(192,29):
-prefer-const: Identifier 'doc' is never reassigned; use 'const' instead of 'let'.
-WARNING in /Users/swilkinss2012/Documents/GitHub/Dash-Web/src/client/util/RichTextSchema.tsx(640,134):
-semicolon: Missing semicolon
-WARNING in /Users/swilkinss2012/Documents/GitHub/Dash-Web/src/client/util/RichTextSchema.tsx(649,21):
-prefer-const: Identifier 'expand' is never reassigned; use 'const' instead of 'let'.
-WARNING in /Users/swilkinss2012/Documents/GitHub/Dash-Web/src/client/util/RichTextSchema.tsx(650,21):
-prefer-const: Identifier 'tr' is never reassigned; use 'const' instead of 'let'.
-WARNING in /Users/swilkinss2012/Documents/GitHub/Dash-Web/src/client/util/RichTextSchema.tsx(654,138):
-semicolon: Missing semicolon
-WARNING in /Users/swilkinss2012/Documents/GitHub/Dash-Web/src/client/util/RichTextSchema.tsx(658,10):
-semicolon: Missing semicolon
-WARNING in /Users/swilkinss2012/Documents/GitHub/Dash-Web/src/client/views/collections/CollectionView.tsx(243,13):
-prefer-const: Identifier 'main' is never reassigned; use 'const' instead of 'let'.
-WARNING in /Users/swilkinss2012/Documents/GitHub/Dash-Web/src/client/views/collections/CollectionView.tsx(244,13):
-prefer-const: Identifier 'next' is never reassigned; use 'const' instead of 'let'.
-WARNING in /Users/swilkinss2012/Documents/GitHub/Dash-Web/src/client/views/collections/CollectionView.tsx(245,13):
-prefer-const: Identifier 'prev' is never reassigned; use 'const' instead of 'let'.
-WARNING in /Users/swilkinss2012/Documents/GitHub/Dash-Web/src/client/views/DocumentDecorations.tsx(88,21):
-prefer-const: Identifier 'selectionTitleFieldKey' is never reassigned; use 'const' instead of 'let'.
-WARNING in /Users/swilkinss2012/Documents/GitHub/Dash-Web/src/client/views/DocumentDecorations.tsx(95,8):
-semicolon: Missing semicolon
-WARNING in /Users/swilkinss2012/Documents/GitHub/Dash-Web/src/client/views/EditableView.tsx(123,13):
-prefer-const: Identifier 'wasFocused' is never reassigned; use 'const' instead of 'let'.
-WARNING in /Users/swilkinss2012/Documents/GitHub/Dash-Web/src/client/views/MainView.tsx(289,11):
-semicolon: Missing semicolon
-WARNING in /Users/swilkinss2012/Documents/GitHub/Dash-Web/src/client/views/nodes/DocumentView.tsx(151,25):
-prefer-const: Identifier 'any' is never reassigned; use 'const' instead of 'let'.
-WARNING in /Users/swilkinss2012/Documents/GitHub/Dash-Web/src/client/views/nodes/FormattedTextBox.tsx(910,13):
-prefer-const: Identifier 'prosediv' is never reassigned; use 'const' instead of 'let'.
-WARNING in /Users/swilkinss2012/Documents/GitHub/Dash-Web/src/client/views/nodes/FormattedTextBox.tsx(911,13):
-prefer-const: Identifier 'keeplocation' is never reassigned; use 'const' instead of 'let'.
-WARNING in /Users/swilkinss2012/Documents/GitHub/Dash-Web/src/client/views/nodes/FormattedTextBox.tsx(913,13):
-prefer-const: Identifier 'pos' is never reassigned; use 'const' instead of 'let'.
-WARNING in /Users/swilkinss2012/Documents/GitHub/Dash-Web/src/client/views/nodes/FormattedTextBox.tsx(928,17):
-prefer-const: Identifier 'pcords' is never reassigned; use 'const' instead of 'let'.
-WARNING in /Users/swilkinss2012/Documents/GitHub/Dash-Web/src/client/views/nodes/FormattedTextBox.tsx(929,17):
-prefer-const: Identifier 'node' is never reassigned; use 'const' instead of 'let'.
-WARNING in /Users/swilkinss2012/Documents/GitHub/Dash-Web/src/client/views/nodes/FormattedTextBox.tsx(935,21):
-prefer-const: Identifier 'lastNode' is never reassigned; use 'const' instead of 'let'.
-WARNING in /Users/swilkinss2012/Documents/GitHub/Dash-Web/src/client/views/nodes/FormattedTextBox.tsx(976,71):
-semicolon: Missing semicolon
-WARNING in /Users/swilkinss2012/Documents/GitHub/Dash-Web/src/client/views/nodes/FormattedTextBox.tsx(987,17):
-prefer-const: Identifier '$pos' is never reassigned; use 'const' instead of 'let'.
-WARNING in /Users/swilkinss2012/Documents/GitHub/Dash-Web/src/client/views/nodes/FormattedTextBox.tsx(1001,25):
-prefer-const: Identifier '$olist_pos' is never reassigned; use 'const' instead of 'let'.
-WARNING in /Users/swilkinss2012/Documents/GitHub/Dash-Web/src/client/views/nodes/FormattedTextBox.tsx(1103,17):
-prefer-const: Identifier 'newHeight' is never reassigned; use 'const' instead of 'let'.
-No type errors found
-Version: typescript 3.7.2, tslint 5.18.0
-Time: 5473ms
diff --git a/logs/server_pids.txt b/logs/server_pids.txt
deleted file mode 100644
index 2aa143f24..000000000
--- a/logs/server_pids.txt
+++ /dev/null
@@ -1 +0,0 @@
-9675 created at Wed, 11 Dec 2019 08:44:28 GMT
diff --git a/src/server/ActionUtilities.ts b/src/server/ActionUtilities.ts
index 9bdc4ed93..2e62443c6 100644
--- a/src/server/ActionUtilities.ts
+++ b/src/server/ActionUtilities.ts
@@ -1,4 +1,4 @@
-import { readFile, writeFile, exists, mkdir, unlink } from 'fs';
+import { readFile, writeFile, exists, mkdir, unlink, createWriteStream } from 'fs';
import { ExecOptions } from 'shelljs';
import { exec } from 'child_process';
import * as path from 'path';
@@ -10,6 +10,11 @@ export function pathFromRoot(relative: string) {
return path.resolve(projectRoot, relative);
}
+export async function fileDescriptorFromStream(path: string) {
+ const logStream = createWriteStream(path);
+ return new Promise<number>(resolve => logStream.on("open", resolve));
+}
+
export const command_line = (command: string, fromDirectory?: string) => {
return new Promise<string>((resolve, reject) => {
const options: ExecOptions = {};
@@ -54,7 +59,7 @@ export async function log_execution<T>({ startMessage, endMessage, action, color
} catch (e) {
error = e;
} finally {
- log_helper(`${typeof endMessage === "string" ? endMessage : endMessage({ result, error })}.`, resolvedColor);
+ log_helper(typeof endMessage === "string" ? endMessage : endMessage({ result, error }), resolvedColor);
}
return result;
}
diff --git a/src/server/ProcessManager.ts b/src/server/ChildProcessUtilities/ProcessFactory.ts
index 671f0a234..745b1479a 100644
--- a/src/server/ProcessManager.ts
+++ b/src/server/ChildProcessUtilities/ProcessFactory.ts
@@ -1,44 +1,28 @@
-import { existsSync, mkdirSync, createWriteStream } from "fs";
-import { pathFromRoot, log_execution } from './ActionUtilities';
+import { existsSync, mkdirSync } from "fs";
+import { pathFromRoot, log_execution, fileDescriptorFromStream } from '../ActionUtilities';
import { red, green } from "colors";
import rimraf = require("rimraf");
-import { ChildProcess, spawn } from "child_process";
+import { ChildProcess, spawn, StdioOptions } from "child_process";
import { Stream } from "stream";
+import { resolve } from "path";
-const daemonPath = pathFromRoot("./src/server/daemon/persistence_daemon.ts");
-
-export namespace ProcessManager {
-
- export async function initialize() {
- const logPath = pathFromRoot("./logs");
- if (existsSync(logPath)) {
- if (!process.env.SPAWNED) {
- await new Promise<any>(resolve => rimraf(logPath, resolve));
- }
- }
- mkdirSync(logPath);
- }
-
- function generate_log_name(command: string, args?: readonly string[]) {
- return pathFromRoot(`./logs/${command}-${args?.length}-${new Date().toUTCString()}.log`);
- }
+export namespace ProcessFactory {
export type Sink = "pipe" | "ipc" | "ignore" | "inherit" | Stream | number | null | undefined;
- export async function spawn_detached(command: string, args?: readonly string[], out?: Sink): Promise<ChildProcess> {
- if (!out) {
- const logStream = createWriteStream(generate_log_name(command, args));
- out = await new Promise<number>(resolve => logStream.on("open", resolve));
+ export async function createWorker(command: string, args?: readonly string[], stdio?: StdioOptions | "logfile", detached = true): Promise<ChildProcess> {
+ if (stdio === "logfile") {
+ const log_fd = await Logger.create(command, args);
+ stdio = ["ignore", log_fd, log_fd];
}
- const child = spawn(command, args, { detached: true, stdio: ["ignore", out, out] });
+ const child = spawn(command, args, { detached, stdio });
child.unref();
return child;
}
- let daemonInitialized = false;
- export async function trySpawnDaemon() {
- if (!process.env.SPAWNED && !daemonInitialized) {
- daemonInitialized = true;
+ export namespace NamedAgents {
+
+ export async function persistenceDaemon() {
await log_execution({
startMessage: "\ninitializing persistence daemon",
endMessage: ({ result, error }) => {
@@ -50,11 +34,34 @@ export namespace ProcessManager {
}
return "failsafe daemon process successfully spawned";
},
- action: () => spawn_detached('npx', ['ts-node', daemonPath], process.stdout),
+ 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<any>(resolve => rimraf(logPath, resolve));
+ }
+ }
+ mkdirSync(logPath);
+ }
+
+ export async function create(command: string, args?: readonly string[]): Promise<number> {
+ 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/daemon/persistence_daemon.ts b/src/server/ChildProcessUtilities/daemon/persistence_daemon.ts
index 099c7898c..888cf38b8 100644
--- a/src/server/daemon/persistence_daemon.ts
+++ b/src/server/ChildProcessUtilities/daemon/persistence_daemon.ts
@@ -1,32 +1,52 @@
import * as request from "request-promise";
-import { log_execution, pathFromRoot } from "../ActionUtilities";
+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, createWriteStream, existsSync } from "fs";
+import { writeFileSync, appendFileSync, existsSync, mkdirSync } from "fs";
import { resolve } from 'path';
import { ChildProcess } from "child_process";
-import { ProcessManager } from "../ProcessManager";
+import { ProcessFactory } from "../ProcessFactory";
-console.log(yellow("Initializing daemon..."));
+const identifier = yellow("__daemon__:");
process.on('SIGINT', () => current_backup?.kill("SIGTERM"));
-const crashLogPath = resolve(__dirname, `./session_crashes_${timestamp()}.log`);
+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()}.`);
- console.log(formatted);
+ 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";
-let restarting = false;
-
const frequency = 10;
const { pid } = process;
-writeFileSync(resolve(__dirname, "./current_daemon_pid.txt"), pid);
-console.log(cyan(`${pid} written to ./current_daemon_pid.txt`));
+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()}`;
@@ -35,9 +55,9 @@ function timestamp() {
let current_backup: ChildProcess | undefined = undefined;
async function listen() {
- console.log(yellow(`Beginning to poll server heartbeat every ${frequency} seconds...\n`));
+ identifiedLog(yellow(`Beginning to poll server heartbeat every ${frequency} seconds...\n`));
if (!LOCATION) {
- console.log(red("No location specified for persistence daemon. Please include as a command line environment variable or in a .env file."));
+ 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`;
@@ -60,26 +80,26 @@ async function listen() {
addLogEntry("Detected a server crash", red);
current_backup?.kill();
await log_execution({
- startMessage: "Sending crash notification email",
+ startMessage: identifier + " Sending crash notification email",
endMessage: ({ error, result }) => {
const success = error === null && result === true;
- return `${(success ? `Notification successfully sent to` : `Failed to notify`)} ${recipient} ${timestamp()}`;
+ 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: "Initiating server restart",
+ startMessage: identifier + " Initiating server restart",
endMessage: ({ result, error }) => {
const success = error === null && result !== undefined;
- return success ? "Child process spawned.." : `An error occurred while attempting to restart the server:\n${error}`;
+ return identifier + success ? " Child process spawned..." : ` An error occurred while attempting to restart the server:\n${error}`;
},
- action: () => ProcessManager.spawn_detached('npm', ['run', 'start-spawn']),
+ action: () => ProcessFactory.createWorker('npm', ['run', 'start-spawn'], "inherit"),
color: green
});
- writeFileSync(pathFromRoot("./logs/current_server_pid.txt"), `${current_backup?.pid ?? -1} created ${timestamp()}\n`);
+ writeLocalPidLog("server", `${(current_backup?.pid ?? -2) + 1} created ${timestamp()}`);
} else {
- console.log(yellow(`Callback ignored because restarting already initiated ${timestamp()}`));
+ identifiedLog(yellow(`Callback ignored because restarting already initiated ${timestamp()}`));
}
}
}
diff --git a/src/server/daemon/current_daemon_pid.txt b/src/server/daemon/current_daemon_pid.txt
deleted file mode 100644
index f3cd0298c..000000000
--- a/src/server/daemon/current_daemon_pid.txt
+++ /dev/null
@@ -1 +0,0 @@
-9626 \ No newline at end of file
diff --git a/src/server/daemon/session_crashes_@ 2019-12-11T08:31:56.281Z.log b/src/server/daemon/session_crashes_@ 2019-12-11T08:31:56.281Z.log
deleted file mode 100644
index 32b7810ea..000000000
--- a/src/server/daemon/session_crashes_@ 2019-12-11T08:31:56.281Z.log
+++ /dev/null
@@ -1 +0,0 @@
-Detected a server crash @ 2019-12-11T08:32:36.317Z
diff --git a/src/server/daemon/session_crashes_@ 2019-12-11T08:43:46.454Z.log b/src/server/daemon/session_crashes_@ 2019-12-11T08:43:46.454Z.log
deleted file mode 100644
index ebb6843c2..000000000
--- a/src/server/daemon/session_crashes_@ 2019-12-11T08:43:46.454Z.log
+++ /dev/null
@@ -1,2 +0,0 @@
-Detected a server crash @ 2019-12-11T08:44:26.494Z.
-Backup server successfully restarted @ 2019-12-11T08:45:33.644Z.
diff --git a/src/server/index.ts b/src/server/index.ts
index 795418b31..bebb9b365 100644
--- a/src/server/index.ts
+++ b/src/server/index.ts
@@ -23,7 +23,7 @@ import GeneralGoogleManager from "./ApiManagers/GeneralGoogleManager";
import GooglePhotosManager from "./ApiManagers/GooglePhotosManager";
import { yellow, red } from "colors";
import { disconnect } from "../server/Initialization";
-import { ProcessManager } from "./ProcessManager";
+import { ProcessFactory, Logger } from "./ChildProcessUtilities/ProcessFactory";
export const publicDirectory = path.resolve(__dirname, "public");
export const filesDirectory = path.resolve(publicDirectory, "files");
@@ -36,7 +36,7 @@ export const ExitHandlers = new Array<() => void>();
* before clients can access the server should be run or awaited here.
*/
async function preliminaryFunctions() {
- await ProcessManager.initialize();
+ await Logger.initialize();
await GoogleCredentialsLoader.loadCredentials();
GoogleApiServerUtils.processProjectCredentials();
await DashUploadUtils.buildFileDirectories();
@@ -121,11 +121,16 @@ function routeSetter({ isRelease, addSupervisedRoute, logRegistrationOutcome }:
}
});
+ let daemonInitialized = false;
+ const { SPAWNED, RELEASE } = process.env;
addSupervisedRoute({
method: Method.GET,
subscription: "/persist",
onValidation: ({ res }) => {
- ProcessManager.trySpawnDaemon();
+ if (RELEASE && !SPAWNED && !daemonInitialized) {
+ daemonInitialized = true;
+ ProcessFactory.NamedAgents.persistenceDaemon();
+ }
res.redirect("/home");
}
});