Ensure config nodes are instantiated in the right order

This commit is contained in:
Nick O'Leary 2016-04-27 10:31:19 +01:00
parent 2a089f7d90
commit b744491dd2
2 changed files with 84 additions and 6 deletions

View File

@ -36,17 +36,40 @@ function Flow(global,flow) {
var id;
catchNodeMap = {};
statusNodeMap = {};
for (id in flow.configs) {
if (flow.configs.hasOwnProperty(id)) {
node = flow.configs[id];
if (!activeNodes[id]) {
var configNodes = Object.keys(flow.configs);
var configNodeAttempts = {};
while(configNodes.length > 0) {
id = configNodes.shift();
node = flow.configs[id];
if (!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]]) {
// References a non-existent config node
// Add it to the back of the list to try again later
configNodes.push(id);
configNodeAttempts[id] = (configNodeAttempts[id]||0)+1;
if (configNodeAttempts[id] === 100) {
throw new Error("Circular config node dependency detected: "+id);
}
readyToCreate = false;
break;
}
}
}
if (readyToCreate) {
newNode = createNode(node.type,node);
if (newNode) {
activeNodes[id] = newNode;
}
}
}
}
};
if (diff && diff.rewired) {
for (var j=0;j<diff.rewired.length;j++) {
var rewireNode = activeNodes[diff.rewired[j]];

View File

@ -45,7 +45,7 @@ describe('Flow', function() {
var TestNode = function(n) {
Node.call(this,n);
createCount++;
this._index = createCount++;
this.scope = n.scope;
var node = this;
this.foo = n.foo;
@ -173,6 +173,61 @@ describe('Flow', function() {
});
it("instantiates config nodes in the right order",function(done) {
var config = flowUtils.parseConfig([
{id:"t1",type:"tab"},
{id:"1",x:10,y:10,z:"t1",type:"test",foo:"a",wires:["2"]},
{id:"2",x:10,y:10,z:"t1",type:"test",foo:"a",wires:["3"]},
{id:"3",x:10,y:10,z:"t1",type:"test",foo:"a",wires:[]},
{id:"4",z:"t1",type:"test",foo:"5"}, // This node depends on #5
{id:"5",z:"t1",type:"test"}
]);
var flow = Flow.create(config,config.flows["t1"]);
flow.start();
Object.keys(flow.getActiveNodes()).should.have.length(5);
currentNodes.should.have.a.property("1");
currentNodes.should.have.a.property("2");
currentNodes.should.have.a.property("3");
currentNodes.should.have.a.property("4");
currentNodes.should.have.a.property("5");
currentNodes["1"].should.have.a.property("_index",2);
currentNodes["2"].should.have.a.property("_index",3);
currentNodes["3"].should.have.a.property("_index",4);
currentNodes["4"].should.have.a.property("_index",1);
currentNodes["5"].should.have.a.property("_index",0);
flow.stop().then(function() {
currentNodes.should.not.have.a.property("1");
currentNodes.should.not.have.a.property("2");
currentNodes.should.not.have.a.property("3");
currentNodes.should.not.have.a.property("4");
currentNodes.should.not.have.a.property("5");
stoppedNodes.should.have.a.property("1");
stoppedNodes.should.have.a.property("2");
stoppedNodes.should.have.a.property("3");
stoppedNodes.should.have.a.property("4");
stoppedNodes.should.have.a.property("5");
done();
});
});
it("detects dependency loops in config nodes",function() {
var config = flowUtils.parseConfig([
{id:"t1",type:"tab"},
{id:"node1",z:"t1",type:"test",foo:"node2"}, // This node depends on #5
{id:"node2",z:"t1",type:"test",foo:"node1"}
]);
var flow = Flow.create(config,config.flows["t1"]);
/*jshint immed: false */
(function(){
flow.start();
}).should.throw("Circular config node dependency detected: node1");
});
it("instantiates a subflow and stops it",function(done) {
var config = flowUtils.parseConfig([
{id:"t1",type:"tab"},