diff --git a/packages/node_modules/@node-red/runtime/lib/nodes/Node.js b/packages/node_modules/@node-red/runtime/lib/nodes/Node.js index 44dffe22e..132709372 100644 --- a/packages/node_modules/@node-red/runtime/lib/nodes/Node.js +++ b/packages/node_modules/@node-red/runtime/lib/nodes/Node.js @@ -16,7 +16,6 @@ var util = require("util"); var EventEmitter = require("events").EventEmitter; -var when = require("when"); var redUtil = require("@node-red/util").util; var Log = require("@node-red/util").log; // TODO: separate module @@ -92,21 +91,34 @@ Node.prototype.close = function(removed) { var callback = this._closeCallbacks[i]; if (callback.length > 0) { promises.push( - when.promise(function(resolve) { - var args = []; - if (callback.length === 2) { - args.push(!!removed); + new Promise((resolve) => { + try { + var args = []; + if (callback.length === 2) { + args.push(!!removed); + } + args.push(() => { + resolve(); + }); + callback.apply(node, args); + } catch(err) { + // TODO: error thrown in node async close callback + // We've never logged this properly. + resolve(); } - args.push(resolve); - callback.apply(node, args); }) ); } else { - callback.call(node); + try { + callback.call(node); + } catch(err) { + // TODO: error thrown in node sync close callback + // We've never logged this properly. + } } } if (promises.length > 0) { - return when.settle(promises).then(function() { + return Promise.all(promises).then(function() { if (this._context) { return context.delete(this._alias||this.id,this.z); } @@ -115,7 +127,7 @@ Node.prototype.close = function(removed) { if (this._context) { return context.delete(this._alias||this.id,this.z); } - return; + return Promise.resolve(); } }; @@ -138,8 +150,6 @@ Node.prototype.send = function(msg) { /* istanbul ignore else */ if (node) { node.receive(msg); - } else { - console.log("trying to send to a node not on this flow",this._wire); } return; } else { @@ -187,8 +197,6 @@ Node.prototype.send = function(msg) { } } } - } else { - console.log("trying to send to a node not on this flow",this._wire); } } } @@ -295,4 +303,5 @@ Node.prototype.metric = function(eventname, msg, metricValue) { Node.prototype.status = function(status) { this._flow.handleStatus(this,status); }; + module.exports = Node; diff --git a/packages/node_modules/@node-red/runtime/lib/nodes/flows/Flow.js b/packages/node_modules/@node-red/runtime/lib/nodes/flows/Flow.js index 6f0455d3e..c78b91a86 100644 --- a/packages/node_modules/@node-red/runtime/lib/nodes/flows/Flow.js +++ b/packages/node_modules/@node-red/runtime/lib/nodes/flows/Flow.js @@ -14,14 +14,14 @@ * limitations under the License. **/ -var when = require("when"); var clone = require("clone"); -var Subflow; -var Log; var redUtil = require("@node-red/util").util; var flowUtil = require("./util"); var events = require("../../events"); +var Subflow; +var Log; + var nodeCloseTimeout = 15000; /** @@ -227,55 +227,42 @@ class Flow { * @return {[type]} [description] */ stop(stopList, removedList) { - return new Promise((resolve,reject) => { - this.trace("stop "+this.TYPE); - var i; - if (stopList) { - // for (i=0;i { subflow.stop() })); - } catch(err) { - node.error(err); - } - delete this.subflowInstanceNodes[stopList[i]]; - } else { - try { - var removed = removedMap[stopList[i]]; - promises.push(stopNode(node,removed)); - } catch(err) { - node.error(err); - } + var promises = []; + for (i=0;i { subflow.stop() })); + } catch(err) { + node.error(err); + } + delete this.subflowInstanceNodes[stopList[i]]; + } else { + try { + var removed = removedMap[stopList[i]]; + promises.push(stopNode(node,removed).catch(()=>{})); + } catch(err) { + node.error(err); } } } - when.settle(promises).then(function(results) { - resolve(); - }); - }); + } + return Promise.all(promises); } @@ -455,22 +442,20 @@ class Flow { * @return {[type]} [description] */ function stopNode(node,removed) { - return when.promise(function(resolve, reject) { - var start; - when.promise(function(resolve) { - Log.trace("Stopping node "+node.type+":"+node.id+(removed?" removed":"")); - start = Date.now(); - resolve(node.close(removed)); - }).timeout(nodeCloseTimeout).then(function(){ - var delta = Date.now() - start; - Log.trace("Stopped node "+node.type+":"+node.id+" ("+delta+"ms)" ); - resolve(delta); - },function(err) { - var delta = Date.now() - start; - node.error(Log._("nodes.flows.stopping-error",{message:err})); - Log.debug(err.stack); - reject(err); - }); + Log.trace("Stopping node "+node.type+":"+node.id+(removed?" removed":"")); + const start = Date.now(); + const closePromise = node.close(removed); + const closeTimeout = new Promise((resolve,reject) => { + setTimeout(() => { + reject("Close timed out"); + }, nodeCloseTimeout); + }); + return Promise.race([closePromise,closeTimeout]).then(() => { + var delta = Date.now() - start; + Log.trace("Stopped node "+node.type+":"+node.id+" ("+delta+"ms)" ); + }).catch(err => { + node.error(Log._("nodes.flows.stopping-error",{message:err})); + Log.debug(err.stack); }) } diff --git a/packages/node_modules/@node-red/runtime/lib/nodes/flows/index.js b/packages/node_modules/@node-red/runtime/lib/nodes/flows/index.js index eeff37b8c..20c3274d1 100644 --- a/packages/node_modules/@node-red/runtime/lib/nodes/flows/index.js +++ b/packages/node_modules/@node-red/runtime/lib/nodes/flows/index.js @@ -357,7 +357,7 @@ function start(type,diff,muteLog) { function stop(type,diff,muteLog) { if (!started) { - return when.resolve(); + return Promise.resolve(); } type = type||"full"; diff = diff||{ @@ -395,29 +395,27 @@ function stop(type,diff,muteLog) { } } - return when.promise(function(resolve,reject) { - when.settle(promises).then(function() { - for (id in activeNodesToFlow) { - if (activeNodesToFlow.hasOwnProperty(id)) { - if (!activeFlows[activeNodesToFlow[id]]) { - delete activeNodesToFlow[id]; - } - } - } - if (stopList) { - stopList.forEach(function(id) { + return Promise.resolve(promises).then(function() { + for (id in activeNodesToFlow) { + if (activeNodesToFlow.hasOwnProperty(id)) { + if (!activeFlows[activeNodesToFlow[id]]) { delete activeNodesToFlow[id]; - }); - } - if (!muteLog) { - if (type !== "full") { - log.info(log._("nodes.flows.stopped-modified-"+type)); - } else { - log.info(log._("nodes.flows.stopped-flows")); } } - resolve(); - }); + } + if (stopList) { + stopList.forEach(function(id) { + delete activeNodesToFlow[id]; + }); + } + if (!muteLog) { + if (type !== "full") { + log.info(log._("nodes.flows.stopped-modified-"+type)); + } else { + log.info(log._("nodes.flows.stopped-flows")); + } + } + events.emit("nodes-stopped"); }); } diff --git a/test/unit/@node-red/runtime/lib/nodes/Node_spec.js b/test/unit/@node-red/runtime/lib/nodes/Node_spec.js index b90c5dd8c..7e5aed1b0 100644 --- a/test/unit/@node-red/runtime/lib/nodes/Node_spec.js +++ b/test/unit/@node-red/runtime/lib/nodes/Node_spec.js @@ -55,8 +55,7 @@ describe('Node', function() { n.on('close',function() { done(); }); - var p = n.close(); - should.not.exist(p); + n.close(); }); it('returns a promise when provided a callback with a done parameter',function(testdone) { diff --git a/test/unit/@node-red/runtime/lib/nodes/flows/Flow_spec.js b/test/unit/@node-red/runtime/lib/nodes/flows/Flow_spec.js index 5b719b28a..14b1e58ab 100644 --- a/test/unit/@node-red/runtime/lib/nodes/flows/Flow_spec.js +++ b/test/unit/@node-red/runtime/lib/nodes/flows/Flow_spec.js @@ -346,7 +346,7 @@ describe('Flow', function() { stoppedNodes.should.have.a.property("2"); stoppedNodes.should.have.a.property("3"); done(); - }); + }).catch(done); }); it("stops specified nodes",function(done) {