From a3fc1dda8cdd44b2fac87ebad17e1bd973a3f596 Mon Sep 17 00:00:00 2001 From: Hornwitser Date: Sat, 3 Aug 2019 12:14:04 +0200 Subject: [PATCH] Refactor master.js Move server initialization code to startServer and call it only when master.js is being runned directly. Also refactor the server listen step to work properly when https is configured and only listen after plugins have completed loading. Remove the async function wrapper around the master.js code. This is just dumb and makes the code untestable. --- master.js | 128 ++++++++++++++++++++++++++++++------------------------ 1 file changed, 71 insertions(+), 57 deletions(-) diff --git a/master.js b/master.js index 38463281..e0a16dad 100644 --- a/master.js +++ b/master.js @@ -14,15 +14,6 @@ node master.js // const updater = require("./updater.js"); // updater.update().then(console.log); -(async ()=>{ - -// Set the process title, shows up as the title of the CMD window on windows -// and as the process name in ps/top on linux. -process.title = "clusterioMaster"; - -// add better stack traces on promise rejection -process.on('unhandledRejection', r => console.log(r)); - // configgy stuff debug = false; @@ -55,24 +46,6 @@ const getFactorioLocale = require("lib/getFactorioLocale"); // homemade express middleware for token auth const authenticate = require("lib/authenticate")(config); -/** Sync */ -function randomStringAsBase64Url(size) { - return base64url(crypto.randomBytes(size)); -} -if (!fs.existsSync("secret-api-token.txt")) { - config.masterAuthSecret = randomStringAsBase64Url(256); - fs.writeFileSync("config.json",JSON.stringify(config, null, 4)); - fs.writeFileSync("secret-api-token.txt", jwt.sign({ id: "api" }, config.masterAuthSecret, { - expiresIn: 86400*365 // expires in 1 year - })); - console.log("Generated new master authentication private key!"); - process.exit(0); -} -// write an auth token to file -fs.writeFileSync("secret-api-token.txt", jwt.sign({ id: "api" }, config.masterAuthSecret, { - expiresIn: 86400*365 // expires in 1 year -})); - const express = require("express"); const compression = require('compression'); const cookieParser = require('cookie-parser'); @@ -174,9 +147,6 @@ const prometheusMasterInventoryGauge = new Prometheus.Gauge({ help: 'Amount of items stored on master', labelNames: ["itemName"], }); -setInterval(()=>{ - fs.writeFileSync("database/items.json", JSON.stringify(db.items)); -},config.autosaveInterval || 60000); /** GET Prometheus metrics endpoint. Returns performance and usage metrics in a prometheus readable format. @memberof clusterioMaster @@ -266,8 +236,6 @@ db.items.removeItem = function(object) { }; // store slaves and inventory in a .json full of JSON data -process.on('SIGINT', shutdown); // ctrl + c -process.on('SIGHUP', shutdown); // terminal closed async function shutdown() { console.log('Ctrl-C...'); let exitStartTime = Date.now(); @@ -764,28 +732,9 @@ app.get("/api/getFactorioLocale", function(req,res){ res.send(factorioLocale); }); }); -if(args.sslPort || config.sslPort){ - try{ - var certificate = fs.readFileSync(path.resolve(config.databaseDirectory, 'certificates/cert.crt')); - var privateKey = fs.readFileSync(path.resolve(config.databaseDirectory, 'certificates/cert.key')); - - httpsServer = require("https").createServer({ - key: privateKey, - cert: certificate - }, app).listen(args.sslPort || config.sslPort); - } catch(e){ - console.error(e) - } -} -if(args.masterPort || config.masterPort){ - server = require("http").Server(app); - server.listen(args.masterPort || config.masterPort || 8080, function () { - console.log("Listening on port %s...", server.address().port); - }); -} /* Websockets for remoteMap */ -var io = require("socket.io")(); +var io = require("socket.io")({}); const ioMetrics = require("socket.io-prometheus"); ioMetrics(io); @@ -975,8 +924,14 @@ io.on('connection', function (socket) { }); // handle plugins on the master -async function getPlugins(){ +var masterPlugins = []; +async function pluginManagement(){ let startPluginLoad = Date.now(); + masterPlugins = await getPlugins(); + console.log("All plugins loaded in "+(Date.now() - startPluginLoad)+"ms"); +} + +async function getPlugins(){ const pluginManager = require("lib/manager/pluginManager.js")(config); let plugins = []; let pluginsToLoad = await pluginManager.getPlugins(); @@ -1007,15 +962,74 @@ async function getPlugins(){ let plugin = plugins[i]; if(plugin.main.onLoadFinish && typeof plugin.main.onLoadFinish == "function") await plugin.main.onLoadFinish({plugins}); } - console.log("All plugins loaded in "+(Date.now() - startPluginLoad)+"ms"); return plugins; } +async function startServer() { + // Set the process title, shows up as the title of the CMD window on windows + // and as the process name in ps/top on linux. + process.title = "clusterioMaster"; -var masterPlugins = await getPlugins(); + // add better stack traces on promise rejection + process.on('unhandledRejection', r => console.log(r)); + /** Sync */ + function randomStringAsBase64Url(size) { + return base64url(crypto.randomBytes(size)); + } -io.attach(server); + if (!fs.existsSync("secret-api-token.txt")) { + config.masterAuthSecret = randomStringAsBase64Url(256); + fs.writeFileSync("config.json",JSON.stringify(config, null, 4)); + fs.writeFileSync("secret-api-token.txt", jwt.sign({ id: "api" }, config.masterAuthSecret, { + expiresIn: 86400*365 // expires in 1 year + })); + console.log("Generated new master authentication private key!"); + process.exit(0); + } + // write an auth token to file + fs.writeFileSync("secret-api-token.txt", jwt.sign({ id: "api" }, config.masterAuthSecret, { + expiresIn: 86400*365 // expires in 1 year + })); + setInterval(()=>{ + fs.writeFileSync("database/items.json", JSON.stringify(db.items)); + },config.autosaveInterval || 60000); + process.on('SIGINT', shutdown); // ctrl + c + process.on('SIGHUP', shutdown); // terminal closed + + // Make sure we're actually going to listen on a port + let httpPort = args.masterPort || config.masterPort; + let httpsPort = args.sslPort || config.sslPort; + if (!httpPort && !httpsPort) { + console.error("Error: at least one of httpPort and sslPort must be configured"); + process.exit(1); + } + + // Load plugins + await pluginManagement(); + + // Only start listening for connections after all plugins have loaded + if (httpPort) { + let httpServer = require("http").Server(app); + httpServer.listen(httpPort); + console.log("Listening for HTTP on port %s...", httpServer.address().port); + } + + if (httpsPort) { + var certificate = fs.readFileSync(path.resolve(config.databaseDirectory, 'certificates/cert.crt')); + var privateKey = fs.readFileSync(path.resolve(config.databaseDirectory, 'certificates/cert.key')); + + let httpsServer = require("https").createServer({ + key: privateKey, + cert: certificate + }, app) + httpsServer.listen(httpsPort); + console.log("Listening for HTTPS on port %s...", httpsServer.address().port); + } +} module.exports = app; -})(); + +if (module === require.main) { + startServer(); +}