Custom node development help (prevent wiring 2 injects to same node/determin running state of node/take care of proper functioning when facing multiple injects)

Hello i'm having a little trouble in understanding which options i have, in making my custom devloped nodes robust for use.

Here the scenario given 3 custom nodes without further implementation details:
Node A(Type inject)
Node B(type inject)
Node C(long running complex process (including http calls and signalr callback actions at given points) which can be used either from node A or B)

Question 1 :
How can i prevent a user from wiring more than 1 node(A or B) to node C.
Or atleast warn/error in the editor if more than 1 wire was attached.
Question 2:
If it's not possible to hinder wiring more than 1 node to C how do i take care that node C executes it's process correctly until the end for n injects it's facing simultaniously.

Any help would be much apreciated.

That is not a design pattern Node-RED supports (by design)

My question is why would you want to? If your node is written without using context or shared data, there should be no reason to inhibit multiple consecutive inputs.

This "long running complex process" needs to be placed into an async operation. Otherwise it will block the whole execution chain. The only thing you need to ensure is to tell NR when the async op is done().
If it's an async operation, it shouldn't matter, how offen this operation is being triggered.

I released a new node that may help here :nerd_face:

node-red-semaphore-plus (node) - Node-RED (nodered.org)

So i guess i have to explain further.

The process that gets started interacts with a machine.
Until the machine is finished with the processing there should be no other possibility to interact with that machine until it's done and ofcourse the followup nodes in the flow are executed.

By design i still can attach a second inject and trigger that now as well okay, but that should be blocked somehow, and since node-red isn't going to take care of it i have somehow (that's where i need help in figuring out if that's even possible).

Scenarios i want to prevent from happening:
A or B are attached to 1 C node multiple times and A or B are started multiple times.
A or B are attached to 1 or more C nodes and are executed multiple times.

If you need to control access to a resource in the node its self (for public users), check the source of my previous node comment

it employs @shopify/semaphore - npm (npmjs.com)

That sounds like you are building something very bespoke and inflexible. The idea of node-red is to provide "building blocks" - nodes that are fairly atomic - they should do one thing (and do it well). Users then put these building blocks together to make something bespoke (like the node you are describing). The beauty of this design means any bugs can be quickly and easily fixed right there in the flows without having to wait for a complex node to be fixed.

If you insist on taking this path, then your options come down to implementing your own busy flag inside of the nodes code. Set it true when working & ignore it (or raise an error) if a new msg arrives while busy is true

Yeah the whole idea in using node-red is somehow, develop nodes for the enduser,
and give them the possibility to hook inside certain steps(which ain't supported by us or not part of our product and ofcourse would need a manual) and execute own flows in between those points.

E.g. listen on certain IO changes and do something with a other device when a condition is met if not do something else etc. etc.

And since most of those things tend to be repetetive with smaller adjustments by provided inputs the enduser can take care of, it sounded like a good idea to use node-red for that kind of automation.

Given the fact the machine i'm concerned about can't do multiple things at the same time just one after another i still need a way to control multiple executions.

Don't know if a simple busy flag will prevent that anyway.

That's why i asked if it's even possible to:
Hinder wiring a node multiple times to a other in certain cases.
Notify node-red that my processing node is already busy and hinder execution of any other custom flow that includes this processing node until a complete flow is done.

Since i'm just developing i have to take care of the enduser interacting with what i develop, and i stumbled over described problem.

Any guidance if it's somehow achiveable would be highly apreciated.
If not than we need to take a other route.

As I said, no, not a design pattern Node-RED supports (and IMO, it is all the better for that).

Sure it will. If busy === true then don't do things. It won't help with the wiring but importantly it will prevent a 2nd msg triggering this long closed process for a 2nd time. (NOTE: when i said use a busy flag I was referring to the server side part)

I'll give it a shot and refactor accordingly, thanks.

If you don't want to ignore messages while the first operation is proceeding then you can queue them inside your node instead.

Thanks, i was playing with that thought as well.
I might make it an additional option inside the node edit dialog itself and based on true/false value of that option i decide on if i queue the messages or not.
Will need to see what the requirements are exactly and if we want to support that, or not.

Unless I've misunderstood.

If you want to allow users to add custom parts while controlling access to a device, you probably want and entry and an exit node.

The entry node would have a config that sets the device being controlled. It would also have a flag so that the entry is closed once a trigger enders.

The exit node would reset the flag so that the entry reopens. It would also receive whatever output comes from the users flow which was triggered by the entry.

In between, you could allow pretty much anything.

I think that there are already some nodes in the library that operate in a similar way. It is also a little similar to the http-in/-out nodes.

So just a little bit of reference what i did so far to have a little controle over described problem.

In case it could be solved otherwise please feel free to share some sources or point me to there.

Step 1:
Have a service that keeps the state busy/idle which is consumed in this long running process.
Have a constructor where you can pass a instance of RED in this service something like so:

class StateService{
    _red;
    _state;
    constructor(RED) {
        this._red = RED;
    }

    setState(state) {
        this.machineBusyState = state;
        var event = {
            id: 'FanzyUniqueEventGosHere',
            retain: false,
            payload: {
                state: state
            }
        };
        this._red.events.emit("runtime-event", event);
    };
    getState() { return this._state; };
}
module.exports = StateService;
  1. Adapt the long running process slightly, and when my stateservice gets instanciated pass RED instance inside
    When process is busy set to busy
    When process is done set to Idle
  2. Make use of ressources folder for custome js that can be consumed in HTML Files.
    What i did here was something like create my own utils object.
    Create a function for state change subscribing of the custom event and keeping track of the state for the HTML part by storing that value in this util object,
    Implemented a function to retrieve the current state when needed.
EditorUtil = function () {
    var _RED;
    var initalized = false;
    var state = "Idle";

    function init(RED) {
        if (initalized)
            return;
        _RED = RED;
        initalized = true;
    }
    function monitorState() {
        _RED.comms.subscribe("notification/#", function (topic, payload) {
            if (topic.startsWith("notification/FanzyUniqueEventGosHere")) {
                console.log("State: ", payload.state);
                state = payload.state;
            }
        });
    }
    function getCurrentState() {
        return state;
    }

    return {
        init,
        monitorState: monitorState,
        getCurrentState: getCurrentState
    }
}();
  1. Have a dummy HTML node and register it in my package where i initialize my custom util object by passing RED instance inside + include my custom js file for all other nodes.
    If this can be done differently maybe :man_shrugging:
<script src="resources/my-package/lib/editor.util.js"></script>
<script type="text/javascript">
    (function () {
        EditorUtil.init(RED);
        EditorUtil.monitorState();
    })();
</script>
  1. Check on those nodes which can trigger the process for the current state of the process, if state is idle act normally as a trigger node.
    If state is busy provide a notification in the editor, so the user is aware of it.

I think that I'm not really understanding your requirements. You seem to be inventing something that works completely differently to the way that Node-RED is designed. While Node-RED is flexible enough that you could indeed probably do all that, I'm missing a good reason as to why you would actually want to.

What you are now describing seems to fit more into an architecture where you embed Node-RED into your own custom node.js microservice. And it can do that - did I mention how flexible Node-RED can be?

But given your original description, this feels like significant overkill. So either I've still missed something or you might want to think more simply and along a flow-style rather than a service-style approach?

The term I was trying to think of in my last post was "Finite State Machine". If you try this search, you may get the idea.

Node-RED Library - state-machine

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