Messages sent via "On Start" only reliable on partial deploy but not during " nodered.service" start. Possible?

Hi All,

I believe the subject already says it really.
I'm running latest Node-RED release with Node 18 and I just finished a big bunch of code that is supposed to run whenever I deploy, NR crashes (luckily rarely happens) or when I have to reboot the underlaying server.
For me it seems like sending messages from the new code that I added to the "On Start" tab of a function node is only executed during deploy and flow restart but it's not executed when the whole nodered.service starts up.
Is that possible?

No, at least it should not be possible.

Show us what you have in On Start and how you know it is not running.

Thank you!
That would be a massive piece of code but I'll create something simple quickly.

Simple flow.
It should show both in the debug window and also node status.
I added a delay to make 100 % sure I don't miss anything during start and the Web UI is surely fully initialized after 15 seconds.

So this doesn't fire anything when I do a systemctl restart nodered.service

image

[
    {
        "id": "30c5668f02ac9e3d",
        "type": "function",
        "z": "5357e3dfed4a478e",
        "name": "OnStartTest",
        "func": "return;",
        "outputs": 1,
        "timeout": 0,
        "noerr": 0,
        "initialize": "let out = {};\nout.payload = \"Test\";\nnode.send(out);\nnode.done;\nreturn;\n",
        "finalize": "",
        "libs": [],
        "x": 450,
        "y": 320,
        "wires": [
            [
                "a20b460a2829470a",
                "755406ef6e5ddfef"
            ]
        ]
    },
    {
        "id": "a20b460a2829470a",
        "type": "delay",
        "z": "5357e3dfed4a478e",
        "name": "",
        "pauseType": "delay",
        "timeout": "15",
        "timeoutUnits": "seconds",
        "rate": "1",
        "nbRateUnits": "1",
        "rateUnits": "second",
        "randomFirst": "1",
        "randomLast": "5",
        "randomUnits": "seconds",
        "drop": false,
        "allowrate": false,
        "outputs": 1,
        "x": 640,
        "y": 320,
        "wires": [
            [
                "3301e1068bb52a4f"
            ]
        ]
    },
    {
        "id": "755406ef6e5ddfef",
        "type": "debug",
        "z": "5357e3dfed4a478e",
        "name": "Debug1Test",
        "active": true,
        "tosidebar": true,
        "console": false,
        "tostatus": true,
        "complete": "payload",
        "targetType": "msg",
        "statusVal": "payload",
        "statusType": "auto",
        "x": 650,
        "y": 420,
        "wires": []
    },
    {
        "id": "3301e1068bb52a4f",
        "type": "debug",
        "z": "5357e3dfed4a478e",
        "name": "Debug2Test",
        "active": true,
        "tosidebar": true,
        "console": false,
        "tostatus": true,
        "complete": "payload",
        "targetType": "msg",
        "statusVal": "payload",
        "statusType": "auto",
        "x": 830,
        "y": 320,
        "wires": []
    }
]

If I change a line on the function node and deploy I see the test message twice (immideately and after 15 secs)

It should & probably does, however, there may be a timing issue due to attempting to "send" a message before the other nodes in your flow have initialised. It may even be sent but

the simplest way is to use an inject set to trigger on startup to perform initialisations.

NOTE: I forget whether the on start code is even permitted to send messages :thinking:


to prove what I am saying, do an node.error('testing 123') in the On Start function - you will see this in the Node-REd console output.

It is, I use it a lot and it works during deploy.

I added it to my code. No output :frowning:

let out = {};
out.payload = "Test";
node.send(out);
node.error('testing 123');
node.done;
return;

node.done is not needed (and it doesnt do anything without (brackets) anyhow)
return is unnecessary if it is the last statement

So I did a test using:

let m = {};
m.payload = "Test Payload";
node.send(m);
node.error('deliberate node.error');

And sure enough i DO get a message in the console log.

image

However the results are mixed, as I expected.

  • FULL Deploy
    • The debug node does NOT receive a message
  • Modify func node then do a NODE ONLY deploy - the msg is sent.
  • recreate the function AFTER all other connected nodes, deploy (Full or Node only) and it DOES send

Proving that the on start occurs in order of node creation (the order the node is stored in the flow)

This, is not a reliable way to use "On Start" IMO. As i said before, to ensure all nodes are initialised and running, you should use an inject (as the inject wont fire untill the "Flows Started" message (i.e. all nodes are initialised)

Demo:

Demo flow (note how the function "I was added first" is at the top and the "I was added 2nd last" is 2nd from the bottom!

[
    {
        "id": "99ad09d05093ee4a",
        "type": "function",
        "z": "3642c7ee286f9c17",
        "name": "I was added first",
        "func": "\nreturn msg;",
        "outputs": 1,
        "timeout": 0,
        "noerr": 0,
        "initialize": "let m = {};\nm.payload = \"Test Payload 2\";\nnode.send(m);\nnode.error('deliberate node.error 2');\n",
        "finalize": "",
        "libs": [],
        "x": 300,
        "y": 480,
        "wires": [
            [
                "44a542c2d5181115",
                "0484dedcdd96f7e7"
            ]
        ]
    },
    {
        "id": "f22eda38365a0e9b",
        "type": "debug",
        "z": "3642c7ee286f9c17",
        "name": "I will work",
        "active": true,
        "tosidebar": true,
        "console": true,
        "tostatus": true,
        "complete": "payload",
        "targetType": "msg",
        "statusVal": "payload",
        "statusType": "auto",
        "x": 630,
        "y": 260,
        "wires": []
    },
    {
        "id": "6e2f83184fe48a05",
        "type": "delay",
        "z": "3642c7ee286f9c17",
        "name": "",
        "pauseType": "delay",
        "timeout": "10",
        "timeoutUnits": "seconds",
        "rate": "1",
        "nbRateUnits": "1",
        "rateUnits": "second",
        "randomFirst": "1",
        "randomLast": "5",
        "randomUnits": "seconds",
        "drop": false,
        "allowrate": false,
        "outputs": 1,
        "x": 480,
        "y": 380,
        "wires": [
            [
                "6a9a28c3aa062dc8"
            ]
        ]
    },
    {
        "id": "6a9a28c3aa062dc8",
        "type": "debug",
        "z": "3642c7ee286f9c17",
        "name": "I will work after delay",
        "active": true,
        "tosidebar": true,
        "console": true,
        "tostatus": true,
        "complete": "payload",
        "targetType": "msg",
        "statusVal": "payload",
        "statusType": "auto",
        "x": 670,
        "y": 380,
        "wires": []
    },
    {
        "id": "44a542c2d5181115",
        "type": "delay",
        "z": "3642c7ee286f9c17",
        "name": "",
        "pauseType": "delay",
        "timeout": "10",
        "timeoutUnits": "seconds",
        "rate": "1",
        "nbRateUnits": "1",
        "rateUnits": "second",
        "randomFirst": "1",
        "randomLast": "5",
        "randomUnits": "seconds",
        "drop": false,
        "allowrate": false,
        "outputs": 1,
        "x": 470,
        "y": 540,
        "wires": [
            [
                "f53dbbe2cc034447"
            ]
        ]
    },
    {
        "id": "0484dedcdd96f7e7",
        "type": "debug",
        "z": "3642c7ee286f9c17",
        "name": "I will not work",
        "active": true,
        "tosidebar": true,
        "console": true,
        "tostatus": true,
        "complete": "payload",
        "targetType": "msg",
        "statusVal": "payload",
        "statusType": "auto",
        "x": 640,
        "y": 480,
        "wires": []
    },
    {
        "id": "f53dbbe2cc034447",
        "type": "debug",
        "z": "3642c7ee286f9c17",
        "name": "I will not work",
        "active": true,
        "tosidebar": true,
        "console": true,
        "tostatus": true,
        "complete": "payload",
        "targetType": "msg",
        "statusVal": "payload",
        "statusType": "auto",
        "x": 640,
        "y": 540,
        "wires": []
    },
    {
        "id": "c2c7afc08e883d45",
        "type": "function",
        "z": "3642c7ee286f9c17",
        "name": "I was added 2nd last",
        "func": "\nreturn msg;",
        "outputs": 1,
        "timeout": 0,
        "noerr": 0,
        "initialize": "let m = {};\nm.payload = \"Test Payload\";\nnode.send(m);\nnode.error('deliberate node.error');\n",
        "finalize": "",
        "libs": [],
        "x": 300,
        "y": 320,
        "wires": [
            [
                "f22eda38365a0e9b",
                "6e2f83184fe48a05",
                "1dd9f3f48b9f1d7d"
            ]
        ]
    },
    {
        "id": "1dd9f3f48b9f1d7d",
        "type": "debug",
        "z": "3642c7ee286f9c17",
        "name": "I will NOT work (last node in flow)",
        "active": true,
        "tosidebar": true,
        "console": true,
        "tostatus": true,
        "complete": "payload",
        "targetType": "msg",
        "statusVal": "payload",
        "statusType": "auto",
        "x": 700,
        "y": 320,
        "wires": []
    }
]
1 Like

Thanks for that! I forgot the brackets only with the testing node.
I hardly ever use return msg since I mainly send async messages so I use node.done() and return in several places in the code and adding it here is just because of a habit.

Wow, many thanks for that!
Honestly this makes it completely unreliable for me but since I always do partial deploys and hardly ever any service restarts I actually never noticed that "On Start" only works for sending messages in a predictable way during partial deploys (if I understood your post correctly).

So, thanks again, that means I will stop using that tab completely for sending any messages. I can't remember reading anything about this limitation in the documentation so I just thought it was a convenient way.

I think it isn't that the sending doesn't work, but that in a full deploy, other nodes may not have been initialised and so are not ready to receive messages, so the message gets lost. When you do a partial deploy of, for instance, the function node, but the other nodes are already deployed and waiting for messages, then it works.

Exactly how I understood the post of @Steve-Mcl .
The problem is since there is no order displayed the only way to check would be to into the JSON export but that would be such a pain in the backside that I rather stop sending any messages via "On Start".

Changed the title to make it less confusing

1 Like

OK, I misunderstood, I read it to mean that you thought the sending was failing, whereas it is actually the receiving that is failing.

Absolutely, just don't do it.

It was mentioned in a previous post by @knolleary, that the initialization order is always tab by tab, left to right (and within a tab, by node creation order). I believe if you put your startup node on the last (rightmost) tab, it will ensure all the other nodes are initialized by the time it sends its startup messages.

Until you forget and add a new tab in a years time. It really isn't worth it, just use an inject node triggering on startup to do it.

I agree :slight_smile:
Just need to ensure the delay time on the inject node is big enough. 0.1 seconds is sometimes not enough.

I haven't seen a problem with that setting.

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.