From de0da04e7b792371ede393623aaefcefa02d38c4 Mon Sep 17 00:00:00 2001 From: Joe Uhren Date: Sat, 27 May 2023 21:45:03 -0600 Subject: [PATCH] Added better support for NODE_ENV -The different methods of starting the explorer now set NODE_ENV to "development" or "production" depending on which options were chosen -pm2 is now loaded from within the prestart script and will reload the config instead of starting if it was previously loaded which allows changing the NODE_ENV value if necessary NOTE: if running via pm2 or forever when updating the explorer with this change, it is necessary to manually stop the explorer with `npm run stop-pm2` or `npm run stop-forever` and then start again after the code has been updated to allow NODE_ENV to be set to "production". Without doing this, the explorer will still be run in "development" mode until pm2 or forever is fully stopped and restarted. --- app.js | 17 ++-------- package.json | 6 ++-- scripts/prestart.js | 76 ++++++++++++++++++++++++++++++++------------- 3 files changed, 60 insertions(+), 39 deletions(-) diff --git a/app.js b/app.js index b7868f56..51521aeb 100644 --- a/app.js +++ b/app.js @@ -860,25 +860,12 @@ app.use(function(req, res, next) { next(err); }); -// development error handler -// will print stacktrace -if (app.get('env') === 'development') { - app.use(function(err, req, res, next) { - res.status(err.status || 500); - res.render('error', { - message: err.message, - error: err - }); - }); -} - -// production error handler -// no stacktraces leaked to user +// error handler - will print stacktrace when in development mode, otherwise no stacktraces will be leaked to the user app.use(function(err, req, res, next) { res.status(err.status || 500); res.render('error', { message: err.message, - error: {} + error: (app.get('env') === 'development' ? err : {}) }); }); diff --git a/package.json b/package.json index d020914a..5261a3d2 100644 --- a/package.json +++ b/package.json @@ -6,11 +6,11 @@ "start": "node --stack-size=10000 ./bin/cluster", "stop": "node ./scripts/stop_explorer.js", "start-instance": "npm run prestart && node --stack-size=10000 ./bin/cluster 1", - "start-forever": "npm run prestart \"forever\"", + "start-forever": "npm run prestart \"forever production\"", "stop-forever": "forever stop \"explorer\"", "reload-forever": "forever restart \"explorer\"", - "start-pm2": "npm run prestart \"pm2\" && pm2 start ./bin/instance -i 0 -n explorer -p \"./tmp/pm2.pid\" --node-args=\"--stack-size=10000\"", - "start-pm2-debug": "npm run prestart \"pm2\" && pm2 start ./bin/instance -i 0 -n explorer -p \"./tmp/pm2.pid\" --node-args=\"--stack-size=10000\" && pm2 logs", + "start-pm2": "npm run prestart \"pm2 production\"", + "start-pm2-debug": "npm run prestart \"pm2 development\" && pm2 logs", "stop-pm2": "pm2 stop explorer", "reload-pm2": "pm2 reload explorer", "test": "node ./node_modules/jasmine/bin/jasmine.js test/*Spec.js", diff --git a/scripts/prestart.js b/scripts/prestart.js index 3b5cc3da..1953cba7 100644 --- a/scripts/prestart.js +++ b/scripts/prestart.js @@ -32,15 +32,17 @@ if (!(nodeVersionMajor > minNodeVersionMajor || (nodeVersionMajor == minNodeVers process.exit(0); } -function check_argument_passed(cb) { - const pidName = (process.argv[2] != null && process.argv[2] != '' && (process.argv[2] == 'pm2' || process.argv[2] == 'forever') ? process.argv[2] : 'node'); +function check_arguments_passed(cb) { + const arguments = (process.argv[2] == null ? '' : process.argv[2]).split(' '); + const pidName = (arguments != null && arguments.length > 0 && arguments[0] != null && arguments[0] != '' && (arguments[0] == 'pm2' || arguments[0] == 'forever') ? arguments[0] : 'node'); + const node_env = (arguments != null && arguments.length > 0 && arguments[1] != null && arguments[1] != '' ? arguments[1] : 'development'); // check 1st argument - if (process.argv[2] != null) { + if (pidName != null) { const { exec } = require('child_process'); // determine which argument was passed - switch (process.argv[2]) { + switch (pidName) { case 'pm2': // windows pm2 has problem loading locally, but other os's should work fine const isWinOS = process.platform == 'win32'; @@ -56,11 +58,11 @@ function check_argument_passed(cb) { // install pm2 exec(`npm install pm2@latest${(isWinOS ? ' -g' : '')}`, (err, stdout, stderr) => { - // always return the pidName for now without checking results - return cb(pidName); + // always return the pidName and node_env value for now without checking results + return cb(pidName, node_env); }); } else - return cb(pidName); + return cb(pidName, node_env); }); break; case 'forever': @@ -75,36 +77,68 @@ function check_argument_passed(cb) { // install forever exec('npm install forever', (err, stdout, stderr) => { - // always return the pidName for now without checking results - return cb(pidName); + // always return the pidName and node_env value for now without checking results + return cb(pidName, node_env); }); } else - return cb(pidName); + return cb(pidName, node_env); }); break; default: // argument not passed or unknown argument - return cb(pidName); + return cb(pidName, node_env); } } else - return cb(pidName); + return cb(pidName, node_env); } -// check if an argument was passed into this script -check_argument_passed(function(pidName) { +// check if arguments were passed into this script +check_arguments_passed(function(pidName, node_env) { const execSync = require('child_process').execSync; // compile scss to css execSync('node ./scripts/compile_css.js', {stdio : 'inherit'}); // check if the webserver should be started from here based on the pidName - if (pidName == 'forever') { - const path = require('path'); - - // there is a long-time bug or shortcoming in forever that still exists in the latest version which requires the absolute path to the pid file option - // more info: https://github.com/foreversd/forever/issues/421 - // forever is therefore started from here to be able to more easily resolve the absolute path - execSync(`forever start --append --uid "explorer" --pidFile "${path.resolve('./tmp/forever.pid')}" ./bin/cluster`, {stdio : 'inherit'}); + switch (pidName) { + case 'pm2': + let startOrReload = 'start'; + + // get a json list of pm2 processes + let result = execSync(`pm2 jlist`); + + // check if the result is null + if (result != null) { + try { + // convert return result to JSON + result = JSON.parse(result); + + // loop through the results + for (let i = 0; i < result.length; i++) { + // check if this is an explorer process + if (result[i].name == 'explorer') { + // explorer process exists, so reload the process + startOrReload = 'reload'; + break; + } + } + } catch(e) { + // do nothing + } + } + + // Setting the NODE_ENV variable is more easily done from here seeing at the syntax changes slightly depending on operating system + execSync(`${(process.platform == 'win32' ? 'set' : 'export')} NODE_ENV=${node_env} && pm2 ${startOrReload} ./bin/instance -i 0 -n explorer -p "./tmp/pm2.pid" --node-args="--stack-size=10000" --update-env`, {stdio : 'inherit'}); + break; + case 'forever': + const path = require('path'); + + // there is a long-time bug or shortcoming in forever that still exists in the latest version which requires the absolute path to the pid file option + // more info: https://github.com/foreversd/forever/issues/421 + // forever is therefore started from here to be able to more easily resolve the absolute path + // also, setting the NODE_ENV variable is more easily done from here as well seeing at the syntax changes slightly depending on operating system + execSync(`${(process.platform == 'win32' ? 'set' : 'export')} NODE_ENV=${node_env} && forever start --append --uid "explorer" --pidFile "${path.resolve('./tmp/forever.pid')}" ./bin/cluster`, {stdio : 'inherit'}); + break; } // finished pre-loading