Is it impossible to maintain a reliable 1-1 relationship between nodes and external entities?

What I'm referring to is:

  • you create a node in a flow
  • a corresponding resource is created in some external system/service
  • as you edit the flow, restart node-red, disable flows, re-enable flows, etc. the 1-1 relationship between that node and the external resource is maintained
  • when you delete the node from the flow the external resource is deleted

A concrete example could be a node that represents a web page on some external server. You add a node to your flow and a corresponding web page appears on the web site. You delete the node, the web page goes away.

(My use-case is the FlexDash dashboard and the external resources are widgets in FlexDash, but the question and difficulties are generic.)

Difficulties I'm encountering implementing something like that:

  • you cannot store a persistent reference to the external resource in your node, you can only send your node ID to the external service/system and have it store a back-pointer to the node. (You could use a persistent context store as a crutch, but that requires the user creating it in the settings and then entering its name into a config field of the node, which is really cumbersome.)
  • you cannot find out when a node got deleted, so you have to implement some form of garbage collection
  • to implement garbage collection you have to enumerate all nodes of the appropriate types and collect their IDs, I'm not sure there's a clean way to do this, also not sure where one would put code for this and how one would trigger it.

Hey @tve,
I do something similar here. Summarized:

function MyNode(config) {
   RED.nodes.eachNode(function(someNode) {
      if(someNode.type != "tab" && someNode.type != "subflow" && someNode.type != "comment") {
          ...
      }
   });
});

This is how it works:

  1. The MyNode function is called when Node-RED is started anyway.
  2. You delete a (e.g. UI) node in the flow editor.
  3. Every time you Deploy your changes, the MyNode function will also be called.

Anyway - based on the node types - you could build a list of ui node ids and send that to your FlexDash. In Flexdash you could determine whether UI nodes are added or removed, and then you can create your widgets. Because I assume that is the reason of your question?

But I doubt whether this is a good way to do it!
One main disadvantage I see, is that you want to do this only once in 1 single node. Because:

  • if you have N ui nodes in your flow, you want to do it only once.
  • if you remove the last UI node from the flow (which means you end up with 0 ui nodes), you still want to execute this loop.

That could be solved if we need to add a single Flexdash Manager node in the flow, that handles all this stuff. But some users will forget to add it, or remove it accidentally. Or they add multiple manager nodes...

Perhaps another approach would be better...
Suppose you have a FlexDash sidebar (similar to the current Dashboard). In that sidebar code you have access to all the flow editor events (see events), like the following events:

  • deploy
  • nodes:add
  • nodes:remove

Perhaps you don't even need the latter two events, because in the deploy event you can enumerate all nodes and send them to Flexdash (but of course then you need the delta calculation in Flexdash...).

Imho this is a better solution since such a sidebar would allow you to integrate your Flexdash even more into Node-RED, for those who like the concept of ui nodes.

BTW developing a sidebar is completely different to developing a node. I am not an expert in it, and have done it only once (for my node-red-contrib-xterm node). If you want I can try to help you with building a very basic one, if you want...

1 Like

@tve,
I have never had a detailed look at the current dashboard internals, but I think works like this in very rough lines:

  1. The dasbhoard sidebar panel (called ui_base) intercepts all added and removed ui nodes. You can see here which events it uses to do that (editor:save, nodes:add, nodes:remove).

  2. Based on these events it will maintain the treeview in the sidebar panel.

  3. At deploy the client side config will be transferred to the server side (like with normal nodes):

    function BaseNode(config) {
       ...
       ui.addBaseConfig(this.config);
    }
    
  4. So you end up in the addBaseConfig function

  5. And finally in the updateUi function, which emits the config to the frontend.

I don't say you need to take the same route, but hopefully it gives you some ideas of how you might design your own integration...

1 Like

Don't want to go too much off-topic, but I mean that you could simply collect all info about ui nodes in your sidebar panel. And that you add a link to an external third-party layout manager on your sidebar panel. That way you don't need to develop and maintain a complex sidebar like we have today. And perhaps you then even don't need to specify in every ui node's config screen, the size and tabsheet/group of the widget.
Anyway completely off topic, but just mentioning it as a possible way of working with a small manageble sidebar.

My time is up for today...

1 Like

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