create new _msgid from a function node

1,675 views
Skip to first unread message

iurly

unread,
Oct 30, 2017, 12:00:37 PM10/30/17
to Node-RED
Hi,

I was expecting two brand new messages created from within a function node, to have unique _msgids:

[{"id":"12ca8b0b.cb49dd","type":"function","z":"52115b7e.28bf34","name":"msg","func":"msg1 = { cmd: \"one\", topic:\"one\", payload:\"one\", _msgid: \"266c0e6c.d993f2\" };\nmsg2 = { cmd: \"two\", topic:\"two\", payload:\"two\"};\nreturn [msg1, msg2];","outputs":"2","noerr":0,"x":510,"y":200,"wires":[["e80ace03.ae3ae"],["d48a55d0.e344b"]]},{"id":"809918c3.81aea","type":"inject","z":"52115b7e.28bf34","name":"","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":false,"x":300,"y":200,"wires":[["12ca8b0b.cb49dd","fbec44a0.771e1"]]},{"id":"e80ace03.ae3ae","type":"debug","z":"52115b7e.28bf34","name":"","active":true,"console":"false","complete":"true","x":630,"y":180,"wires":[]},{"id":"d48a55d0.e344b","type":"debug","z":"52115b7e.28bf34","name":"","active":true,"console":"false","complete":"true","x":630,"y":220,"wires":[]},{"id":"fbec44a0.771e1","type":"debug","z":"52115b7e.28bf34","name":"","active":true,"console":"false","complete":"true","x":630,"y":140,"wires":[]}]

To my surprise, I couldn't find a way to have unique _msgid: the three debug nodes always show the same value.
What's the reason behind that? Is there a way I could create a brand new _msgid?

The reason I'm asking is because I'm getting weird behaviors from a subflow I wrote.
The subflow (which should ideally be a node, but I figured it'd be easier to start with a subflow for fast prototyping) does some serialization by storing a messages in a queue (global variable) and pulling it out whenever a response is received.
Indeed, I'm getting duplicated messages and I suspect I'm creating weird loops due to the _msgid being stored and duplicated.

Any ideas?
Thanks

Julian Knight

unread,
Oct 30, 2017, 6:12:06 PM10/30/17
to Node-RED
You can delete it, Node-RED recreates it when you pass to the next node. Not aware of any such issues though. Are you sure you aren't falling foul of the fact that msg's are passed as references between nodes? That does occasionally cause issues where changing a msg property has unintended consequences.

iurly

unread,
Oct 31, 2017, 2:58:54 AM10/31/17
to Node-RED
Hi Julian,

thank you for your answer.
I was pretty sure msg's would be passed by reference, that's why I tried to create brand new messages instead of reusing msg.
Indeed, I tried what you said and got even more surprising results.
With reference to my previous example flow, here's some versions of the function code:

Case 0:
var msg1 = { cmd: "one", topic:"one", payload:"one", _msgid: "266c0e6c.d993f2" };
var msg2 = { cmd: "two", topic:"two", payload:"two"};
return [msg1,msg2];

===> Here the same input _msgid is copied to both outputs. Notice how the value of _msgid manually set within msg1 is always ignored.

Case 1:
var msg1 = { cmd: "one", topic:"one", payload:"one", _msgid: "266c0e6c.d993f2" };
var msg2 = { cmd: "two", topic:"two", payload:"two"};
delete msg._msgid;
return [msg1,msg2];

===> Here msg1 and msg2 have a different _msgid than the input one. However, they're both the same. Notice how I'm deleting it from the source message.

Case 2:
var msg1 = { cmd: "one", topic:"one", payload:"one", _msgid: "266c0e6c.d993f2" };
var msg2 = { cmd: "two", topic:"two", payload:"two"};
delete msg._msgid;
node.send([msg1,msg2]);
return null;

===> Here again, as in case 0, _msgid is copied over in spite of being explicitly deleted. Same happens if you have two separate send's
[msg1, null] and [null, msg2].

Could anyone please shed some light on what's going on here?
What would be right approach to "creating" new messages?

Thank you!

steve rickus

unread,
Oct 31, 2017, 10:41:45 AM10/31/17
to Node-RED
Indeed, I was surprised that there seems to be no way to override the msg id -- so I started digging through the 80-function.js file...

When the function node receives a msg, it creates a new "sandbox", passing in the function code to be run. Here is the relevant code:

        var context = vm.createContext(sandbox);
        try {
            this.script = vm.createScript(functionText);
            this.on("input", function(msg) {
                try {
                    var start = process.hrtime();
                    context
.msg = msg;
                   
this.script.runInContext(context);
                    sendResults
(this,msg._msgid,context.results);


So it's clear that no matter what the returned msg looks like, the original _msg.id is applied to the msg object leaving the function node. This is by design, no doubt, and would need enhancement by the core team in order to be overridden.

There is an internal send(id, msg) function that is not available from within the sandbox -- perhaps that could be made available as an overloaded way to send out new msgs from your function code. Then you could do something like this in your function:

var msg1 = { cmd: "one", topic:"one", payload:"one" };

var msg2 = { cmd: "two", topic:"two", payload:"two" };


node
.send(RED.util.generateId(), msg1); // new random id
return msg2; // uses original id

Of course, only Nick could decide whether that is feasible and/or advisable.
--
Steve

Nick O'Leary

unread,
Oct 31, 2017, 10:48:29 AM10/31/17
to Node-RED Mailing List
The reason the Function node ensures all messages sent by a Function have the same _msgid as the message it received is so that messages can be traced through the flow.

If you want a your own unique message identifier at your application level that has a different characteristic to _msgid, you should add your own property to do that. Ultimately, its just a random number.

Nick

--
http://nodered.org
 
Join us on Slack to continue the conversation: http://nodered.org/slack
---
You received this message because you are subscribed to the Google Groups "Node-RED" group.
To unsubscribe from this group and stop receiving emails from it, send an email to node-red+unsubscribe@googlegroups.com.
To post to this group, send email to node...@googlegroups.com.
Visit this group at https://groups.google.com/group/node-red.
To view this discussion on the web, visit https://groups.google.com/d/msgid/node-red/525b1fcc-3a19-4edc-b714-148e253fdbe7%40googlegroups.com.

For more options, visit https://groups.google.com/d/optout.

Gerlando Falauto

unread,
Oct 31, 2017, 1:09:53 PM10/31/17
to node...@googlegroups.com
Thank you Nick.
As a matter of fact, I was actually explicitly setting it, yet I would see the same id as I was receiving in input.
The only meaningful way I found to affect the outgoing _msgid is to delete it from msg (regardless of whether msg was being sent or not). In order for this to work though, I have to use the return statement. Using node.send() will retain the value from the input in any case.
Is this the expected behavior? 
Thank you.

You received this message because you are subscribed to a topic in the Google Groups "Node-RED" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/node-red/pIIZQmYyYFc/unsubscribe.
To unsubscribe from this group and all its topics, send an email to node-red+unsubscribe@googlegroups.com.

To post to this group, send email to node...@googlegroups.com.
Visit this group at https://groups.google.com/group/node-red.

Julian Knight

unread,
Nov 2, 2017, 9:07:54 AM11/2/17
to Node-RED
What Nick is saying is that you shouldn't be using _msgid for this purpose. The naming convention also implies this. While I also hadn't expected to see what you found, I can see Nick's point and it makes sense.

Simply add a msg.msgid property instead and process that way. You can default it to _msgid and overwrite as needed.
To unsubscribe from this group and stop receiving emails from it, send an email to node-red+u...@googlegroups.com.

To post to this group, send email to node...@googlegroups.com.
Visit this group at https://groups.google.com/group/node-red.

--
http://nodered.org
 
Join us on Slack to continue the conversation: http://nodered.org/slack
---
You received this message because you are subscribed to a topic in the Google Groups "Node-RED" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/node-red/pIIZQmYyYFc/unsubscribe.
To unsubscribe from this group and all its topics, send an email to node-red+u...@googlegroups.com.

To post to this group, send email to node...@googlegroups.com.
Visit this group at https://groups.google.com/group/node-red.
Reply all
Reply to author
Forward
0 new messages