aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/client/DocServer.ts1
-rw-r--r--src/client/util/ClientDiagnostics.ts34
-rw-r--r--src/client/util/TooltipTextMenu.tsx2
-rw-r--r--src/client/views/Main.tsx2
-rw-r--r--src/server/ActionUtilities.ts8
-rw-r--r--src/server/ApiManagers/DiagnosticManager.ts30
-rw-r--r--src/server/ApiManagers/SearchManager.ts49
-rw-r--r--src/server/Message.ts1
-rw-r--r--src/server/Websocket/Websocket.ts4
-rw-r--r--src/server/index.ts41
10 files changed, 96 insertions, 76 deletions
diff --git a/src/client/DocServer.ts b/src/client/DocServer.ts
index e4b183715..befe9ea5c 100644
--- a/src/client/DocServer.ts
+++ b/src/client/DocServer.ts
@@ -82,6 +82,7 @@ export namespace DocServer {
Utils.AddServerHandler(_socket, MessageStore.UpdateField, respondToUpdate);
Utils.AddServerHandler(_socket, MessageStore.DeleteField, respondToDelete);
Utils.AddServerHandler(_socket, MessageStore.DeleteFields, respondToDelete);
+ _socket.on("connection_terminated", () => alert("Your connection to the server has been terminated."));
}
function errorFunc(): never {
diff --git a/src/client/util/ClientDiagnostics.ts b/src/client/util/ClientDiagnostics.ts
deleted file mode 100644
index 0a213aa1c..000000000
--- a/src/client/util/ClientDiagnostics.ts
+++ /dev/null
@@ -1,34 +0,0 @@
-export namespace ClientDiagnostics {
-
- export async function start() {
-
- let serverPolls = 0;
- const serverHandle = setInterval(async () => {
- if (++serverPolls === 20) {
- alert("Your connection to the server has been terminated.");
- clearInterval(serverHandle);
- }
- await fetch("/serverHeartbeat");
- serverPolls--;
- }, 1000 * 15);
-
- let executed = false;
- let solrHandle: NodeJS.Timeout | undefined;
- const handler = async () => {
- const response = await fetch("/solrHeartbeat");
- if (!(await response.json()).running) {
- if (!executed) {
- alert("Looks like SOLR is not running on your machine.");
- executed = true;
- solrHandle && clearInterval(solrHandle);
- }
- }
- };
- await handler();
- if (!executed) {
- solrHandle = setInterval(handler, 1000 * 15);
- }
-
- }
-
-} \ No newline at end of file
diff --git a/src/client/util/TooltipTextMenu.tsx b/src/client/util/TooltipTextMenu.tsx
index 89037dcb2..01d566831 100644
--- a/src/client/util/TooltipTextMenu.tsx
+++ b/src/client/util/TooltipTextMenu.tsx
@@ -1030,7 +1030,7 @@ export class TooltipTextMenu {
TooltipTextMenuManager.Instance._brushMarks && TooltipTextMenuManager.Instance._brushMap.set(input.value, TooltipTextMenuManager.Instance._brushMarks);
input.style.background = "lightGray";
}
- }
+ };
const wrapper = document.createElement("div");
wrapper.appendChild(input);
diff --git a/src/client/views/Main.tsx b/src/client/views/Main.tsx
index 9e699978f..b21eb9c8f 100644
--- a/src/client/views/Main.tsx
+++ b/src/client/views/Main.tsx
@@ -5,12 +5,10 @@ import * as ReactDOM from 'react-dom';
import * as React from 'react';
import { DocServer } from "../DocServer";
import { AssignAllExtensions } from "../../extensions/General/Extensions";
-import { ClientDiagnostics } from "../util/ClientDiagnostics";
AssignAllExtensions();
(async () => {
- await ClientDiagnostics.start();
const info = await CurrentUserUtils.loadCurrentUser();
DocServer.init(window.location.protocol, window.location.hostname, 4321, info.email);
await Docs.Prototypes.initialize();
diff --git a/src/server/ActionUtilities.ts b/src/server/ActionUtilities.ts
index 4fe7374d1..1ebeab203 100644
--- a/src/server/ActionUtilities.ts
+++ b/src/server/ActionUtilities.ts
@@ -9,21 +9,21 @@ export const command_line = (command: string, fromDirectory?: string) => {
return new Promise<string>((resolve, reject) => {
const options: ExecOptions = {};
if (fromDirectory) {
- options.cwd = path.join(__dirname, fromDirectory);
+ options.cwd = path.resolve(__dirname, fromDirectory);
}
exec(command, options, (err, stdout) => err ? reject(err) : resolve(stdout));
});
};
export const read_text_file = (relativePath: string) => {
- const target = path.join(__dirname, relativePath);
+ const target = path.resolve(__dirname, relativePath);
return new Promise<string>((resolve, reject) => {
fs.readFile(target, (err, data) => err ? reject(err) : resolve(data.toString()));
});
};
export const write_text_file = (relativePath: string, contents: any) => {
- const target = path.join(__dirname, relativePath);
+ const target = path.resolve(__dirname, relativePath);
return new Promise<void>((resolve, reject) => {
fs.writeFile(target, contents, (err) => err ? reject(err) : resolve());
});
@@ -75,5 +75,5 @@ export async function Prune(rootDirectory: string): Promise<boolean> {
export const Destroy = (mediaPath: string) => new Promise<boolean>(resolve => fs.unlink(mediaPath, error => resolve(error === null)));
export function addBeforeExitHandler(handler: NodeJS.BeforeExitListener) {
- process.on("beforeExit", handler);
+ // process.on("beforeExit", handler);
}
diff --git a/src/server/ApiManagers/DiagnosticManager.ts b/src/server/ApiManagers/DiagnosticManager.ts
deleted file mode 100644
index 104985481..000000000
--- a/src/server/ApiManagers/DiagnosticManager.ts
+++ /dev/null
@@ -1,30 +0,0 @@
-import ApiManager, { Registration } from "./ApiManager";
-import { Method } from "../RouteManager";
-import request = require('request-promise');
-
-export default class DiagnosticManager extends ApiManager {
-
- protected initialize(register: Registration): void {
-
- register({
- method: Method.GET,
- subscription: "/serverHeartbeat",
- onValidation: ({ res }) => res.send(true)
- });
-
- register({
- method: Method.GET,
- subscription: "/solrHeartbeat",
- onValidation: async ({ res }) => {
- try {
- await request("http://localhost:8983");
- res.send({ running: true });
- } catch (e) {
- res.send({ running: false });
- }
- }
- });
-
- }
-
-} \ No newline at end of file
diff --git a/src/server/ApiManagers/SearchManager.ts b/src/server/ApiManagers/SearchManager.ts
index 7afecbb18..0e794fed6 100644
--- a/src/server/ApiManagers/SearchManager.ts
+++ b/src/server/ApiManagers/SearchManager.ts
@@ -4,13 +4,28 @@ import { Search } from "../Search";
const findInFiles = require('find-in-files');
import * as path from 'path';
import { pathToDirectory, Directory } from "./UploadManager";
+import { command_line, addBeforeExitHandler } from "../ActionUtilities";
+import request = require('request-promise');
+import { red, green, yellow, cyan } from "colors";
-export default class SearchManager extends ApiManager {
+export class SearchManager extends ApiManager {
protected initialize(register: Registration): void {
register({
method: Method.GET,
+ subscription: "/startSolr",
+ onValidation: async ({ res }) => res.send((await SolrManager.SetRunning(true)) ? "Successfully started Solr!" : "Uh oh! Check the console for the error that occurred while starting Solr")
+ });
+
+ register({
+ method: Method.GET,
+ subscription: "/stopSolr",
+ onValidation: async ({ res }) => res.send((await SolrManager.SetRunning(false)) ? "Successfully stopped Solr!" : "Uh oh! Check the console for the error that occurred while stopping Solr")
+ });
+
+ register({
+ method: Method.GET,
subscription: "/textsearch",
onValidation: async ({ req, res }) => {
const q = req.query.q;
@@ -46,4 +61,36 @@ export default class SearchManager extends ApiManager {
}
+}
+
+export namespace SolrManager {
+
+ export async function initializeSolr() {
+ console.log(cyan("\nInspecting Solr status..."));
+ try {
+ await request("http://localhost:8983");
+ console.log(green('Solr already running\n'));
+ } catch (e) {
+ console.log(cyan('Initializing Solr...'));
+ await SolrManager.SetRunning(true);
+ } finally {
+ addBeforeExitHandler(async () => SolrManager.SetRunning(false));
+ }
+ }
+
+ export async function SetRunning(status: boolean): Promise<boolean> {
+ const args = status ? "start" : "stop -p 8983";
+ console.log(`Solr management: trying to ${args}`);
+ try {
+ console.log(await command_line(`solr.cmd ${args}`, "../../solr-8.1.1/bin"));
+ return true;
+ } catch (e) {
+ console.log(red(`Solr management error: unable to ${args}`));
+ if (status) {
+ process.exit(0);
+ }
+ return false;
+ }
+ }
+
} \ No newline at end of file
diff --git a/src/server/Message.ts b/src/server/Message.ts
index aaee143e8..621abfd1e 100644
--- a/src/server/Message.ts
+++ b/src/server/Message.ts
@@ -50,6 +50,7 @@ export namespace MessageStore {
export const GetFields = new Message<string[]>("Get Fields"); // send string[] of 'id' get Transferable[] back
export const GetDocument = new Message<string>("Get Document");
export const DeleteAll = new Message<any>("Delete All");
+ export const ConnectionTerminated = new Message<string>("Connection Terminated");
export const GetRefField = new Message<string>("Get Ref Field");
export const GetRefFields = new Message<string[]>("Get Ref Fields");
diff --git a/src/server/Websocket/Websocket.ts b/src/server/Websocket/Websocket.ts
index 60c34aa44..de1d5eb25 100644
--- a/src/server/Websocket/Websocket.ts
+++ b/src/server/Websocket/Websocket.ts
@@ -10,6 +10,7 @@ import { GoogleCredentialsLoader } from "../credentials/CredentialsLoader";
import { logPort, addBeforeExitHandler } from "../ActionUtilities";
import { timeMap } from "../ApiManagers/UserManager";
import { green } from "colors";
+import { ExitHandlers } from "..";
export namespace WebSocket {
@@ -52,8 +53,9 @@ export namespace WebSocket {
Utils.AddServerHandler(socket, MessageStore.DeleteFields, ids => DeleteFields(socket, ids));
Utils.AddServerHandlerCallback(socket, MessageStore.GetRefField, GetRefField);
Utils.AddServerHandlerCallback(socket, MessageStore.GetRefFields, GetRefFields);
+
+ ExitHandlers.push(() => socket.broadcast.emit("connection_terminated", Date.now()));
});
- addBeforeExitHandler(async () => { await new Promise<void>(resolve => endpoint.close(resolve)); });
endpoint.listen(socketPort);
logPort("websocket", socketPort);
}
diff --git a/src/server/index.ts b/src/server/index.ts
index 551ce3898..42b4f7ff2 100644
--- a/src/server/index.ts
+++ b/src/server/index.ts
@@ -10,7 +10,7 @@ import initializeServer from './Initialization';
import RouteManager, { Method, _success, _permission_denied, _error, _invalid, OnUnauthenticated } from './RouteManager';
import * as qs from 'query-string';
import UtilManager from './ApiManagers/UtilManager';
-import SearchManager from './ApiManagers/SearchManager';
+import { SearchManager, SolrManager } from './ApiManagers/SearchManager';
import UserManager from './ApiManagers/UserManager';
import { WebSocket } from './Websocket/Websocket';
import DownloadManager from './ApiManagers/DownloadManager';
@@ -21,18 +21,48 @@ import UploadManager from "./ApiManagers/UploadManager";
import { log_execution } from "./ActionUtilities";
import GeneralGoogleManager from "./ApiManagers/GeneralGoogleManager";
import GooglePhotosManager from "./ApiManagers/GooglePhotosManager";
-import DiagnosticManager from "./ApiManagers/DiagnosticManager";
import { yellow } from "colors";
export const publicDirectory = path.resolve(__dirname, "public");
export const filesDirectory = path.resolve(publicDirectory, "files");
+export const ExitHandlers = new Array<() => void>();
+
/**
* These are the functions run before the server starts
* listening. Anything that must be complete
* before clients can access the server should be run or awaited here.
*/
async function preliminaryFunctions() {
+ process.on('SIGINT', () => {
+ const { stdin, stdout, stderr } = process;
+ stdin.resume();
+ stdout.resume();
+ stderr.resume();
+ ExitHandlers.forEach(handler => handler());
+ console.log("Okay, now we're done...");
+ // process.exit(0);
+ });
+
+ (process as any).on('cleanup', () => {
+ console.log("CLEANING UP!");
+ });
+
+ process.on('exit', function () {
+ (process.emit as Function)('cleanup');
+ });
+
+ //catch uncaught exceptions, trace, then exit normally
+ process.on('uncaughtException', function (e) {
+ console.log('Uncaught Exception...');
+ process.exit(99);
+ });
+ process.on('unhandledRejection', function (e) {
+ console.log('Unhandled Rejection...');
+ process.exit(99);
+ });
+
+ await SolrManager.initializeSolr();
await GoogleCredentialsLoader.loadCredentials();
GoogleApiServerUtils.processProjectCredentials();
await DashUploadUtils.buildFileDirectories();
@@ -57,7 +87,6 @@ function routeSetter({ isRelease, addSupervisedRoute, logRegistrationOutcome }:
new UserManager(),
new UploadManager(),
new DownloadManager(),
- new DiagnosticManager(),
new SearchManager(),
new PDFManager(),
new DeleteManager(),
@@ -79,6 +108,12 @@ function routeSetter({ isRelease, addSupervisedRoute, logRegistrationOutcome }:
onValidation: ({ res }) => res.redirect("/home")
});
+ addSupervisedRoute({
+ method: Method.GET,
+ subscription: "/serverHeartbeat",
+ onValidation: ({ res }) => res.send(true)
+ });
+
const serve: OnUnauthenticated = ({ req, res }) => {
const detector = new mobileDetect(req.headers['user-agent'] || "");
const filename = detector.mobile() !== null ? 'mobile/image.html' : 'index.html';