1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
|
import { Session } from "./Session/session";
import { Email } from "./ActionUtilities";
import { red, yellow, green } from "colors";
import { get } from "request-promise";
import { Utils } from "../Utils";
import { WebSocket } from "./Websocket/Websocket";
import { MessageStore } from "./Message";
import { launchServer, onWindows } from ".";
/**
* If we're the monitor (master) thread, we should launch the monitor logic for the session.
* Otherwise, we must be on a worker thread that was spawned *by* the monitor (master) thread, and thus
* our job should be to run the server.
*/
export class DashSessionAgent extends Session.AppliedSessionAgent {
private readonly notificationRecipients = ["samuel_wilkins@brown.edu"];
private readonly signature = "-Dash Server Session Manager";
protected async launchMonitor() {
const monitor = Session.Monitor.Create({
key: async key => {
// this sends a pseudorandomly generated guid to the configuration's recipients, allowing them alone
// to kill the server via the /kill/:key route
const content = `The key for this session (started @ ${new Date().toUTCString()}) is ${key}.\n\n${this.signature}`;
const failures = await Email.dispatchAll(this.notificationRecipients, "Server Termination Key", content);
if (failures) {
failures.map(({ recipient, error: { message } }) => monitor.mainLog(red(`dispatch failure @ ${recipient} (${yellow(message)})`)));
return false;
}
return true;
},
crash: async ({ name, message, stack }) => {
const body = [
"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.",
].join("\n\n");
const content = `${body}\n\n${this.signature}`;
const failures = await Email.dispatchAll(this.notificationRecipients, "Dash Web Server Crash", content);
if (failures) {
failures.map(({ recipient, error: { message } }) => monitor.mainLog(red(`dispatch failure @ ${recipient} (${yellow(message)})`)));
return false;
}
return true;
}
});
monitor.addReplCommand("pull", [], () => monitor.exec("git pull"));
monitor.addReplCommand("solr", [/start|stop/], async args => {
const command = `${onWindows ? "solr.cmd" : "solr"} ${args[0] === "start" ? "start" : "stop -p 8983"}`;
await monitor.exec(command, { cwd: "./solr-8.3.1/bin" });
try {
await get("http://localhost:8983");
monitor.mainLog(green("successfully connected to 8983 after running solr initialization"));
} catch {
monitor.mainLog(red("unable to connect at 8983 after running solr initialization"));
}
});
return monitor;
}
protected async launchServerWorker() {
const worker = Session.ServerWorker.Create(launchServer); // server initialization delegated to worker
worker.addExitHandler(reason => {
const { _socket } = WebSocket;
if (_socket) {
const message = typeof reason === "boolean" ? (reason ? "exit" : "temporary") : "crash";
Utils.Emit(_socket, MessageStore.ConnectionTerminated, message);
}
});
return worker;
}
}
|