Delay node will rate-limit but not delay

I am trying to delay a series of messages with a custom delay using the delay node. I'm using a function node to insert msg.delay into the message headed to the delay node. However, the delay node does not delay the messages and outputs the messages in quick succession. Previously, I was using the rate limiting feature of the delay node with success. But, when I use the delay method, no delay occurs. Even when I use a fixed delay, the delay is ignored. Any input would be greatly appreciated.

Try this;

[
    {
        "id": "b8357465.ef65d8",
        "type": "delay",
        "z": "a444a9ff.e7a408",
        "name": "",
        "pauseType": "delayv",
        "timeout": "5",
        "timeoutUnits": "seconds",
        "rate": "1",
        "nbRateUnits": "1",
        "rateUnits": "second",
        "randomFirst": "1",
        "randomLast": "5",
        "randomUnits": "seconds",
        "drop": false,
        "x": 220,
        "y": 360,
        "wires": [
            [
                "219eb1db.93dabe"
            ]
        ]
    },
    {
        "id": "2796e5a2.cfef8a",
        "type": "inject",
        "z": "a444a9ff.e7a408",
        "name": "",
        "topic": "",
        "payload": "",
        "payloadType": "date",
        "repeat": "",
        "crontab": "",
        "once": false,
        "onceDelay": 0.1,
        "x": 100,
        "y": 240,
        "wires": [
            [
                "2b96e85e.20a7d8"
            ]
        ]
    },
    {
        "id": "219eb1db.93dabe",
        "type": "debug",
        "z": "a444a9ff.e7a408",
        "name": "",
        "active": true,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "false",
        "x": 370,
        "y": 360,
        "wires": []
    },
    {
        "id": "2b96e85e.20a7d8",
        "type": "function",
        "z": "a444a9ff.e7a408",
        "name": "",
        "func": "msg.delay = 20000;\nreturn msg;",
        "outputs": 1,
        "noerr": 0,
        "x": 160,
        "y": 300,
        "wires": [
            [
                "b8357465.ef65d8"
            ]
        ]
    }
]

If you stick a debug node (set to 'complete msg object') to the function node, you will see both msg.payload & msg.delay being sent to the delay node.

delay

Your example works fine if I only insert a single timestamp, but if I repeatedly press the insert button, a delay of 20 seconds occurs but then all messages are sent in quick succession (at the speed in which I pressed insert). I was expecting to see a 20 second delay between each message. I'm guessing that the delay is calculated based on the arrival time of each message, and since all messages are arriving quickly, they are being sent just as quickly, after the 20 second delay expires.

In my flow, I'm sending a stream of values that I want rate limited, but I need the rate to be variable depending on what is configured in the dashboard. Rate limiting works, but it's not variable. What I guess I need is a delay that starts over after the sending of each message.

Yes, correct.

I thought it did?

[
    {
        "id": "b8357465.ef65d8",
        "type": "delay",
        "z": "a444a9ff.e7a408",
        "name": "",
        "pauseType": "delayv",
        "timeout": "5",
        "timeoutUnits": "seconds",
        "rate": "1",
        "nbRateUnits": "1",
        "rateUnits": "second",
        "randomFirst": "1",
        "randomLast": "5",
        "randomUnits": "seconds",
        "drop": false,
        "x": 400,
        "y": 1870,
        "wires": [
            [
                "219eb1db.93dabe"
            ]
        ]
    },
    {
        "id": "2796e5a2.cfef8a",
        "type": "inject",
        "z": "a444a9ff.e7a408",
        "name": "",
        "topic": "",
        "payload": "B",
        "payloadType": "str",
        "repeat": "",
        "crontab": "",
        "once": false,
        "onceDelay": 0.1,
        "x": 160,
        "y": 1870,
        "wires": [
            [
                "2b96e85e.20a7d8"
            ]
        ]
    },
    {
        "id": "219eb1db.93dabe",
        "type": "debug",
        "z": "a444a9ff.e7a408",
        "name": "",
        "active": true,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "false",
        "x": 490,
        "y": 1930,
        "wires": []
    },
    {
        "id": "2b96e85e.20a7d8",
        "type": "function",
        "z": "a444a9ff.e7a408",
        "name": "",
        "func": "msg.delay = 20000;\nreturn msg;",
        "outputs": 1,
        "noerr": 0,
        "x": 230,
        "y": 1930,
        "wires": [
            [
                "b8357465.ef65d8"
            ]
        ]
    },
    {
        "id": "3e5006a5.c75fba",
        "type": "inject",
        "z": "a444a9ff.e7a408",
        "name": "",
        "topic": "",
        "payload": "A",
        "payloadType": "str",
        "repeat": "",
        "crontab": "",
        "once": false,
        "onceDelay": 0.1,
        "x": 160,
        "y": 1750,
        "wires": [
            [
                "fdc19cae.4d79c"
            ]
        ]
    },
    {
        "id": "fdc19cae.4d79c",
        "type": "function",
        "z": "a444a9ff.e7a408",
        "name": "",
        "func": "msg.delay = 10000;\nreturn msg;",
        "outputs": 1,
        "noerr": 0,
        "x": 230,
        "y": 1810,
        "wires": [
            [
                "b8357465.ef65d8"
            ]
        ]
    }
]

Is there a way of achieving the desired effect? Basically a stream of messages slowed down to a variable rate?

Hmm? Your second example is interesting. It appears that if the delay changes between messages, then they are outputted as expected with each delay respected, but if the first inject is pressed twice in a row, both messages are outputted quickly.

Wouldn't you expect them to be?

Am I right in thinking that what you want is an extension to the Delay node such that in Rate Limit mode it respects msg.delay so that the rate can be varied? If so then I think that would require a code change to the Delay node.

Thanks for the feedback. Now that I have a better understanding of the functionality and limitations of the delay node, I've come up with a working solution. Basically what I've done is use a few interim functions to set, then increment the delay by a given amount for each msg in the stream. This allows me to set a value in the dashboard, then calculate the desired delay between each message, and increment msg.delay for each payload.

It would be nice if the rate-limiting function of the delay node would accept input values similar to the delay function. That would suffice just fine, or if the delay function had an option to start the next message's delay after sending the previous message. But my hack works fine for anyone looking for a similar solution.

I'm using this technique to create dim-up schedules for lighting in my house, but want to set the dim rate dynamically in the dashboard. For example, in the a.m I want the lights in our bedrooms to slowly turn on from off to a desired level over 20 to 30 minutes. But, configurable in the dashboard.

Here's an example flow where 60 messages are created with incremented delays. They are all created instantly, but stream out of the delay node at 1 per second:

[{"id":"515f4b35.4afad4","type":"delay","z":"b4bc3dc8.d6e5d","name":"","pauseType":"delayv","timeout":"5","timeoutUnits":"seconds","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"x":1390,"y":270,"wires":[["db48e4f5.377228"]]},{"id":"db48e4f5.377228","type":"debug","z":"b4bc3dc8.d6e5d","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","x":1520,"y":270,"wires":[]},{"id":"fabab6a1.c76f7","type":"function","z":"b4bc3dc8.d6e5d","name":"Increment the delay","func":"\nif (!flow.get('msgPreviousDelay')) {\n var previousDelay = flow.get('msgDelay');\n flow.set('msgPreviousDelay',previousDelay);\n thisDelay = parseInt(previousDelay)+0;\n}\nelse {\n var previousDelay = flow.get('msgPreviousDelay');\n thisDelay = parseInt(previousDelay)+flow.get('msgDelay');\n}\n\nflow.set('msgPreviousDelay',thisDelay);\n\nmsg.delay = thisDelay;\n\nreturn msg;","outputs":1,"noerr":0,"x":1230,"y":320,"wires":[["515f4b35.4afad4"]]},{"id":"dbde0bf1.b1a22","type":"function","z":"b4bc3dc8.d6e5d","name":"Reset the flow","func":"\nflow.set('msgDelay',1000);\nflow.set('msgPreviousDelay',0);\nmsg.reset = 1;\nreturn msg;","outputs":1,"noerr":0,"x":500,"y":380,"wires":[["e9a2f385.de0dc8"]]},{"id":"5bc0493f.72ca1","type":"inject","z":"b4bc3dc8.d6e5d","name":"Inject","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":360,"y":320,"wires":[["dbde0bf1.b1a22"]]},{"id":"e9a2f385.de0dc8","type":"function","z":"b4bc3dc8.d6e5d","name":"Make an array of 60 messages","func":"\nif (msg.reset) {\n var msgArray = [];\n var i=0;\n while(i <= 60){\n msgArray.push(i);\n i = parseInt(i)+1;\n }\n if (msgArray) {\n var msg1 = { payload:msgArray };\n return [ msg1 ];\n }\n else {\n return null;\n }\n}\n","outputs":1,"noerr":0,"x":710,"y":440,"wires":[["cc5c3f39.e1c398"]]},{"id":"cc5c3f39.e1c398","type":"split","z":"b4bc3dc8.d6e5d","name":"Split the array into separate messages","splt":"\n","spltType":"str","arraySplt":1,"arraySpltType":"len","stream":false,"addname":"","x":990,"y":380,"wires":[["fabab6a1.c76f7"]]}]

1 Like