1
0
mirror of https://github.com/node-red/node-red.git synced 2023-10-10 13:36:53 +02:00

Remove promises from Join node

This commit is contained in:
Nick O'Leary 2019-01-02 22:37:06 +00:00
parent 747af44fc1
commit 43b7aa40c3
No known key found for this signature in database
GPG Key ID: 4F2157149161A6C9

View File

@ -248,33 +248,11 @@ module.exports = function(RED) {
return _maxKeptMsgsCount; return _maxKeptMsgsCount;
} }
function applyReduce(exp, accum, msg, index, count) { function applyReduce(exp, accum, msg, index, count, done) {
exp.assign("I", index); exp.assign("I", index);
exp.assign("N", count); exp.assign("N", count);
exp.assign("A", accum); exp.assign("A", accum);
return new Promise((resolve,reject) => { RED.util.evaluateJSONataExpression(exp, msg, done);
RED.util.evaluateJSONataExpression(exp, msg, (err, result) => {
if (err) {
reject(err);
} else {
resolve(result);
}
});
});
}
function applyFixup(exp, accum, count) {
exp.assign("N", count);
exp.assign("A", accum);
return new Promise((resolve,reject) => {
return RED.util.evaluateJSONataExpression(exp, {}, (err, result) => {
if (err) {
reject(err);
} else {
resolve(result);
}
});
});
} }
function exp_or_undefined(exp) { function exp_or_undefined(exp) {
@ -285,39 +263,68 @@ module.exports = function(RED) {
return exp return exp
} }
function reduceAndSendGroup(node, group) {
function reduceMessageGroup(node,msgs,exp,fixup,count,accumulator,done) {
var msg = msgs.shift();
exp.assign("I", msg.parts.index);
exp.assign("N", count);
exp.assign("A", accumulator);
RED.util.evaluateJSONataExpression(exp, msg, (err,result) => {
if (err) {
return done(err);
}
if (msgs.length === 0) {
if (fixup) {
fixup.assign("N", count);
fixup.assign("A", result);
RED.util.evaluateJSONataExpression(fixup, {}, (err, result) => {
if (err) {
return done(err);
}
node.send({payload: result});
done();
});
} else {
node.send({payload: result});
done();
}
} else {
reduceMessageGroup(node,msgs,exp,fixup,count,result,done);
}
});
}
function reduceAndSendGroup(node, group, done) {
var is_right = node.reduce_right; var is_right = node.reduce_right;
var flag = is_right ? -1 : 1; var flag = is_right ? -1 : 1;
var msgs = group.msgs; var msgs = group.msgs;
return getInitialReduceValue(node, node.exp_init, node.exp_init_type).then(accum => { try {
var reduceExpression = node.reduceExpression; RED.util.evaluateNodeProperty(node.exp_init, node.exp_init_type, node, {}, (err,accum) => {
var fixupExpression = node.fixupExpression; var reduceExpression = node.reduceExpression;
var count = group.count; var fixupExpression = node.fixupExpression;
msgs.sort(function(x,y) { var count = group.count;
var ix = x.parts.index; msgs.sort(function(x,y) {
var iy = y.parts.index; var ix = x.parts.index;
if (ix < iy) {return -flag;} var iy = y.parts.index;
if (ix > iy) {return flag;} if (ix < iy) {return -flag;}
return 0; if (ix > iy) {return flag;}
}); return 0;
return msgs.reduce((promise, msg) => promise.then(accum => applyReduce(reduceExpression, accum, msg, msg.parts.index, count)), Promise.resolve(accum))
.then(accum => {
if(fixupExpression !== undefined) {
return applyFixup(fixupExpression, accum, count).then(accum => {
node.send({payload: accum});
});
} else {
node.send({payload: accum});
}
}); });
}).catch(err => { reduceMessageGroup(node, msgs,reduceExpression,fixupExpression,count,accum,(err,result) => {
throw new Error(RED._("join.errors.invalid-expr",{error:err.message})); if (err) {
}); done(err);
return;
} else {
done();
}
})
});
} catch(err) {
done(new Error(RED._("join.errors.invalid-expr",{error:err.message})));
}
} }
function reduceMessage(node, msg) { function reduceMessage(node, msg, done) {
var promise;
if (msg.hasOwnProperty('parts')) { if (msg.hasOwnProperty('parts')) {
var parts = msg.parts; var parts = msg.parts;
var pending = node.pending; var pending = node.pending;
@ -335,51 +342,37 @@ module.exports = function(RED) {
} }
var group = pending[gid]; var group = pending[gid];
var msgs = group.msgs; var msgs = group.msgs;
if(parts.hasOwnProperty('count') && (group.count === undefined)) { if (parts.hasOwnProperty('count') && (group.count === undefined)) {
group.count = parts.count; group.count = parts.count;
} }
msgs.push(msg); msgs.push(msg);
pending_count++; pending_count++;
var completeProcess = function() { var completeProcess = function(err) {
if (err) {
return done(err);
}
node.pending_count = pending_count; node.pending_count = pending_count;
var max_msgs = maxKeptMsgsCount(node); var max_msgs = maxKeptMsgsCount(node);
if ((max_msgs > 0) && (pending_count > max_msgs)) { if ((max_msgs > 0) && (pending_count > max_msgs)) {
node.pending = {}; node.pending = {};
node.pending_count = 0; node.pending_count = 0;
var promise = Promise.reject(RED._("join.too-many")); done(RED._("join.too-many"));
promise.catch(()=>{}); return;
return promise;
} }
return Promise.resolve(); return done();
} }
if(msgs.length === group.count) {
if (msgs.length === group.count) {
delete pending[gid]; delete pending[gid];
pending_count -= msgs.length; pending_count -= msgs.length;
promise = reduceAndSendGroup(node, group).then(completeProcess); reduceAndSendGroup(node, group, completeProcess)
} else { } else {
promise = completeProcess(); completeProcess();
} }
} else { } else {
node.send(msg); node.send(msg);
done();
} }
if (!promise) {
promise = Promise.resolve();
}
return promise;
}
function getInitialReduceValue(node, exp, exp_type) {
return new Promise((resolve, reject) => {
RED.util.evaluateNodeProperty(exp, exp_type, node, {},
(err, result) => {
if(err) {
return reject(err);
}
else {
return resolve(result);
}
});
});
} }
function JoinNode(n) { function JoinNode(n) {
@ -490,7 +483,7 @@ module.exports = function(RED) {
} }
var pendingMessages = []; var pendingMessages = [];
var activeMessagePromise = null; var activeMessage = null;
// In reduce mode, we must process messages fully in order otherwise // In reduce mode, we must process messages fully in order otherwise
// groups may overlap and cause unexpected results. The use of JSONata // groups may overlap and cause unexpected results. The use of JSONata
// means some async processing *might* occur if flow/global context is // means some async processing *might* occur if flow/global context is
@ -499,7 +492,7 @@ module.exports = function(RED) {
if (msg) { if (msg) {
// A new message has arrived - add it to the message queue // A new message has arrived - add it to the message queue
pendingMessages.push(msg); pendingMessages.push(msg);
if (activeMessagePromise !== null) { if (activeMessage !== null) {
// The node is currently processing a message, so do nothing // The node is currently processing a message, so do nothing
// more with this message // more with this message
return; return;
@ -508,19 +501,21 @@ module.exports = function(RED) {
if (pendingMessages.length === 0) { if (pendingMessages.length === 0) {
// There are no more messages to process, clear the active flag // There are no more messages to process, clear the active flag
// and return // and return
activeMessagePromise = null; activeMessage = null;
return; return;
} }
// There are more messages to process. Get the next message and // There are more messages to process. Get the next message and
// start processing it. Recurse back in to check for any more // start processing it. Recurse back in to check for any more
var nextMsg = pendingMessages.shift(); var nextMsg = pendingMessages.shift();
activeMessagePromise = reduceMessage(node, nextMsg) activeMessage = true;
.then(processReduceMessageQueue) reduceMessage(node, nextMsg, err => {
.catch((err) => { if (err) {
node.error(err,nextMsg); node.error(err,nextMsg);
return processReduceMessageQueue(); }
}); activeMessage = null;
processReduceMessageQueue();
})
} }
this.on("input", function(msg) { this.on("input", function(msg) {