WIP: Start refactor of nodes/Flow.js

This commit is contained in:
Nick O'Leary
2019-01-11 14:53:21 +00:00
parent 30aebc4ee3
commit da756fa568
2 changed files with 136 additions and 95 deletions

View File

@@ -20,38 +20,42 @@ var typeRegistry = require("@node-red/registry");
var Log;
var redUtil = require("@node-red/util").util;
var flowUtil = require("./util");
var Node;
var nodeCloseTimeout = 15000;
function Flow(global,flow) {
if (typeof flow === 'undefined') {
flow = global;
class Flow {
constructor(global,flow) {
this.global = global;
if (typeof flow === 'undefined') {
this.flow = global;
} else {
this.flow = flow;
}
this.activeNodes = {};
this.subflowInstanceNodes = {};
this.catchNodeMap = {};
this.statusNodeMap = {};
}
var activeNodes = {};
var subflowInstanceNodes = {};
var catchNodeMap = {};
var statusNodeMap = {};
this.start = function(diff) {
start(diff) {
var node;
var newNode;
var id;
catchNodeMap = {};
statusNodeMap = {};
this.catchNodeMap = {};
this.statusNodeMap = {};
var configNodes = Object.keys(flow.configs);
var configNodes = Object.keys(this.flow.configs);
var configNodeAttempts = {};
while (configNodes.length > 0) {
id = configNodes.shift();
node = flow.configs[id];
if (!activeNodes[id]) {
node = this.flow.configs[id];
if (!this.activeNodes[id]) {
var readyToCreate = true;
// This node doesn't exist.
// Check it doesn't reference another non-existent config node
for (var prop in node) {
if (node.hasOwnProperty(prop) && prop !== 'id' && prop !== 'wires' && prop !== '_users' && flow.configs[node[prop]]) {
if (!activeNodes[node[prop]]) {
if (node.hasOwnProperty(prop) && prop !== 'id' && prop !== 'wires' && prop !== '_users' && this.flow.configs[node[prop]]) {
if (!this.activeNodes[node[prop]]) {
// References a non-existent config node
// Add it to the back of the list to try again later
configNodes.push(id);
@@ -67,7 +71,7 @@ function Flow(global,flow) {
if (readyToCreate) {
newNode = createNode(node.type,node);
if (newNode) {
activeNodes[id] = newNode;
this.activeNodes[id] = newNode;
}
}
}
@@ -75,31 +79,32 @@ function Flow(global,flow) {
if (diff && diff.rewired) {
for (var j=0;j<diff.rewired.length;j++) {
var rewireNode = activeNodes[diff.rewired[j]];
var rewireNode = this.activeNodes[diff.rewired[j]];
if (rewireNode) {
rewireNode.updateWires(flow.nodes[rewireNode.id].wires);
rewireNode.updateWires(this.flow.nodes[rewireNode.id].wires);
}
}
}
for (id in flow.nodes) {
if (flow.nodes.hasOwnProperty(id)) {
node = flow.nodes[id];
for (id in this.flow.nodes) {
if (this.flow.nodes.hasOwnProperty(id)) {
node = this.flow.nodes[id];
if (!node.subflow) {
if (!activeNodes[id]) {
if (!this.activeNodes[id]) {
newNode = createNode(node.type,node);
if (newNode) {
activeNodes[id] = newNode;
this.activeNodes[id] = newNode;
}
}
} else {
if (!subflowInstanceNodes[id]) {
if (!this.subflowInstanceNodes[id]) {
try {
var nodes = createSubflow(flow.subflows[node.subflow]||global.subflows[node.subflow],node,flow.subflows,global.subflows,activeNodes);
subflowInstanceNodes[id] = nodes.map(function(n) { return n.id});
var subflowDefinition = this.flow.subflows[node.subflow]||this.global.subflows[node.subflow]
var nodes = createSubflow(subflowDefinition,node,this.flow.subflows,this.global.subflows,this.activeNodes);
this.subflowInstanceNodes[id] = nodes.map(function(n) { return n.id});
for (var i=0;i<nodes.length;i++) {
if (nodes[i]) {
activeNodes[nodes[i].id] = nodes[i];
this.activeNodes[nodes[i].id] = nodes[i];
}
}
} catch(err) {
@@ -110,33 +115,33 @@ function Flow(global,flow) {
}
}
for (id in activeNodes) {
if (activeNodes.hasOwnProperty(id)) {
node = activeNodes[id];
for (id in this.activeNodes) {
if (this.activeNodes.hasOwnProperty(id)) {
node = this.activeNodes[id];
if (node.type === "catch") {
catchNodeMap[node.z] = catchNodeMap[node.z] || [];
catchNodeMap[node.z].push(node);
this.catchNodeMap[node.z] = this.catchNodeMap[node.z] || [];
this.catchNodeMap[node.z].push(node);
} else if (node.type === "status") {
statusNodeMap[node.z] = statusNodeMap[node.z] || [];
statusNodeMap[node.z].push(node);
this.statusNodeMap[node.z] = this.statusNodeMap[node.z] || [];
this.statusNodeMap[node.z].push(node);
}
}
}
}
this.stop = function(stopList, removedList) {
return when.promise(function(resolve) {
stop(stopList, removedList) {
return new Promise((resolve,reject) => {
var i;
if (stopList) {
for (i=0;i<stopList.length;i++) {
if (subflowInstanceNodes[stopList[i]]) {
if (this.subflowInstanceNodes[stopList[i]]) {
// The first in the list is the instance node we already
// know about
stopList = stopList.concat(subflowInstanceNodes[stopList[i]].slice(1))
stopList = stopList.concat(this.subflowInstanceNodes[stopList[i]].slice(1))
}
}
} else {
stopList = Object.keys(activeNodes);
stopList = Object.keys(this.activeNodes);
}
// Convert the list to a map to avoid multiple scans of the list
var removedMap = {};
@@ -147,11 +152,11 @@ function Flow(global,flow) {
var promises = [];
for (i=0;i<stopList.length;i++) {
var node = activeNodes[stopList[i]];
var node = this.activeNodes[stopList[i]];
if (node) {
delete activeNodes[stopList[i]];
if (subflowInstanceNodes[stopList[i]]) {
delete subflowInstanceNodes[stopList[i]];
delete this.activeNodes[stopList[i]];
if (this.subflowInstanceNodes[stopList[i]]) {
delete this.subflowInstanceNodes[stopList[i]];
}
try {
var removed = removedMap[stopList[i]];
@@ -188,25 +193,25 @@ function Flow(global,flow) {
});
}
this.update = function(_global,_flow) {
global = _global;
flow = _flow;
update(_global,_flow) {
this.global = _global;
this.flow = _flow;
}
this.getNode = function(id) {
return activeNodes[id];
getNode(id) {
return this.activeNodes[id];
}
this.getActiveNodes = function() {
return activeNodes;
getActiveNodes() {
return this.activeNodes;
}
this.handleStatus = function(node,statusMessage) {
handleStatus(node,statusMessage) {
var targetStatusNodes = null;
var reportingNode = node;
var handled = false;
while (reportingNode && !handled) {
targetStatusNodes = statusNodeMap[reportingNode.z];
targetStatusNodes = this.statusNodeMap[reportingNode.z];
if (targetStatusNodes) {
targetStatusNodes.forEach(function(targetStatusNode) {
if (targetStatusNode.scope && targetStatusNode.scope.indexOf(node.id) === -1) {
@@ -230,12 +235,12 @@ function Flow(global,flow) {
});
}
if (!handled) {
reportingNode = activeNodes[reportingNode.z];
reportingNode = this.activeNodes[reportingNode.z];
}
}
}
this.handleError = function(node,logMessage,msg) {
handleError(node,logMessage,msg) {
var count = 1;
if (msg && msg.hasOwnProperty("error") && msg.error !== null) {
if (msg.error.hasOwnProperty("source") && msg.error.source !== null) {
@@ -252,7 +257,7 @@ function Flow(global,flow) {
var throwingNode = node;
var handled = false;
while (throwingNode && !handled) {
targetCatchNodes = catchNodeMap[throwingNode.z];
targetCatchNodes = this.catchNodeMap[throwingNode.z];
if (targetCatchNodes) {
targetCatchNodes.forEach(function(targetCatchNode) {
if (targetCatchNode.scope && targetCatchNode.scope.indexOf(throwingNode.id) === -1) {
@@ -284,43 +289,48 @@ function Flow(global,flow) {
});
}
if (!handled) {
throwingNode = activeNodes[throwingNode.z];
throwingNode = this.activeNodes[throwingNode.z];
}
}
return handled;
}
}
/**
* Create a new instance of a node
* @param {string} type The node type string
* @param {object} config The node configuration object
* @return {Node} The instance of the node
*/
function createNode(type,config) {
var nn = null;
var newNode = null;
try {
var nt = typeRegistry.get(type);
if (nt) {
var conf = clone(config);
delete conf.credentials;
for (var p in conf) {
if (conf.hasOwnProperty(p)) {
flowUtil.mapEnvVarProperties(conf,p);
var nodeTypeConstructor = typeRegistry.get(type);
if (nodeTypeConstructor) {
var conf = clone(config);
delete conf.credentials;
for (var p in conf) {
if (conf.hasOwnProperty(p)) {
flowUtil.mapEnvVarProperties(conf,p);
}
}
try {
newNode = new nodeTypeConstructor(conf);
} catch (err) {
Log.log({
level: Log.ERROR,
id:conf.id,
type: type,
msg: err
});
}
} else {
Log.error(Log._("nodes.flow.unknown-type", {type:type}));
}
try {
nn = new nt(conf);
}
catch (err) {
Log.log({
level: Log.ERROR,
id:conf.id,
type: type,
msg: err
});
}
} else {
Log.error(Log._("nodes.flow.unknown-type", {type:type}));
} catch(err) {
Log.error(err);
}
} catch(err) {
Log.error(err);
}
return nn;
return newNode;
}
function createSubflow(sf,sfn,subflows,globalSubflows,activeNodes) {
@@ -342,7 +352,7 @@ function createSubflow(sf,sfn,subflows,globalSubflows,activeNodes) {
newNodes.push(node);
}
// Clone all of the subflow node definitions and give them new IDs
// Clone all of the subflow config node definitions and give them new IDs
for (i in sf.configs) {
if (sf.configs.hasOwnProperty(i)) {
createNodeInSubflow(sf.configs[i]);
@@ -503,7 +513,6 @@ module.exports = {
init: function(runtime) {
nodeCloseTimeout = runtime.settings.nodeCloseTimeout || 15000;
Log = runtime.log;
Node = require("../Node");
},
create: function(global,conf) {
return new Flow(global,conf);