From c8b9b58373464e5dd37f3ea2733fcdd57f796b4e Mon Sep 17 00:00:00 2001 From: Nuno Guedelha Date: Tue, 26 Oct 2021 14:01:13 +0200 Subject: [PATCH 1/2] Close Telemetry Server: subset B - Stop listening to client requests - Convert 'handleTermination()' into a class for a better handling of the multiple Promise/Resolve cycles. - Create class 'TerminationHandler': main method 'HandleTermination.run()' starts the termination. - Former function 'handleTermination' body now defines 'HandleTermination.runSubsetA()'. - Define 'WebsocketTracker.pauseAll()' which pauses all the open sockets. - Use it for the server closure step B. --- common/websocket-tracker.js | 6 +++ iCubTelemVizServer/iCubTelemVizServer.js | 61 +++++++++++++++++------- 2 files changed, 50 insertions(+), 17 deletions(-) diff --git a/common/websocket-tracker.js b/common/websocket-tracker.js index 1aba8d4..01eb586 100644 --- a/common/websocket-tracker.js +++ b/common/websocket-tracker.js @@ -17,6 +17,12 @@ WebsocketTracker.prototype.closeAll = function() { }); } +WebsocketTracker.prototype.pauseAll = function() { + this.sockets.forEach((value,key) => { + key.pause(); + }); +} + module.exports = function (server) { return new WebsocketTracker(server); } diff --git a/iCubTelemVizServer/iCubTelemVizServer.js b/iCubTelemVizServer/iCubTelemVizServer.js index ce4e752..af708ca 100644 --- a/iCubTelemVizServer/iCubTelemVizServer.js +++ b/iCubTelemVizServer/iCubTelemVizServer.js @@ -4,9 +4,9 @@ // When the signal comes from the terminal, the generated event doesn't have a 'signal' parameter, // so it appears undefined in the callback body. We worked around this issue by explicitly setting // the 'signal' parameter case by case. -process.once('SIGQUIT', () => {handleTermination('SIGQUIT');}); -process.once('SIGTERM', () => {handleTermination('SIGTERM');}); -process.once('SIGINT', () => {handleTermination('SIGINT');}); +process.once('SIGQUIT', () => {terminationHandler.run('SIGQUIT');}); +process.once('SIGTERM', () => {terminationHandler.run('SIGTERM');}); +process.once('SIGINT', () => {terminationHandler.run('SIGINT');}); // require and setup basic http functionalities var portTelemetryReqOrigin = process.env.PORT_TLM_REQ_ORIGIN || 8080 @@ -175,9 +175,29 @@ var openMctServerHandler = new OpenMctServerHandler(console.log,console.error); var ret = openMctServerHandler.start(); console.log(ret); -function handleTermination(signal) { +// Handler for a gracious termination +var terminationHandler = new TerminationHandler( + openMctServerHandler, + telemServer,telemServerTracker, + consoleServer,consoleServerTracker); + +function TerminationHandler( + openMctServerHandler, + telemServer,telemServerTracker, + consoleServer,consoleServerTracker) { + this.openMctServerHandler = openMctServerHandler; + this.telemServer = telemServer; + this.telemServerTracker = telemServerTracker; + this.consoleServer = consoleServer; + this.consoleServerTracker = consoleServerTracker; +} + +TerminationHandler.prototype.run = function(signal) { console.log('Received '+signal+' ...'); + this.runSubsetA(signal); +} +TerminationHandler.prototype.runSubsetA = function (signal) { /* * === Closure subset A === * A.1 - Stop the child Node.js process running the OpenMCT static server. @@ -185,11 +205,11 @@ function handleTermination(signal) { * A.3 - Stop the Control Console HTTP server consoleServer from accepting new connections. */ const closeChildProcessPromise = new Promise(function(resolve,reject) { - ret = openMctServerHandler.stop(signal,resolve,reject); + ret = this.openMctServerHandler.stop(signal,resolve,reject); console.log(ret); - }); + }.bind(this)); const closeTelemServerPromise = new Promise(function(resolve,reject) { - telemServer.close((error) => { + this.telemServer.close((error) => { if (error === undefined) { resolve('iCub Telemetry Server closed: all sockets closed.'); } else { @@ -197,9 +217,9 @@ function handleTermination(signal) { } }); console.log('iCub Telemetry Server closing: no further connection requests accepted.'); - }); + }.bind(this)); const closeConsoleServerPromise = new Promise(function(resolve,reject) { - consoleServer.close((error) => { + this.consoleServer.close((error) => { if (error === undefined) { resolve('Control Console Server closed: all sockets closed.'); } else { @@ -207,13 +227,20 @@ function handleTermination(signal) { } }); console.log('Control Console Server closing: no further incoming requests accepted.'); - }); - Promise.all([closeChildProcessPromise,closeTelemServerPromise,closeConsoleServerPromise]).then( - function(values) { - values.forEach((v) => console.log(v)); - }, - function(error) { - console.error(error.toString()); - } + }.bind(this)); + closeChildProcessPromise.then( + function(value) { + console.log(value); + this.runSubsetB(); + }.bind(this), + function(error) { console.error(error.toString()); } ); } + +TerminationHandler.prototype.runSubsetB = function() { + /* + * === Closure subset B === + * B.1 - Stop listening to client requests ("subscribe"/"unsubscribe" events) on the existing connections. + */ + this.telemServerTracker.pauseAll(); +} From 854962ce6a55544deab7131567526b6566ba73e1 Mon Sep 17 00:00:00 2001 From: Nuno Guedelha Date: Tue, 26 Oct 2021 17:38:40 +0200 Subject: [PATCH 2/2] Move the 'TerminationHandler' class to a dedicated script file --- iCubTelemVizServer/iCubTelemVizServer.js | 65 +---------------------- iCubTelemVizServer/terminationHandler.js | 67 ++++++++++++++++++++++++ 2 files changed, 68 insertions(+), 64 deletions(-) create mode 100644 iCubTelemVizServer/terminationHandler.js diff --git a/iCubTelemVizServer/iCubTelemVizServer.js b/iCubTelemVizServer/iCubTelemVizServer.js index af708ca..93e1d39 100644 --- a/iCubTelemVizServer/iCubTelemVizServer.js +++ b/iCubTelemVizServer/iCubTelemVizServer.js @@ -176,71 +176,8 @@ var ret = openMctServerHandler.start(); console.log(ret); // Handler for a gracious termination +const TerminationHandler = require('./terminationHandler.js'); var terminationHandler = new TerminationHandler( openMctServerHandler, telemServer,telemServerTracker, consoleServer,consoleServerTracker); - -function TerminationHandler( - openMctServerHandler, - telemServer,telemServerTracker, - consoleServer,consoleServerTracker) { - this.openMctServerHandler = openMctServerHandler; - this.telemServer = telemServer; - this.telemServerTracker = telemServerTracker; - this.consoleServer = consoleServer; - this.consoleServerTracker = consoleServerTracker; -} - -TerminationHandler.prototype.run = function(signal) { - console.log('Received '+signal+' ...'); - this.runSubsetA(signal); -} - -TerminationHandler.prototype.runSubsetA = function (signal) { - /* - * === Closure subset A === - * A.1 - Stop the child Node.js process running the OpenMCT static server. - * A.2 - Stop the Telemetry HTTP server telemServer from accepting new connections. - * A.3 - Stop the Control Console HTTP server consoleServer from accepting new connections. - */ - const closeChildProcessPromise = new Promise(function(resolve,reject) { - ret = this.openMctServerHandler.stop(signal,resolve,reject); - console.log(ret); - }.bind(this)); - const closeTelemServerPromise = new Promise(function(resolve,reject) { - this.telemServer.close((error) => { - if (error === undefined) { - resolve('iCub Telemetry Server closed: all sockets closed.'); - } else { - reject(error); - } - }); - console.log('iCub Telemetry Server closing: no further connection requests accepted.'); - }.bind(this)); - const closeConsoleServerPromise = new Promise(function(resolve,reject) { - this.consoleServer.close((error) => { - if (error === undefined) { - resolve('Control Console Server closed: all sockets closed.'); - } else { - reject(error); - } - }); - console.log('Control Console Server closing: no further incoming requests accepted.'); - }.bind(this)); - closeChildProcessPromise.then( - function(value) { - console.log(value); - this.runSubsetB(); - }.bind(this), - function(error) { console.error(error.toString()); } - ); -} - -TerminationHandler.prototype.runSubsetB = function() { - /* - * === Closure subset B === - * B.1 - Stop listening to client requests ("subscribe"/"unsubscribe" events) on the existing connections. - */ - this.telemServerTracker.pauseAll(); -} diff --git a/iCubTelemVizServer/terminationHandler.js b/iCubTelemVizServer/terminationHandler.js new file mode 100644 index 0000000..f078ca9 --- /dev/null +++ b/iCubTelemVizServer/terminationHandler.js @@ -0,0 +1,67 @@ +"use strict"; + +function TerminationHandler( + openMctServerHandler, + telemServer,telemServerTracker, + consoleServer,consoleServerTracker) { + this.openMctServerHandler = openMctServerHandler; + this.telemServer = telemServer; + this.telemServerTracker = telemServerTracker; + this.consoleServer = consoleServer; + this.consoleServerTracker = consoleServerTracker; +} + +TerminationHandler.prototype.run = function(signal) { + console.log('Received '+signal+' ...'); + this.runSubsetA(signal); +} + +TerminationHandler.prototype.runSubsetA = function (signal) { + /* + * === Closure subset A === + * A.1 - Stop the child Node.js process running the OpenMCT static server. + * A.2 - Stop the Telemetry HTTP server telemServer from accepting new connections. + * A.3 - Stop the Control Console HTTP server consoleServer from accepting new connections. + */ + const closeChildProcessPromise = new Promise(function(resolve,reject) { + let ret = this.openMctServerHandler.stop(signal,resolve,reject); + console.log(ret); + }.bind(this)); + const closeTelemServerPromise = new Promise(function(resolve,reject) { + this.telemServer.close((error) => { + if (error === undefined) { + resolve('iCub Telemetry Server closed: all sockets closed.'); + } else { + reject(error); + } + }); + console.log('iCub Telemetry Server closing: no further connection requests accepted.'); + }.bind(this)); + const closeConsoleServerPromise = new Promise(function(resolve,reject) { + this.consoleServer.close((error) => { + if (error === undefined) { + resolve('Control Console Server closed: all sockets closed.'); + } else { + reject(error); + } + }); + console.log('Control Console Server closing: no further incoming requests accepted.'); + }.bind(this)); + closeChildProcessPromise.then( + function(value) { + console.log(value); + this.runSubsetB(); + }.bind(this), + function(error) { console.error(error.toString()); } + ); +} + +TerminationHandler.prototype.runSubsetB = function() { + /* + * === Closure subset B === + * B.1 - Stop listening to client requests ("subscribe"/"unsubscribe" events) on the existing connections. + */ + this.telemServerTracker.pauseAll(); +} + +module.exports = TerminationHandler;