aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--logs/npm-2-Wed, 11 Dec 2019 08:44:28 GMT.log274
-rw-r--r--logs/npx ts-node-20965-Wed, 11 Dec 2019 03:38:32 GMT0
-rw-r--r--logs/server_pids.txt1
-rw-r--r--src/server/ActionUtilities.ts22
-rw-r--r--src/server/ProcessManager.ts49
-rw-r--r--src/server/daemon/current_daemon_pid.txt1
-rw-r--r--src/server/daemon/persistence_daemon.ts53
-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
9 files changed, 357 insertions, 46 deletions
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
new file mode 100644
index 000000000..37e232d48
--- /dev/null
+++ b/logs/npm-2-Wed, 11 Dec 2019 08:44:28 GMT.log
@@ -0,0 +1,274 @@
+
+> 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/npx ts-node-20965-Wed, 11 Dec 2019 03:38:32 GMT b/logs/npx ts-node-20965-Wed, 11 Dec 2019 03:38:32 GMT
deleted file mode 100644
index e69de29bb..000000000
--- a/logs/npx ts-node-20965-Wed, 11 Dec 2019 03:38:32 GMT
+++ /dev/null
diff --git a/logs/server_pids.txt b/logs/server_pids.txt
new file mode 100644
index 000000000..2aa143f24
--- /dev/null
+++ b/logs/server_pids.txt
@@ -0,0 +1 @@
+9675 created at Wed, 11 Dec 2019 08:44:28 GMT
diff --git a/src/server/ActionUtilities.ts b/src/server/ActionUtilities.ts
index 2173f4369..9bdc4ed93 100644
--- a/src/server/ActionUtilities.ts
+++ b/src/server/ActionUtilities.ts
@@ -1,12 +1,11 @@
-import * as fs from 'fs';
+import { readFile, writeFile, exists, mkdir, unlink } from 'fs';
import { ExecOptions } from 'shelljs';
-import { exec, spawn } from 'child_process';
+import { exec } from 'child_process';
import * as path from 'path';
import * as rimraf from "rimraf";
import { yellow, Color } from 'colors';
const projectRoot = path.resolve(__dirname, "../../");
-
export function pathFromRoot(relative: string) {
return path.resolve(projectRoot, relative);
}
@@ -21,24 +20,17 @@ export const command_line = (command: string, fromDirectory?: string) => {
});
};
-export async function spawn_detached_process(command: string, args?: readonly string[]) {
- const out = path.resolve(projectRoot, `./logs/${command}-${process.pid}-${new Date().toUTCString()}`);
- const child_out = fs.openSync(out, 'a');
- const child_error = fs.openSync(out, 'a');
- spawn(command, args, { detached: true, stdio: ["ignore", child_out, child_error] }).unref();
-}
-
export const read_text_file = (relativePath: string) => {
const target = path.resolve(__dirname, relativePath);
return new Promise<string>((resolve, reject) => {
- fs.readFile(target, (err, data) => err ? reject(err) : resolve(data.toString()));
+ readFile(target, (err, data) => err ? reject(err) : resolve(data.toString()));
});
};
export const write_text_file = (relativePath: string, contents: any) => {
const target = path.resolve(__dirname, relativePath);
return new Promise<void>((resolve, reject) => {
- fs.writeFile(target, contents, (err) => err ? reject(err) : resolve());
+ writeFile(target, contents, (err) => err ? reject(err) : resolve());
});
};
@@ -93,10 +85,10 @@ export function msToTime(duration: number) {
}
export const createIfNotExists = async (path: string) => {
- if (await new Promise<boolean>(resolve => fs.exists(path, resolve))) {
+ if (await new Promise<boolean>(resolve => exists(path, resolve))) {
return true;
}
- return new Promise<boolean>(resolve => fs.mkdir(path, error => resolve(error === null)));
+ return new Promise<boolean>(resolve => mkdir(path, error => resolve(error === null)));
};
export async function Prune(rootDirectory: string): Promise<boolean> {
@@ -104,4 +96,4 @@ export async function Prune(rootDirectory: string): Promise<boolean> {
return error === null;
}
-export const Destroy = (mediaPath: string) => new Promise<boolean>(resolve => fs.unlink(mediaPath, error => resolve(error === null)));
+export const Destroy = (mediaPath: string) => new Promise<boolean>(resolve => unlink(mediaPath, error => resolve(error === null)));
diff --git a/src/server/ProcessManager.ts b/src/server/ProcessManager.ts
index 2237f9e1b..671f0a234 100644
--- a/src/server/ProcessManager.ts
+++ b/src/server/ProcessManager.ts
@@ -1,7 +1,9 @@
-import { writeFileSync, unlinkSync, existsSync, mkdirSync } from "fs";
-import { pathFromRoot, log_execution, spawn_detached_process } from './ActionUtilities';
-import { resolve } from "path";
-import { red, yellow } from "colors";
+import { existsSync, mkdirSync, createWriteStream } from "fs";
+import { pathFromRoot, log_execution } from './ActionUtilities';
+import { red, green } from "colors";
+import rimraf = require("rimraf");
+import { ChildProcess, spawn } from "child_process";
+import { Stream } from "stream";
const daemonPath = pathFromRoot("./src/server/daemon/persistence_daemon.ts");
@@ -9,22 +11,33 @@ export namespace ProcessManager {
export async function initialize() {
const logPath = pathFromRoot("./logs");
- const filePath = resolve(logPath, "./server_pids.txt");
- const exists = existsSync(logPath);
- if (exists) {
- unlinkSync(filePath);
- } else {
- mkdirSync(logPath);
+ if (existsSync(logPath)) {
+ if (!process.env.SPAWNED) {
+ await new Promise<any>(resolve => rimraf(logPath, resolve));
+ }
}
- const { pid } = process;
- if (process.env.SPAWNED === "true") {
- writeFileSync(filePath, `${pid} created at ${new Date().toUTCString()}\n`);
+ mkdirSync(logPath);
+ }
+
+ function generate_log_name(command: string, args?: readonly string[]) {
+ return pathFromRoot(`./logs/${command}-${args?.length}-${new Date().toUTCString()}.log`);
+ }
+
+ 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));
}
+ const child = spawn(command, args, { detached: true, stdio: ["ignore", out, out] });
+ child.unref();
+ return child;
}
let daemonInitialized = false;
export async function trySpawnDaemon() {
- if (!daemonInitialized) {
+ if (!process.env.SPAWNED && !daemonInitialized) {
daemonInitialized = true;
await log_execution({
startMessage: "\ninitializing persistence daemon",
@@ -32,13 +45,15 @@ export namespace ProcessManager {
const success = error === null && result !== undefined;
if (!success) {
console.log(red("failed to initialize the persistance daemon"));
+ console.log(error);
process.exit(0);
}
- return "persistence daemon process closed";
+ return "failsafe daemon process successfully spawned";
},
- action: () => spawn_detached_process("npx ts-node", [daemonPath]),
- color: yellow
+ action: () => spawn_detached('npx', ['ts-node', daemonPath], process.stdout),
+ color: green
});
+ console.log();
}
}
diff --git a/src/server/daemon/current_daemon_pid.txt b/src/server/daemon/current_daemon_pid.txt
new file mode 100644
index 000000000..f3cd0298c
--- /dev/null
+++ b/src/server/daemon/current_daemon_pid.txt
@@ -0,0 +1 @@
+9626 \ No newline at end of file
diff --git a/src/server/daemon/persistence_daemon.ts b/src/server/daemon/persistence_daemon.ts
index 3eb17a9b4..099c7898c 100644
--- a/src/server/daemon/persistence_daemon.ts
+++ b/src/server/daemon/persistence_daemon.ts
@@ -1,22 +1,41 @@
import * as request from "request-promise";
-import { log_execution, spawn_detached_process } from "../ActionUtilities";
-import { red, yellow, cyan, green } from "colors";
+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 } from "fs";
+import { writeFileSync, appendFileSync, createWriteStream, existsSync } from "fs";
import { resolve } from 'path';
+import { ChildProcess } from "child_process";
+import { ProcessManager } from "../ProcessManager";
+
+console.log(yellow("Initializing daemon..."));
+
+process.on('SIGINT', () => current_backup?.kill("SIGTERM"));
+
+const crashLogPath = resolve(__dirname, `./session_crashes_${timestamp()}.log`);
+function addLogEntry(message: string, color: Color) {
+ const formatted = color(`${message} ${timestamp()}.`);
+ console.log(formatted);
+ appendFileSync(crashLogPath, `${formatted}\n`);
+}
const LOCATION = "http://localhost";
const recipient = "samuel_wilkins@brown.edu";
let restarting = false;
-writeFileSync(resolve(__dirname, "./current_pid.txt"), process.pid);
+const frequency = 10;
+const { pid } = process;
+writeFileSync(resolve(__dirname, "./current_daemon_pid.txt"), pid);
+console.log(cyan(`${pid} written to ./current_daemon_pid.txt`));
function timestamp() {
return `@ ${new Date().toISOString()}`;
}
+let current_backup: ChildProcess | undefined = undefined;
+
async function listen() {
+ console.log(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."));
process.exit(0);
@@ -28,34 +47,40 @@ async function listen() {
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;
- console.log(yellow("Detected a server crash!"));
+ addLogEntry("Detected a server crash", red);
+ current_backup?.kill();
await log_execution({
startMessage: "Sending crash notification email",
endMessage: ({ error, result }) => {
const success = error === null && result === true;
- return (success ? `Notification successfully sent to ` : `Failed to notify `) + recipient;
+ return `${(success ? `Notification successfully sent to` : `Failed to notify`)} ${recipient} ${timestamp()}`;
},
action: async () => notify(error || "Hmm, no error to report..."),
color: cyan
});
- console.log(await log_execution({
+ current_backup = await log_execution({
startMessage: "Initiating server restart",
- endMessage: "Server successfully restarted",
- action: () => spawn_detached_process(`npm run start-spawn`),
+ 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}`;
+ },
+ action: () => ProcessManager.spawn_detached('npm', ['run', 'start-spawn']),
color: green
- }));
- restarting = false;
+ });
+ writeFileSync(pathFromRoot("./logs/current_server_pid.txt"), `${current_backup?.pid ?? -1} created ${timestamp()}\n`);
} else {
console.log(yellow(`Callback ignored because restarting already initiated ${timestamp()}`));
}
- } else {
- console.log(green(`No issues detected ${timestamp()}`));
}
}
}, 1000 * 10);
@@ -85,7 +110,7 @@ async function notify(error: any) {
text: emailText(error)
} as MailOptions;
return new Promise<boolean>(resolve => {
- smtpTransport.sendMail(mailOptions, (dispatchError: Error | null) => { console.log(dispatchError); resolve(dispatchError === null); });
+ smtpTransport.sendMail(mailOptions, (dispatchError: Error | null) => resolve(dispatchError === null));
});
}
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
new file mode 100644
index 000000000..32b7810ea
--- /dev/null
+++ b/src/server/daemon/session_crashes_@ 2019-12-11T08:31:56.281Z.log
@@ -0,0 +1 @@
+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
new file mode 100644
index 000000000..ebb6843c2
--- /dev/null
+++ b/src/server/daemon/session_crashes_@ 2019-12-11T08:43:46.454Z.log
@@ -0,0 +1,2 @@
+Detected a server crash @ 2019-12-11T08:44:26.494Z.
+Backup server successfully restarted @ 2019-12-11T08:45:33.644Z.