mirror of
https://github.com/node-red/node-red.git
synced 2023-10-10 13:36:53 +02:00
Add number of units to the delay node (rate) (#994)
* Add possibility to set the value for the rate unit Backward compatible, if the new nbRateUnits is not set, default to 1. This way we can delay messages to 1 msg per X seconds/minutes/hours days instead of always 1. Useful when interacting with API that have a uncommon rate limiting like 1req per 2 seconds. * Fix existing testing for delay * Add new test for the nbRateUnits * Fix label for timed and topic for delay node * Schrink width of Units delay rate * pluralisation of labels * Dynamic pluralisation respecting i18n * Remove debug data left
This commit is contained in:
parent
e4c951984a
commit
ea8c6d5cce
@ -42,11 +42,12 @@
|
|||||||
<label for="node-input-rate"><i class="fa fa-clock-o"></i> <span data-i18n="delay.rate"></span></label>
|
<label for="node-input-rate"><i class="fa fa-clock-o"></i> <span data-i18n="delay.rate"></span></label>
|
||||||
<input type="text" id="node-input-rate" placeholder="1" style="text-align:end; width:30px !important">
|
<input type="text" id="node-input-rate" placeholder="1" style="text-align:end; width:30px !important">
|
||||||
<label for="node-input-rateUnits"><span data-i18n="delay.msgper"></span></label>
|
<label for="node-input-rateUnits"><span data-i18n="delay.msgper"></span></label>
|
||||||
<select id="node-input-rateUnits" style="width:140px !important">
|
<input type="text" id="node-input-nbRateUnits" placeholder="1" style="text-align:end; width:30px !important">
|
||||||
<option value="second" data-i18n="delay.sec"></option>
|
<select id="node-input-rateUnits" style="width:110px !important">
|
||||||
<option value="minute" data-i18n="delay.min"></option>
|
<option value="second" data-i18n="delay.label.units.second.singular"></option>
|
||||||
<option value="hour" data-i18n="delay.hour"></option>
|
<option value="minute" data-i18n="delay.label.units.minute.singular"></option>
|
||||||
<option value="day" data-i18n="delay.day"></option>
|
<option value="hour" data-i18n="delay.label.units.hour.singular"></option>
|
||||||
|
<option value="day" data-i18n="delay.label.units.day.singular"></option>
|
||||||
</select>
|
</select>
|
||||||
<br/>
|
<br/>
|
||||||
<div id="node-input-dr"><input style="margin: 20px 0 20px 100px; width: 30px;" type="checkbox" id="node-input-drop"><label style="width: 250px;" for="node-input-drop"><span data-i18n="delay.dropmsg"></span></label></div>
|
<div id="node-input-dr"><input style="margin: 20px 0 20px 100px; width: 30px;" type="checkbox" id="node-input-drop"><label style="width: 250px;" for="node-input-drop"><span data-i18n="delay.dropmsg"></span></label></div>
|
||||||
@ -98,6 +99,7 @@
|
|||||||
timeout: {value:"5", required:true, validate:RED.validators.number()},
|
timeout: {value:"5", required:true, validate:RED.validators.number()},
|
||||||
timeoutUnits: {value:"seconds"},
|
timeoutUnits: {value:"seconds"},
|
||||||
rate: {value:"1", required:true, validate:RED.validators.number()},
|
rate: {value:"1", required:true, validate:RED.validators.number()},
|
||||||
|
nbRateUnits: {value:"1", required:true, validate:RED.validators.number()},
|
||||||
rateUnits: {value: "second"},
|
rateUnits: {value: "second"},
|
||||||
randomFirst: {value:"1", required:true, validate:RED.validators.number()},
|
randomFirst: {value:"1", required:true, validate:RED.validators.number()},
|
||||||
randomLast: {value:"5", required:true, validate:RED.validators.number()},
|
randomLast: {value:"5", required:true, validate:RED.validators.number()},
|
||||||
@ -113,16 +115,22 @@
|
|||||||
if (this.timeoutUnits == "milliseconds") { units = "ms"; }
|
if (this.timeoutUnits == "milliseconds") { units = "ms"; }
|
||||||
return this.name||this._("delay.label.delay")+" "+this.timeout+" "+units;
|
return this.name||this._("delay.label.delay")+" "+this.timeout+" "+units;
|
||||||
} else if (this.pauseType == "rate") {
|
} else if (this.pauseType == "rate") {
|
||||||
var units = this.rateUnits ? this.rateUnits.charAt(0) : "s";
|
var units = this.rateUnits ? (this.nbRateUnits > 1 ? this.nbRateUnits : '') + this.rateUnits.charAt(0) : "s";
|
||||||
return this.name||this._("delay.label.limit")+" "+this.rate+" msg/"+units;
|
return this.name||this._("delay.label.limit")+" "+this.rate+" msg/"+units;
|
||||||
} else if (this.pauseType == "random") {
|
} else if (this.pauseType == "random") {
|
||||||
return this.name || this._("delay.label.random");
|
return this.name || this._("delay.label.random");
|
||||||
}
|
}
|
||||||
else if (this.pauseType == "timed") {
|
else if (this.pauseType == "timed") {
|
||||||
return this.name || this.rate+" "+this._("delay.label.timed")+" "+this.rateUnits;
|
var units = '';
|
||||||
|
if (this.nbRateUnits > 1) {
|
||||||
|
units = this.nbRateUnits + ' ' + this._("delay.label.units." + this.rateUnits + ".plural");
|
||||||
|
} else {
|
||||||
|
units = this._("delay.label.units." + this.rateUnits + ".singular");
|
||||||
|
}
|
||||||
|
return this.name || this.rate + " " + this._("delay.label.timed") + ' ' + units;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
var units = this.rateUnits ? this.rateUnits.charAt(0) : "s";
|
var units = this.rateUnits ? (this.nbRateUnits > 1 ? this.nbRateUnits : '') + this.rateUnits.charAt(0) : "s";
|
||||||
return this.name || this._("delay.label.queue")+" "+this.rate+" msg/"+units;
|
return this.name || this._("delay.label.queue")+" "+this.rate+" msg/"+units;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -130,12 +138,39 @@
|
|||||||
return this.name?"node_label_italic":"";
|
return this.name?"node_label_italic":"";
|
||||||
},
|
},
|
||||||
oneditprepare: function() {
|
oneditprepare: function() {
|
||||||
|
var node = this;
|
||||||
$( "#node-input-timeout" ).spinner({min:1});
|
$( "#node-input-timeout" ).spinner({min:1});
|
||||||
$( "#node-input-rate" ).spinner({min:1});
|
$( "#node-input-rate" ).spinner({min:1});
|
||||||
|
$( "#node-input-nbRateUnits" ).spinner({min:1});
|
||||||
|
|
||||||
$( "#node-input-randomFirst" ).spinner({min:0});
|
$( "#node-input-randomFirst" ).spinner({min:0});
|
||||||
$( "#node-input-randomLast" ).spinner({min:1});
|
$( "#node-input-randomLast" ).spinner({min:1});
|
||||||
|
|
||||||
|
$('.ui-spinner-button').click(function() {
|
||||||
|
$(this).siblings('input').change();
|
||||||
|
});
|
||||||
|
|
||||||
|
$( "#node-input-nbRateUnits" ).on('change keyup', function() {
|
||||||
|
var $this = $(this);
|
||||||
|
var val = parseInt($this.val());
|
||||||
|
var type = "singular";
|
||||||
|
if(val > 1) {
|
||||||
|
type = "plural";
|
||||||
|
}
|
||||||
|
if($this.attr("data-type") == type) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
$this.attr("data-type", type);
|
||||||
|
$("#node-input-rateUnits option").each(function () {
|
||||||
|
var $option = $(this);
|
||||||
|
var key = "delay.label.units." + $option.val() + "." + type;
|
||||||
|
$option.attr('data-i18n', 'node-red:' + key);
|
||||||
|
$option.html(node._(key));
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (this.pauseType == "delay") {
|
if (this.pauseType == "delay") {
|
||||||
$("#delay-details").show();
|
$("#delay-details").show();
|
||||||
$("#rate-details").hide();
|
$("#rate-details").hide();
|
||||||
|
@ -51,6 +51,8 @@ module.exports = function(RED) {
|
|||||||
this.rate = 1000/n.rate;
|
this.rate = 1000/n.rate;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.rate *= (n.nbRateUnits > 0 ? n.nbRateUnits : 1);
|
||||||
|
|
||||||
if (n.randomUnits === "milliseconds") {
|
if (n.randomUnits === "milliseconds") {
|
||||||
this.randomFirst = n.randomFirst * 1;
|
this.randomFirst = n.randomFirst * 1;
|
||||||
this.randomLast = n.randomLast * 1;
|
this.randomLast = n.randomLast * 1;
|
||||||
|
@ -200,7 +200,25 @@
|
|||||||
"limit": "limit",
|
"limit": "limit",
|
||||||
"random": "random",
|
"random": "random",
|
||||||
"queue": "queue",
|
"queue": "queue",
|
||||||
"timed": "releases per"
|
"timed": "releases per",
|
||||||
|
"units" : {
|
||||||
|
"second": {
|
||||||
|
"plural" : "Seconds",
|
||||||
|
"singular": "Second"
|
||||||
|
},
|
||||||
|
"minute": {
|
||||||
|
"plural" : "Minutes",
|
||||||
|
"singular": "Minute"
|
||||||
|
},
|
||||||
|
"hour": {
|
||||||
|
"plural" : "Hours",
|
||||||
|
"singular": "Hour"
|
||||||
|
},
|
||||||
|
"day": {
|
||||||
|
"plural" : "Days",
|
||||||
|
"singular": "Day"
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"error": {
|
"error": {
|
||||||
"buffer": "buffer exceeded 1000 messages",
|
"buffer": "buffer exceeded 1000 messages",
|
||||||
|
@ -40,7 +40,7 @@ describe('delay Node', function() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should be loaded', function(done) {
|
it('should be loaded', function(done) {
|
||||||
var flow = [{"id":"delayNode1","type":"delay","name":"delayNode","pauseType":"delay","timeout":"5","timeoutUnits":"seconds","rate":"1","rateUnits":"day","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"wires":[[]]}];
|
var flow = [{"id":"delayNode1","type":"delay", "nbRateUnits":"1", "name":"delayNode","pauseType":"delay","timeout":"5","timeoutUnits":"seconds","rate":"1","rateUnits":"day","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"wires":[[]]}];
|
||||||
helper.load(delayNode, flow, function() {
|
helper.load(delayNode, flow, function() {
|
||||||
var delayNode1 = helper.getNode("delayNode1");
|
var delayNode1 = helper.getNode("delayNode1");
|
||||||
delayNode1.should.have.property('name', 'delayNode');
|
delayNode1.should.have.property('name', 'delayNode');
|
||||||
@ -50,7 +50,7 @@ describe('delay Node', function() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should be able to set rate to hour', function(done) {
|
it('should be able to set rate to hour', function(done) {
|
||||||
var flow = [{"id":"delayNode1","type":"delay","name":"delayNode","pauseType":"delay","timeout":"5","timeoutUnits":"seconds","rate":"1","rateUnits":"hour","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"wires":[[]]}];
|
var flow = [{"id":"delayNode1","type":"delay", "nbRateUnits":"1", "name":"delayNode","pauseType":"delay","timeout":"5","timeoutUnits":"seconds","rate":"1","rateUnits":"hour","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"wires":[[]]}];
|
||||||
helper.load(delayNode, flow, function() {
|
helper.load(delayNode, flow, function() {
|
||||||
var delayNode1 = helper.getNode("delayNode1");
|
var delayNode1 = helper.getNode("delayNode1");
|
||||||
delayNode1.should.have.property('name', 'delayNode');
|
delayNode1.should.have.property('name', 'delayNode');
|
||||||
@ -60,7 +60,7 @@ describe('delay Node', function() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should be able to set rate to minute', function(done) {
|
it('should be able to set rate to minute', function(done) {
|
||||||
var flow = [{"id":"delayNode1","type":"delay","name":"delayNode","pauseType":"delay","timeout":"5","timeoutUnits":"seconds","rate":"1","rateUnits":"minute","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"wires":[[]]}];
|
var flow = [{"id":"delayNode1","type":"delay", "nbRateUnits":"1", "name":"delayNode","pauseType":"delay","timeout":"5","timeoutUnits":"seconds","rate":"1","rateUnits":"minute","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"wires":[[]]}];
|
||||||
helper.load(delayNode, flow, function() {
|
helper.load(delayNode, flow, function() {
|
||||||
var delayNode1 = helper.getNode("delayNode1");
|
var delayNode1 = helper.getNode("delayNode1");
|
||||||
delayNode1.should.have.property('name', 'delayNode');
|
delayNode1.should.have.property('name', 'delayNode');
|
||||||
@ -173,10 +173,11 @@ describe('delay Node', function() {
|
|||||||
/**
|
/**
|
||||||
* Runs a rate limit test - only testing seconds!
|
* Runs a rate limit test - only testing seconds!
|
||||||
* @param aLimit - the message limit count
|
* @param aLimit - the message limit count
|
||||||
|
* @param nbUnit - the multiple of the unit, aLimit Message for nbUnit Seconds
|
||||||
* @param runtimeInMillis - when to terminate run and count messages received
|
* @param runtimeInMillis - when to terminate run and count messages received
|
||||||
*/
|
*/
|
||||||
function genericRateLimitSECONDSTest(aLimit, runtimeInMillis, done) {
|
function genericRateLimitSECONDSTest(aLimit, nbUnit, runtimeInMillis, done) {
|
||||||
var flow = [{"id":"delayNode1","type":"delay","name":"delayNode","pauseType":"rate","timeout":5,"timeoutUnits":"seconds","rate":aLimit,"rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"wires":[["helperNode1"]]},
|
var flow = [{"id":"delayNode1","type":"delay","nbRateUnits":nbUnit,"name":"delayNode","pauseType":"rate","timeout":5,"timeoutUnits":"seconds","rate":aLimit,"rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"wires":[["helperNode1"]]},
|
||||||
{id:"helperNode1", type:"helper", wires:[]}];
|
{id:"helperNode1", type:"helper", wires:[]}];
|
||||||
helper.load(delayNode, flow, function() {
|
helper.load(delayNode, flow, function() {
|
||||||
var delayNode1 = helper.getNode("delayNode1");
|
var delayNode1 = helper.getNode("delayNode1");
|
||||||
@ -223,21 +224,27 @@ describe('delay Node', function() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
it('limits the message rate to 1 per second', function(done) {
|
it('limits the message rate to 1 per second', function(done) {
|
||||||
genericRateLimitSECONDSTest(1, 1500, done);
|
genericRateLimitSECONDSTest(1, 1, 1500, done);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('limits the message rate to 2 per second, 2 seconds', function(done) {
|
it('limits the message rate to 1 per 2 seconds', function(done) {
|
||||||
this.timeout(6000);
|
this.timeout(6000);
|
||||||
genericRateLimitSECONDSTest(2, 2100, done);
|
genericRateLimitSECONDSTest(1, 2, 3000, done);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('limits the message rate to 2 per seconds, 2 seconds', function(done) {
|
||||||
|
this.timeout(6000);
|
||||||
|
genericRateLimitSECONDSTest(2, 1, 2100, done);
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Runs a rate limit test with drop support - only testing seconds!
|
* Runs a rate limit test with drop support - only testing seconds!
|
||||||
* @param aLimit - the message limit count
|
* @param aLimit - the message limit count
|
||||||
|
* @param nbUnit - the multiple of the unit, aLimit Message for nbUnit Seconds
|
||||||
* @param runtimeInMillis - when to terminate run and count messages received
|
* @param runtimeInMillis - when to terminate run and count messages received
|
||||||
*/
|
*/
|
||||||
function dropRateLimitSECONDSTest(aLimit, runtimeInMillis, done) {
|
function dropRateLimitSECONDSTest(aLimit, nbUnit, runtimeInMillis, done) {
|
||||||
var flow = [{"id":"delayNode1","type":"delay","name":"delayNode","pauseType":"rate","timeout":5,"timeoutUnits":"seconds","rate":aLimit,"rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":true,"wires":[["helperNode1"]]},
|
var flow = [{"id":"delayNode1","type":"delay","name":"delayNode","pauseType":"rate","timeout":5,"nbRateUnits":nbUnit,"timeoutUnits":"seconds","rate":aLimit,"rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":true,"wires":[["helperNode1"]]},
|
||||||
{id:"helperNode1", type:"helper", wires:[]}];
|
{id:"helperNode1", type:"helper", wires:[]}];
|
||||||
helper.load(delayNode, flow, function() {
|
helper.load(delayNode, flow, function() {
|
||||||
var delayNode1 = helper.getNode("delayNode1");
|
var delayNode1 = helper.getNode("delayNode1");
|
||||||
@ -298,12 +305,17 @@ describe('delay Node', function() {
|
|||||||
|
|
||||||
it('limits the message rate to 1 per second, 4 seconds, with drop', function(done) {
|
it('limits the message rate to 1 per second, 4 seconds, with drop', function(done) {
|
||||||
this.timeout(6000);
|
this.timeout(6000);
|
||||||
dropRateLimitSECONDSTest(1, 4000, done);
|
dropRateLimitSECONDSTest(1, 1, 4000, done);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('limits the message rate to 1 per 2 seconds, 4 seconds, with drop', function(done) {
|
||||||
|
this.timeout(6000);
|
||||||
|
dropRateLimitSECONDSTest(1, 2, 4500, done);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('limits the message rate to 2 per second, 5 seconds, with drop', function(done) {
|
it('limits the message rate to 2 per second, 5 seconds, with drop', function(done) {
|
||||||
this.timeout(6000);
|
this.timeout(6000);
|
||||||
dropRateLimitSECONDSTest(2, 5000, done);
|
dropRateLimitSECONDSTest(2, 1, 5000, done);
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -436,7 +448,7 @@ describe('delay Node', function() {
|
|||||||
|
|
||||||
it('handles delay queue', function(done) {
|
it('handles delay queue', function(done) {
|
||||||
this.timeout(2000);
|
this.timeout(2000);
|
||||||
var flow = [{id:"delayNode1", type :"delay","name":"delayNode","pauseType":"queue","timeout":1,"timeoutUnits":"seconds","rate":4,"rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"wires":[["helperNode1"]]},
|
var flow = [{id:"delayNode1", type :"delay","name":"delayNode","nbRateUnits":"1","pauseType":"queue","timeout":1,"timeoutUnits":"seconds","rate":4,"rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"wires":[["helperNode1"]]},
|
||||||
{id:"helperNode1", type:"helper", wires:[]}];
|
{id:"helperNode1", type:"helper", wires:[]}];
|
||||||
helper.load(delayNode, flow, function() {
|
helper.load(delayNode, flow, function() {
|
||||||
var delayNode1 = helper.getNode("delayNode1");
|
var delayNode1 = helper.getNode("delayNode1");
|
||||||
|
Loading…
Reference in New Issue
Block a user