Convert app-start/-stop callbacks to async/await (#3035)

supersedes https://github.com/MichMich/MagicMirror/pull/3027 and just
touches the start/stop calls.

---------

Co-authored-by: veeck <michael@veeck.de>
This commit is contained in:
Veeck
2023-02-22 18:58:00 +01:00
committed by GitHub
parent 2b792cdbb8
commit fe0b915a5d
5 changed files with 90 additions and 70 deletions

130
js/app.js
View File

@@ -53,6 +53,9 @@ function App() {
/**
* Loads the config file. Combines it with the defaults and returns the config
*
* @async
* @returns {Promise<object>} the loaded config or the defaults if something goes wrong
*/
async function loadConfig() {
Log.log("Loading config ...");
@@ -115,8 +118,7 @@ function App() {
fs.accessSync(configFilename, fs.F_OK);
const c = require(configFilename);
checkDeprecatedOptions(c);
const config = Object.assign(defaults, c);
return config;
return Object.assign(defaults, c);
} catch (e) {
if (e.code === "ENOENT") {
Log.error(Utils.colors.error("WARNING! Could not find config file. Please create one. Starting with default configuration."));
@@ -125,8 +127,9 @@ function App() {
} else {
Log.error(Utils.colors.error(`WARNING! Could not load config file. Starting with default configuration. Error found: ${e}`));
}
return defaults;
}
return defaults;
}
/**
@@ -258,59 +261,55 @@ function App() {
/**
* Start the core app.
*
* It loads the config, then it loads all modules. When it's done it
* executes the callback with the config as argument.
* It loads the config, then it loads all modules.
*
* @param {Function} callback Function to be called after start
* @async
* @returns {Promise<object>} the config used
*/
this.start = function (callback) {
loadConfig().then((c) => {
config = c;
this.start = async function () {
config = await loadConfig();
Log.setLogLevel(config.logLevel);
Log.setLogLevel(config.logLevel);
let modules = [];
let modules = [];
for (const module of config.modules) {
if (!modules.includes(module.module) && !module.disabled) {
modules.push(module.module);
for (const module of config.modules) {
if (!modules.includes(module.module) && !module.disabled) {
modules.push(module.module);
}
}
loadModules(modules, async function () {
httpServer = new Server(config);
const { app, io } = await httpServer.open();
Log.log("Server started ...");
const nodePromises = [];
for (let nodeHelper of nodeHelpers) {
nodeHelper.setExpressApp(app);
nodeHelper.setSocketIO(io);
try {
nodePromises.push(nodeHelper.start());
} catch (error) {
Log.error(`Error when starting node_helper for module ${nodeHelper.name}:`);
Log.error(error);
}
}
loadModules(modules, async function () {
httpServer = new Server(config);
const { app, io } = await httpServer.open();
Log.log("Server started ...");
const results = await Promise.allSettled(nodePromises);
const nodePromises = [];
for (let nodeHelper of nodeHelpers) {
nodeHelper.setExpressApp(app);
nodeHelper.setSocketIO(io);
try {
nodePromises.push(nodeHelper.start());
} catch (error) {
Log.error(`Error when starting node_helper for module ${nodeHelper.name}:`);
Log.error(error);
}
// Log errors that happened during async node_helper startup
results.forEach((result) => {
if (result.status === "rejected") {
Log.error(result.reason);
}
Promise.allSettled(nodePromises).then((results) => {
// Log errors that happened during async node_helper startup
results.forEach((result) => {
if (result.status === "rejected") {
Log.error(result.reason);
}
});
Log.log("Sockets connected & modules started ...");
});
});
if (typeof callback === "function") {
callback(config);
}
Log.log("Sockets connected & modules started ...");
});
return config;
};
/**
@@ -319,15 +318,40 @@ function App() {
*
* Added to fix #1056
*
* @param {Function} callback Function to be called after the app has stopped
* @returns {Promise} A promise that is resolved when all node_helpers and
* the http server has been closed
*/
this.stop = function (callback) {
for (const nodeHelper of nodeHelpers) {
if (typeof nodeHelper.stop === "function") {
nodeHelper.stop();
this.stop = async function () {
const nodePromises = [];
for (let nodeHelper of nodeHelpers) {
try {
if (typeof nodeHelper.stop === "function") {
nodePromises.push(nodeHelper.stop());
}
} catch (error) {
Log.error(`Error when stopping node_helper for module ${nodeHelper.name}:`);
console.error(error);
}
}
httpServer.close().then(callback);
const results = await Promise.allSettled(nodePromises);
// Log errors that happened during async node_helper stopping
results.forEach((result) => {
if (result.status === "rejected") {
Log.error(result.reason);
}
});
Log.log("Node_helpers stopped ...");
// To be able to stop the app even if it hasn't been started (when
// running with Electron against another server)
if (!httpServer) {
return Promise.resolve();
}
return httpServer.close();
};
/**
@@ -337,12 +361,12 @@ function App() {
* Note: this is only used if running `server-only`. Otherwise
* this.stop() is called by app.on("before-quit"... in `electron.js`
*/
process.on("SIGINT", () => {
process.on("SIGINT", async () => {
Log.log("[SIGINT] Received. Shutting down server...");
setTimeout(() => {
process.exit(0);
}, 3000); // Force quit after 3 seconds
this.stop();
await this.stop();
process.exit(0);
});
@@ -350,12 +374,12 @@ function App() {
* Listen to SIGTERM signals so we can stop everything when we
* are asked to stop by the OS.
*/
process.on("SIGTERM", () => {
process.on("SIGTERM", async () => {
Log.log("[SIGTERM] Received. Shutting down server...");
setTimeout(() => {
process.exit(0);
}, 3000); // Force quit after 3 seconds
this.stop();
await this.stop();
process.exit(0);
});
}