Injecting Messages on a specific node for building approval workflows

Hi,
I want to build an approval Node object.
The idear is, that the node stores the msg object (e.g. in a database) and sends an email to the user.
Once the user confirms or makes a decision, this triggers a continue of the flow.
To reach that, the stored msg object should be (enriched) reinjected in the node (or the next connected node).

Now I'm stucking at the point how to send a message to a specific node.
Is there any API or functionality to
a) get the current NodeID
b) reinject a message exactly into this Node?

Thanks a lot for any help :slight_smile:

It would seem to me you should have a flow with an email-in node that gets the email and you send that to a node to determine if it is valid. If so, you read the data from the db and build the msg and send it to the next place in the original flow

Thanks @zenofmud: I am aware that this possible. But I want to have a "more generic" node-object that automatically "continues" from that node on and also reduces complexity in the workflow management.

so this node needs to also handle the emailing and getting the response back ?

I would like to do the email processing outside of NodeRed. So I want from an external programm to inject a message to a specific node.

You cannot inject a message to any generic node in the flow.

You'll need to identify the points in your flow where you might want to inject a message and add nodes that are designed to be triggered by an external event as and when you want - for example a set of HTTP-In nodes, or MQTT-In nodes.

still looks to me like the approval coming back in would be better starting the "next" section of the process. You can of course group them together using the group functionality

Hi,

You cannot inject a message to any generic node in the flow.

==> I would like to inject a message to a specific node in the flow

The issue of using such a model with get-approval - receive-approval with http-in or mqtt-in is that it prevents me from just dragging in one node that does all the details for me.
I have each time to define an individual endpoint to separate each flow and I can't add this "transparent" in the flow-chain. Thats the reason I would like to do that within one flow and reinject the message if it comes later (maybe even some days) at exactly this position.

But why don't you want to have explicit points in your flow where the out-of-flow approval process occurs? Surely having very explicit points in the flow will make it easier to understand.

Regardless, the point stands that you cannot send messages to arbitrary nodes - messages can only flow over wires.

Simplistically and with very very little consideration to finer detail - one such way might be...

  • store the msg in flow or global context object named "messages", keyed by msg._msgid
    • this msg should probably be tagged with a current approval "stage" (e.g. "stage 1") (or similar)
    • you might also want to add an expiry timestamp to the msg at this point
  • send your email with a defined structure that contains the current processing stage, _msgid and whatever else is required for your external system to understand the current process

at this point your external process does its bit

upon approval / rejection etc...

  • have your external system call an endpoint named /routing (or whatever) and send a payload like { "msgid": "xxxx", "stage": "stage1", "result": "approved" }
  • based on the payload received, retrieve the original msg from the context object
  • remove the msg from the context object store
  • update the msg properties as required, then route it to its next point of processing.

It is at this point :point_up_2:t2: where the routing occurs (depending on the approval / rejection / stage / other criteria) you can switch the msg to any node in your flow(s) (albeit pre-determined routes only - determined by the pre-programmed switching logic and wires in your flow(s) )


Disclaimer I have zero doubt there are much better ways of handling this kind of approval routing. In fact, I dont even like my own suggestion :crazy_face:

If you do go down this avenue...

  • a database should probably be employed instead of context storage.
  • It is NOT necessary to store the message - you only need store a key or the pertinent data (a message can be easily re-created)
  • I have made no reference to integrity of data, no consideration to expired processes, etc etc.

__ its a minefield __

Thanks @dceejay @knolleary and @Steve-Mcl for all your comments :slight_smile: :slight_smile:
I understand that there is currently no way to inject messages directly via API into a specific Flow. That's not so nice for my use-cases (from my point of view).
After reading the blog https://nodered.org/blog/2019/09/20/node-done I was expecting that this should be possible, as it seems that the node.send() seems to be exactly the function I would like to call externally. So is the issue only, that this node-function is not exposed via API?

Let me visualize the only way I think is currently possible (visualization is not great, but should help to understand, I am aware that I can use groups and sub-flows):
Given scenario:
I have 3 independen processes doing a lot of stuff not relevant here. Process A has a 1-step approval process, process B has a 3 step approval process and process C has also a 1-step approval process.
A visualization would look like this:

But I would intuitive like to have a flow like this:

There are 2 things I don't like on the first method:
a) The dependency to the input module, so whenever I add a email-approval-node I have to do a modification on the decision object and a link to the continue of the process (approval-stage-done).
b) The wires are confusing, as there is no wire from request-approval to approval-done but the wires to the decision object. For technical reasons thats clear, but I want to have a generic "approval" node, to perform an abstraction and hide technical details (same as we do using with each node).

Do you see any other option? Do you think that there could be the chance to extend node-red API allow sending a message to a specific node? So far I don't get the difference to input nodes. Actually they send also messages on their position to the next neighbours.

Thank you all very much for your patience with me, sorry for asking questions that might show missing understanding...

Here's another way to do it using a subflow.

  1. Create a subflow to encapsulate the 'getting approval' process.

    The subflow includes an HTTP-In node that sets its url dynamically using a Subflow property - APPROVAL_URL.
    I've given the subflow two outputs - one for approved, one for denied - but of course you could do that however you wanted.
  2. In the Subflow properties, defined two properties:

    APPROVAL_URL is the property used in the HTTP In node. For convenience, this property is derived from another property - APPROVAL_ID. And I have configured the UI for the APPROVAL_URL property to be hidden.
  3. Then, you can add an instance of this subflow wherever you want:

    And when you edit its properties, you can set an identifier for the approval (ie the APPROVAL_ID property defined above:

    In this instance, that would cause the HTTP node to listen on /approval/go-fishing

You'd just need to make sure the APPROVAL_URL property is passed as part of the approval request so the response comes back to the right place.

3 Likes

Thank you very much @knolleary :slight_smile:
Thats a really nice solution allowing me to solve this "challange" for me.

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.