I recently tried using the delay node to rate-limit messages to 1 per day. I had expected the first message to pass immediately, but quickly learned that it holds onto messages that pass until a static interval is reached. So I decided to create a rate limiting subflow. I thought I would share that subflow and ask if anyone else may have a node or similar subflow that may home done it differently from me and what features may differ...
I decided to allow the user to hook into the same timer in different instances by having them set a global variable property. It would be nice though if the default value was a random string so that you're not required to change it unless you explicitly wanted to instances to use the same timer... Any thoughts?
[{"id":"6c0c6334.d0b9dc","type":"subflow","name":"Rate Limit","info":"Initial messages into this flow will immediately pass. Subsequent messages within the set duration (starting after the first passed message) will be skipped.\n\nMultiple subflow instances can use the same timer by setting the same global variable to use. If the value of the variable is true, it means any previous timer has expired and the next message will pass. If it is false, the subflow node will not emit the message (i.e. the message is destroyed).","category":"","in":[{"x":40,"y":80,"wires":[{"id":"1a792ee.e56b151"}]}],"out":[{"x":400,"y":40,"wires":[{"id":"2b21c309.d928bc","port":0}]}],"env":[{"name":"waittime","type":"num","value":"10","ui":{"icon":"font-awesome/fa-hourglass-2","label":{"en-US":"Wait time"},"type":"spinner"}},{"name":"waitunits","type":"str","value":"s","ui":{"icon":"font-awesome/fa-pie-chart","label":{"en-US":"Units"},"type":"select","opts":{"opts":[{"l":{"en-US":"seconds"},"v":"s"},{"l":{"en-US":"minutes"},"v":"m"},{"l":{"en-US":"hours"},"v":"h"},{"l":{"en-US":"days"},"v":"d"}]}}},{"name":"timername","type":"str","value":"rate_limit_name","ui":{"icon":"font-awesome/fa-tag","label":{"en-US":"Global Timer Variable Name to Use"}}}],"color":"#DDAA99"},{"id":"fae935cc.e514d","type":"delay","z":"6c0c6334.d0b9dc","name":"timer","pauseType":"delayv","timeout":"5","timeoutUnits":"seconds","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"x":710,"y":120,"wires":[["1aab977c.c9ae91"]]},{"id":"1ee8e599.d93e12","type":"change","z":"6c0c6334.d0b9dc","name":"Calc Secs","rules":[{"t":"set","p":"delay","pt":"msg","to":"$env('waittime') * 1000","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":560,"y":60,"wires":[["fae935cc.e514d"]]},{"id":"a187ff72.d593","type":"switch","z":"6c0c6334.d0b9dc","name":"wait","property":"waitunits","propertyType":"env","rules":[{"t":"eq","v":"s","vt":"str"},{"t":"eq","v":"m","vt":"str"},{"t":"eq","v":"h","vt":"str"},{"t":"eq","v":"d","vt":"str"},{"t":"else"}],"checkall":"false","repair":false,"outputs":5,"x":430,"y":120,"wires":[["1ee8e599.d93e12"],["ce17b590.337ae"],["25e3671d.ddb368"],["256d77b6.80925"],["a99d1a6a.e11d68"]]},{"id":"ce17b590.337ae","type":"change","z":"6c0c6334.d0b9dc","name":"Calc Mins","rules":[{"t":"set","p":"delay","pt":"msg","to":"$env('waittime') * 1000 * 60","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":560,"y":100,"wires":[["fae935cc.e514d"]]},{"id":"25e3671d.ddb368","type":"change","z":"6c0c6334.d0b9dc","name":"Calc Hrs","rules":[{"t":"set","p":"delay","pt":"msg","to":"$env('waittime') * 1000 * 60 * 60","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":560,"y":140,"wires":[["fae935cc.e514d"]]},{"id":"256d77b6.80925","type":"change","z":"6c0c6334.d0b9dc","name":"Calc Dys","rules":[{"t":"set","p":"delay","pt":"msg","to":"$env('waittime') * 1000 * 60 * 60 * 24","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":560,"y":180,"wires":[["fae935cc.e514d"]]},{"id":"6f982be.34e9fd4","type":"debug","z":"6c0c6334.d0b9dc","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":690,"y":220,"wires":[]},{"id":"2b21c309.d928bc","type":"function","z":"6c0c6334.d0b9dc","name":"set wait to true","func":"global.set(env.get(\"timername\"), true);\nreturn msg;","outputs":1,"noerr":0,"initialize":"// Code added here will be run once\n// whenever the node is deployed.\nglobal.set(env.get(\"timername\"), false);\n","finalize":"","x":280,"y":80,"wires":[["a187ff72.d593"]]},{"id":"1a792ee.e56b151","type":"function","z":"6c0c6334.d0b9dc","name":"skip?","func":"let mywait = false;\nif(global.get(env.get(\"timername\"))!==undefined)\n mywait = global.get(env.get(\"timername\"));\nif(!mywait)\n return msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","x":130,"y":80,"wires":[["2b21c309.d928bc"]]},{"id":"1aab977c.c9ae91","type":"function","z":"6c0c6334.d0b9dc","name":"set wait to true","func":"global.set(env.get(\"timername\"), false);\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","x":860,"y":120,"wires":[[]]},{"id":"a99d1a6a.e11d68","type":"template","z":"6c0c6334.d0b9dc","name":"Error","field":"payload","fieldType":"msg","format":"handlebars","syntax":"mustache","template":"Invalid rate limit units set in subflow properties: {{{waitunits}}}","output":"str","x":550,"y":220,"wires":[["6f982be.34e9fd4"]]}]