Detect when context's variable changes its value

#1

I'm working on a new node that will output a message when a variable receives new value. The format of the message will be similar to:

{
  variable: "the name of the variable",
  oldValue: theOldValue,
  newValue: theNewValue  
}

For this to happen the node need to be notified when someone modifies variable's value trough flow.set(), global.set() or the Change node . To me the obvious way of doing it is to hook the context.set() method (I don't like polling for changes), but I really have no idea how to do it.

Is this possible at all? Or is there already a node that does the same job?

0 Likes

#2

The fact that you need to do this suggests that you are using a context variable where you would be better to send a message. Rather than setting the context variable wherever you set it, send a message to the node that needs to know, with the new value.

Alternatively write the value to MQTT and then subscribe to that topic wherever you need to know about it. Then the node that needs to know will automatically get told. Also, if the variable is required to be persistent over a restart then make the MQTT topic persistent and then the nodes that need to know the value will get informed on startup.

0 Likes

#3

The idea is that the node will generate new message when it detects a variable change. I'm aware of MQTT ways of achieving that. But I don't need MQTT in this case. It is NodeRED runtime related question.

0 Likes

#4

One of the main thoughts behind Node-RED is that you should be able to see what is going on, so messages flow along wires etc. And these events trigger other events. Having invisible connections is not really part of the current thinking.

0 Likes

#5

I see this new node as "IN" node (i.e. without inputs). You subscribe for a variable (a.k.a. topic) and receive notifications from every Set operation. That's similar to MQTT but is more like a pub/sub model for the Context (global or flow). Yes there is a hidden connection between the node and the Context. But this is also true for MQTT node and the MQTT server - the connection between them is also hidden.

The practical side of having such node: there are cases when you need to be notified when a value had been changed and you're interested to see how much is that change. Then build logic like "if the change is bigger than, then do X". Or if the last state was X and the new state is Y, then do Z. I think in most of the cases people use the Function node, write code, store the last state etc. This is error prone.
Why do I want to have this at Context level? Well to achieve simple change detection in most of the cases people use the Function node, write some code, store the last state, compare values etc. So they already have the value stored in the context. So why bother with MQTT and complex custom flows at all? I think such node will be useful to many NodeRED users and will simplify the logic and flows.

My question was is it possible to receive such notifications. If not, then I want to make a proposal for adding capability for subscribing for "context().Set" operations. I think it would not be hard to be implemented. The moment is right since you're implementing variable persistence i.e. you're working / modifying the Context class.

I see this as a new Context API:

context.subscribe(varNameOfInterest, callback);

where callback's signature is: function(oldValue, newValue) {}

0 Likes

#6

No, it is not possible to do with the current API and we're not going to rush anything in at this point with 0.19 ready to ship in the next couple weeks.

I am not in favour of building a pub/sub system (which is what you're proposing) around the Context. As Dave said, the wires in a flow represent the logical flow of events (with specific exceptions for the Status and Catch nodes). The MQTT nodes represent a well understand interaction with an external system.

One of the use cases for the persistent context feature for 0.19 is to allow multiple runtime instances to share a common context. If implementations had to support observability of changes to any value that would greatly complicate any implementation of the context store api.

So no, this isn't something we're going to hold up the 0.19 release for. We can discuss further, but it needs to be done so in full consideration of the changes being introduced and whether it fits with the whole flow-based programming model.

0 Likes

#7

Not in a rush. I'll be happy to discuss the idea. My proposal is based on my overall experience with NodeRED with real life tasks.

0 Likes

#8

What happens if for instance you inject every second on a function that pulls out the value of the variable and this is directed to a rbe node (what makes is that message only will pass if msg.payload has changed, then from then to wherever you wanted to be notified?

Will do exactly what you expect.

Regards

0 Likes

#9

Yeah. But polling. Yuk. :wink:
Then again there was once Object.observe but that got deprecated/removed pretty quick so there must have been fairly good reasons.

You could possibly add a link node next to/ near where it gets written and use the other end of that to expose it where you want

0 Likes