[Feedback Wanted] Flows Sequence

Hi Team,
I would like your feedback on the reasoning that follows.

NR is intended to be used more and more in the industrial sector but the notion of priority in the flows routine is missing. Like flat sequence in LabVIEW or OB40/OB100 in TIA Portal.

Let me explain: an industrial process contains several steps, the process starts with initialization then it is ready to start then production then... Which implies that the routine is carried out according to a sequence.
PS: The structure may vary and be more complex but that is not the point of this subject.

When NR starts, all flows are started at the same time, so it is not possible to create a sequence of flows.

Would it be possible to create a pre-flow and a post-flow?

This would work as follows (if they are used):

  1. Starting NR
  2. Loading all flows
  3. Starting the pre-flow
  4. Waiting the end (a sort of done output)
  5. Stopping the pre-flow
  6. Starting flows
  7. Flows started
  8. Stopping flows (as current stop/restart)
  9. Starting the post-flow
  10. Waiting the end
  11. Stopping the post-flow
  12. NR stopped

I don't know if it will be in high demand but the routine is more part of a real industrial process.

A concrete use case is the FlowFuse device agent, it would be useful to correctly start/stop the instance when a new snapshot is received.

Thanks for your feedbacks.

PS: It's more of a reflection than a FR for now.

Not quite true of course, you can sequence flows - but you have to do the sequencing. It is easy enough to arrange gates that start/stop flows either by date/time or by a flag set by another flow or even one entered by a person.

Would 1 single pre/post be useful though? I would think that most industrial processes - certainly ones that I've modelled in the past - will have many stages, often with complex interlocks and interactions.

A bit like a sub-flow that is called at a specific time? If so, the problem is that the nodes in it have been instantiated. What I'm looking for here is a flow that executes for the time it takes to call done and then stops - the nodes of this flow are only instantiated when the flow is in the right sequence.

NR not being cyclical it would be too complex (I think) to create a real priority - a sequence of three (pre - prod - post) would already be a good structure

On different note, what does that mean "a flow is started" - I was wondering this because what actually gets started:

  • inject node with an insert upon start
  • http-in node
  • cron-plus node
  • ...

does a "flow" actually get started? Or do nodes in flows get started?

I don't know exactly but this question made me wonder.

Aren't you referring to a state-machine ? There are nodes available for these kinds of state flows.

A node is defined in a function. The runtime will start by loading all these functions then calling them (config-node first then the normal ones). When all functions have been called, the runtime triggers flows:started event.

The principle of the sequence is to freeze what is happening inside as long as it is not the right step - when the sequence goes from pre to prod the nodes contained in pre-flows are closed and others are called.

Thanks but this must be done at the runtime level, not at the node level.

It looks like this - that's why I'm simplifying it into just three steps:

This diagram is a state machine, did you look at the node I linked to ?

Yes, but the problem is that when the runtime is stopped, this node is closed regardless of what machine state it is in.

But that isn't how Node-RED works is it. Nodes are initialised when Node-RED starts, an instance is instantiated as soon as they are part of a flow and Node-RED starts. These are fundamental to the structure.

When designing Nodes, you need to take that into account.

If you want code that only instantiates when a flow runs, this is not impossible thanks to the flexibility of node.js but nodes would have to be specifically designed to do that. And it brings its own set of issues such as startup time.

That is what I was intimating.

That is simply a matter of saving state sensibly though isn't it. If a specific state machine node doesn't do it, you could always create your own state-machine flow.


I think that you need to think through the problem from a Node-RED architecture perspective. As far as I can see, Node-RED is perfectly capable of constructing what you are asking for but it will not look like a flow created in LabVIEW which works in a very different way.

For me it sounds more like an initialisation phase - config node cannot be executed but it can be initialised. Once all nodes have been initialised or setup, then the flows:started triggers things like "inject after X seconds" on the inject node.

Sorry, I expressed myself badly (dyslexic too :sweat_smile:)

What I'm trying to achieve when NR starts is a flow that runs until done is called then stops/freezes then standard flows start. When NR stops, standard flows stop then a final flow starts and executes until done is also called and finally stops and the runtime is stopped.

I don't know if I should use initialize or execute but the node cannot trigger anything until it is in the right phase.

No really, this is the principle of initialization and shutdown - it is only executed once when the machine starts/stops respectively

This is mostly possible. Even before shutdown - as long as Node-RED actually shuts down, that, of course, is not always the case. Node-RED may simply go away for a number of reasons and in that case, it cannot shut down so you need to take that into account.

But custom nodes would currently be needed to handle this.

Nodes are executed/initialised on startup. Specific methods of the Node are then run at different stages. It is fairly trivial to make a node with a specific gate. That gate can easily be set to take a phase as an input not simply an on/off.

If you built Node-RED to have a single entry and exit phase, it would have limited use I think but might have some interest.

Yeah, I mean a normal shutdown

So when the runtime starts:

  1. Loading all flows
  2. Starting the pre-flow
  3. pre-flow started
  4. done called
  5. Stopping the pre-flow (close event)
  6. Starting normal flows
  7. Flows started => NR started

When the runtime stops:

  1. Stopping normal flows
  2. Starting the post-flow
  3. post-flow started
  4. done called
  5. Stopping the post-flow
  6. post-flow stopped => NR stopped

Well, it would be possible. I think we would want to hear from Nick as to whether he thought it a good idea though. Personally, I wouldn't want this to take away from other core development that I think is more critical for change but other than that, I can't see that it should be harmful.

2 Likes

Sorry, what do you mean?

I add that this is an "Industrial" case, even me have no use for it at the moment :joy:

I mean that I wouldn't want people spending time on developing it or having its development distract from other Node-RED releases until other priority developments have taken place. That is simply my opinion, especially given that Node-RED's node.js baseline is already 2 major versions behind.

1 Like

Of course, this is why I am not making a request but rather seeing if it is possible because it could be interest the industrial world

I'm sure you're aware of those details:
No flow was ever loaded at runtime start: It's a number of nodes (scripts) that is loaded.
No flow was ever started: It's usually one node or more that initiates a sequence of events.
Currently all nodes are loaded & then sit idle - until an event triggers them.
Nodes may run logic before they are triggered!
...

Looks like there's a lot of work to be done to change the current architecture to act in accordance to that pattern.

redNodes.loadFlows() => storage.getFlows() => Reading the flows.json file

redNodes.startFlows() => setFlows => Flow.create() for each flows then Flow.start() each flows.

Before starting all the active flows it would be necessary to start only the pre flow then the done event triggers the current start of the active flows. The heaviest is this event - that would be something like:

redNodes.loadFlows()
  .then(() => {
    redNodes.startPreFlow()
      .then(() => { redNodes.startFlows() })
      .catch(function(err) {})
  })
  .catch(function(err) {});

It will indeed be necessary to add logic but it does not modify all the current logic

What would happen if a message was sent to a non started flow?