Feature: Add flow.$root for simplified access & add a context that allows for state to be only shared within a single node flow/series

This problem kind of reminds me of angular $scope and $rootscope.. The problem is I have generic sub flows that build on each other and once you get over two levels it becomes very hard to get at the parent, great grandparent, flow states... I just want to pass my common flow state context through all of them and update the parent flow state from grandchildren.

I have a sub flow that sends a notification to Alexa, this is called by a sub flow that turns on or off a switch in home assistant (turn off/on with notification), and then I have sub flows that call this... like turn on when there is motion (with a crazy state machine). Which this one is called as part of a root flow which defines all the identifiers and state I'd need on the flow state. Problem is you quickly need to do $parent.state on the first sub flow but then you have many levels of sub flows... of which you find yourself doing a function node and setting the same variable like this.

flow.set("blah", $parent.blah);

I never used global because from reading multiple pages it sounds like it's across all flows in the entire system and not just the current running flow. If this is not the case then I should just use global and this is not a valid feature request.

The best solution is to pass the data in messages rather than use the context. Then you would save yourself all this trouble.

I was doing that and I hated having tons of extra nodes so I refactored it all. Much cleaner to define it once!

A Flow is represented as a tab within the editor workspace and is the main way to organise nodes.

The term “flow” is also used to informally describe a single set of connected nodes. So a flow (tab) can contain multiple flows (sets of connected nodes).

The terminology is kind of confusing, as a starting out user I thought a flow was just one series of nodes and not the whole sheet. Considering a sub flow has one input and one output as well as a panel can have many different flows in it.. I wouldn't want flow state to be shared by the same panel/sheet. I just want it to be for my single node flow and any of it's sub flows. What works best for this?

Can you define what you mean by that. Also you used the word panel, if you mean tab in the editor then tab is the word to use. Flow context is shared across all nodes in one tab in the editor (not to be confused with dashboard tabs).

I group my tabs by area or feature so this tab Is called closets (manages closet lights) and has multiple flows. By flow, I mean a node that is a series of nodes/sub flows connected together. In the picture below is two different flows.

If you want separate flow context between the two sections you will need to split them onto separate tabs.

That’s insane, I wonder how many people group similar flows sections like me.. I’d need to split this out to about 90 tabs

You could start by setting a prefix to the name so that each part of what you refer to as “flow” is separated by its own prefix in the context.

As I mentioned at the start, if you stick to the node-red way and pass data about in messages, then by avoiding flow and global context you avoid this insanity completely.

1 Like

Would be better to have a context specific to a flow section. I’d think this would be super useful and flow into subflows. Much cleaner and nicer

in the example flow you posted why can't you, in the node that currently sets the context, do

msg.state = {statevar1: x, statevar2: y}
return msg

and then in the subflow pick up the state and use it as required?

2 Likes

While I know a couple situations/my own complex flows where a flow.$root setup would be helpful, for me it’s usually a sign my flow is getting too complicated and needs some restructuring. If it’s too complicated keeping track of where a flow variable is located while writing, try imagining how it is maintaining. For context, I had started nesting up to 3-4 subflows with auth tokens stored in the outer flow context.

Isn’t the whole point of home assistant to use it as a state machine?

The problem with that is I try and treat messages as immutable so I return a new message object per every function node. Seems a context object should flow in each section and I guess it would be really nice having each sub flow use that context. I made a pattern where the sub flow reused parent flow variables or set them from a passed in message.

Definitely feel like the context states are missing a pretty common scenario. Wish we had feature usages so we could see how common this is

If there was a separate context for each group of wired nodes, the management of that context would be complex and unintuitive. There is no unique identifier for such a group of nodes to tie the context to. If a flow is split into two by removing a wire, which of the two halves would keep access to the existing context and which would get a new context assigned?

I do appreciate what you are trying to do with the subflows, and maximising their reuse. We've gone someway to help with this in 1.0, with the ability to provide per-instance env vars on subflows.

You've raised an interesting question about how a subflow can reference a top-level flow context when the subflow doesn't know how deeply nested it is.

Whether adding a way to reference that top-level directly is the right approach will need some thought. There is a trade-off between the various approaches to solving it with the options available today. Passing state in and out via the message and keeping the context access to the top-level is certainly one valid approach to take. Whether that fits in all scenarios is another matter.

As ever, this is a good discussion to have to help us understand more about what users are trying to do and whether we provide the right set of tools to do it.

That is not generally the recommended approach. It would break certain node pairs such as the split/join nodes, or HTTP In/Response nodes, as they rely on key properties existing on the message throughout the flow.

I tried to solve this in my nested subflows by adding an instance env var to each that needed access to an outermost flow variable by posing it as “how is this variable known in the flow that uses this instance”, then accessing it through the parent level, and keep the subflow able to function regardless of how deeply it is nested. I kept losing track of it however, and even with that level of logic applied and drawing it out on paper I kept making mistakes. In the end I decided to take these deeply nested subflows and change them into a couple custom nodes instead to improve maintainability. Even when already setting states on the message object as described above it’s hard to keep track of what you’re doing. And even with a flow.$root syntax added it would stay complex in other aspects, so improving it with a custom node to handle those nesting levels was my preferred choice.

I would be interested to know why, it prevents you passing data down the line which can be a very useful technique.

I’m traveling today but will respond again with all details if I missed any. Seems like we should know but that we don’t know a flows section when they are all wired together with literal wires. The first nodes that executes would just create a unique identifier for that section context and all nodes in the section would use it/get it passes maybe in a msg header.

I haven’t ran into any issues by returning new message objects. I find it cleaner than to reuse an object, then I always know the exact state is being passed into the next node and some Function nodes become one liners just returning a new payload.