I have a sequence that is meant to be called in parallel from different devices.
There is a wait-until node that should evaluate the current state of a dynamically injected entity, derived from a msg.object property — which is different for each device.
Since the wait-until node cant handle multiple messages independently (it only passes the last one), I thought I could wrap the logic into a subflow.
My reasoning was that every msg passed into the subflow would get its own execution context and be evaluated independently.
However, this doesn’t work as expected. Am I misunderstanding how subflows work? Does a subflow share state between invocations, or should it be isolated per message?
Yes, I'm afraid so. Each instance of a subflow is a new flow. It is a bit of a misnomer really in some ways, it is more of a template flow.
To do what you want, use a flow that starts with a link-in and ends with a link-out set to return to the calling link-call node. Use a link-call node wherever you want to feed messages into that flow fragment.
I don't think link-call will do what you want either. If there are multiple messages that need to use the wait-until node would it be ok to queue them and only pass to the wait node once the previous one has been actioned?
As I understand now, its not a real template that is invoked for every message but more like a copy that is deployed in identical referenced copies. So if I send to messages into the same subflow node, they will share the environment, if i send it into two different ones, they wont?
@Colin: No I cant just queue the messages, cause this would mean every entity is waiting for the prior ones. I need parallel execution. So atm I do see 2 possibilities
Just make an identical sequence for every device and make a seperation for each device. This is kinda cluttered and redundant, but at least I can use a subflow to reduce the complexity for maintainance.
do not use wait until but some other logic like comparision to the current state and looping with a delay + timeout. This would probably work but is a dirty workaround imo.
Well, for starters, Node.js doesn't really do parallel operations, it has a single, looping thread. So you can't really get parallel operations unless you create something that creates multiple threads (which is possible in node.js but I'm not aware of a Node-RED node that does that).
So unless I've misunderstood, this is a normal flow in Node-RED. Every time you send a message to a node, it runs its input function afresh. This can be as close to parallel as Node.js is able to achieve since the function will be added to the loop's queue. Node.js (and JavaScript in general) is super efficient at handling the job queue of the loop such that things often seem to be happening in parallel.
While I'm not familiar with the wait-until node, I'm assuming that you want to do processing based on multiple inputs from each device?
Again, this is standard stuff for Node-RED and you can pass multiple device messages into a common node. But if you want to be able to process based on previous messages, you need to retain the data from those messages. There are lots of ways to do this and you would need to explain more about what processes you are trying to achieve. But in general, personally, I typically use a function node and use context variables key'd on the device identifier. Context variables are constrained to the node that creates them and are retained between executions of the node.
Many different devices will broadcast via the input rfx nodes and they are split into three processes that normalise the data and track known and unknown devices (From my location, I can pick up hundreds of devices from surrounding buildings!). So I can easily add a new known device simply by keeping a record of its id.
In the first post, @dierochade asserted that you could only send one message at a time to the wait-until node. If that is correct then it is necessary to wait until it has finished processing one message before sending it another one.
Well I did not mean real time execution, but just that i cannot simply wait forever.
I do not use it much, but in this use case its quite convenient:
The logic is part of my heating control. it has 8 devices and basically runs a schedule that has a value every 15 minutes. I do a lot of tweaking on the schedule like adjustment to presence detection or weather forecast
.
The thermostats have an manual mode, so you can set a fixed temperature. They have the ability to manually set a temperature directly at the device, but stay in schedule mode nonetheless.
I have kinda gate/block that handles these cases like open window or a manual change locally on the device. These values have precedence over the (adjusted) schedule and should remain untouched, but the former only for a limited time etc.
On the other hand, if I close the window or switch to auto mode or enough time since a manual change has passed, it triggers the asignment of the schedule.
For my usecase it has been easy, responsive and reliable to check these events (and the regular 15 minute call) for conditions like "schedule mode" and "unblocked " (for other reasons) and do not let the message pass to assign the scheduled temperature before these conditions are fullfilled. For this I use the wait until node (with a timeout).