diff --git a/packages/node_modules/@node-red/nodes/core/sequence/19-batch.html b/packages/node_modules/@node-red/nodes/core/sequence/19-batch.html
index 9afb84205..91e6567c5 100644
--- a/packages/node_modules/@node-red/nodes/core/sequence/19-batch.html
+++ b/packages/node_modules/@node-red/nodes/core/sequence/19-batch.html
@@ -36,6 +36,10 @@
+
+
+
+
@@ -45,7 +49,7 @@
-
+
@@ -101,6 +105,7 @@
}
},
allowEmptySequence: {value:false},
+ honourParts: {value:false},
topics: {value:[{topic:""}]}
},
inputs:1,
diff --git a/packages/node_modules/@node-red/nodes/core/sequence/19-batch.js b/packages/node_modules/@node-red/nodes/core/sequence/19-batch.js
index f3f29df6a..5cc97e6a9 100644
--- a/packages/node_modules/@node-red/nodes/core/sequence/19-batch.js
+++ b/packages/node_modules/@node-red/nodes/core/sequence/19-batch.js
@@ -181,6 +181,8 @@ module.exports = function(RED) {
RED.nodes.createNode(this,n);
var node = this;
var mode = n.mode || "count";
+ var eof = false;
+ node.honourParts = n.honourParts || false;
node.pending_count = 0;
if (mode === "count") {
@@ -201,9 +203,12 @@ module.exports = function(RED) {
return;
}
var queue = node.pending;
+ if (node.honourParts && msg.hasOwnProperty("parts")) {
+ if (msg.parts.index + 1 === msg.parts.count) { eof = true; }
+ }
queue.push({msg, send, done});
node.pending_count++;
- if (queue.length === count) {
+ if (queue.length === count || eof === true) {
send_msgs(node, queue, is_overlap);
for (let i = 0; i < queue.length-overlap; i++) {
queue[i].done();
@@ -211,6 +216,7 @@ module.exports = function(RED) {
node.pending =
(overlap === 0) ? [] : queue.slice(-overlap);
node.pending_count = 0;
+ eof = false;
}
var max_msgs = max_kept_msgs_count(node);
if ((max_msgs > 0) && (node.pending_count > max_msgs)) {
diff --git a/packages/node_modules/@node-red/nodes/locales/en-US/messages.json b/packages/node_modules/@node-red/nodes/locales/en-US/messages.json
index 598e3536a..bc89992e2 100644
--- a/packages/node_modules/@node-red/nodes/locales/en-US/messages.json
+++ b/packages/node_modules/@node-red/nodes/locales/en-US/messages.json
@@ -1114,6 +1114,7 @@
"too-many": "too many pending messages in batch node",
"unexpected": "unexpected mode",
"no-parts": "no parts property in message",
+ "honourParts": "Allow msg.parts to also complete batch operation.",
"error": {
"invalid-count": "Invalid count",
"invalid-overlap": "Invalid overlap",
diff --git a/test/nodes/core/sequence/19-batch_spec.js b/test/nodes/core/sequence/19-batch_spec.js
index 2ebcb8d4d..b4025a3f8 100644
--- a/test/nodes/core/sequence/19-batch_spec.js
+++ b/test/nodes/core/sequence/19-batch_spec.js
@@ -98,7 +98,7 @@ describe('BATCH node', function() {
var n2 = helper.getNode("n2");
check_data(n1, n2, results, done);
for(var i = 0; i < 6; i++) {
- n1.receive({payload: i});
+ n1.receive({payload: i, parts: { count:6, index:i }});
}
});
}
@@ -168,6 +168,25 @@ describe('BATCH node', function() {
check_count(flow, results, done);
});
+ it('should create seq. with count (more sent than count)', function(done) {
+ var flow = [{id:"n1", type:"batch", name: "BatchNode", mode: "count", count: 4, overlap: 0, interval: 10, allowEmptySequence: false, topics: [], wires:[["n2"]]},
+ {id:"n2", type:"helper"}];
+ var results = [
+ [0, 1, 2, 3]
+ ];
+ check_count(flow, results, done);
+ });
+
+ it('should create seq. with count and terminate early if parts honoured', function(done) {
+ var flow = [{id:"n1", type:"batch", name: "BatchNode", mode: "count", count: 4, overlap: 0, interval: 10, allowEmptySequence:false, honourParts:true, topics: [], wires:[["n2"]]},
+ {id:"n2", type:"helper"}];
+ var results = [
+ [0, 1, 2, 3],
+ [4, 5]
+ ];
+ check_count(flow, results, done);
+ });
+
it('should create seq. with count and overlap', function(done) {
var flow = [{id:"n1", type:"batch", name: "BatchNode", mode: "count", count: 3, overlap: 2, interval: 10, allowEmptySequence: false, topics: [], wires:[["n2"]]},
{id:"n2", type:"helper"}];
@@ -455,7 +474,7 @@ describe('BATCH node', function() {
function mapiDoneTestHelper(done, mode, count, overlap, interval, allowEmptySequence, msgAndTimings) {
const completeNode = require("nr-test-utils").require("@node-red/nodes/core/common/24-complete.js");
const catchNode = require("nr-test-utils").require("@node-red/nodes/core/common/25-catch.js");
- const flow = [{id:"batchNode1", type:"batch", name: "BatchNode", mode, count, overlap, interval,
+ const flow = [{id:"batchNode1", type:"batch", name: "BatchNode", mode, count, overlap, interval,
allowEmptySequence, topics: [{topic: "TA"}], wires:[[]]},
{id:"completeNode1",type:"complete",scope: ["batchNode1"],uncaught:false,wires:[["helperNode1"]]},
{id:"catchNode1", type:"catch",scope: ["batchNode1"],uncaught:false,wires:[["helperNode1"]]},
@@ -482,13 +501,13 @@ describe('BATCH node', function() {
}
it('should call done() when message is sent (mode: count)', function(done) {
- mapiDoneTestHelper(done, "count", 2, 0, 2, false, [
+ mapiDoneTestHelper(done, "count", 2, 0, 2, false, [
{ msg: {payload: 0}, delay: 0, avr: 0, var: 100},
{ msg: {payload: 1}, delay: 0, avr: 0, var: 100}
]);
});
it('should call done() when reset (mode: count)', function(done) {
- mapiDoneTestHelper(done, "count", 2, 0, 2, false, [
+ mapiDoneTestHelper(done, "count", 2, 0, 2, false, [
{ msg: {payload: 0}, delay: 0, avr: 200, var: 100},
{ msg: {payload: 1, reset:true}, delay: 200, avr: 200, var: 100}
]);