How to programmatically identify whether node-red editor has changes to be deployed

Hi All,

I have requirement to programmatically identify changes in node-red editor that are not yet deployed. Manually we can see that node-red displays a blue circle over the nodes that are not deployed. In order to automate and perform certain action based on pending changes, I need to do this programmatically.

In documentation, an event is mentioned workspace:dirty, but its usage is not explained anywhere (client side/server side), and how to access it at workspace level in code. Any help/suggestions are welcome.

Thanks,
Shashwat

Hi @BShashwat, in the editor you can call RED.nodes.dirty() and it will return true if there are changes to be deployed.

@knolleary ... what would be the best place to put this check. I do not want to write it in HTML of each node to check for dirty, as that way it will not cover the pre-built nodes. Is there a single place from where I can capture the state?

Hi @BShashwat

without more information about what you're trying to do, I cannot suggest what would be best for you.

That api call doesn't tell you about individual nodes - it just returns true/false if there are any changes that need to be deployed.

If you can explain in more detail what you want to do, we may be able to help point you in the right direction.

Thanks @knolleary ... My use case is a to extend Node-Red to multiple users/tenants. So from my application UI, I dynamically spin up Node-Red docker containers backed by persistent volumes for individual users who are granted Node-Red access in my app (To avoid users overwriting/messing up each others flows).

Now I can not have too many containers as it consumes lot of cloud resources. So I have decided to terminate those containers when user session ends. Thus I have written code which will calculate time remining before JWT token expires.

I now want to alert users 5 minutes before the session expires and their container terminates (there is no token refresh implemented yet), so as to not lose any changes. Thus I need to know if the workspace is in dirty state to show a pop-up and alert user to save the changes.

Hope this clarifies my scenario.

Regards,
Shashwat

Sounds like you need a Node-RED plugin

1 Like

any thoughts... @knolleary, @TotallyInformation

That is a helpful clarification.

A plugin would be the standard way of injecting code into the editor.

We don't have very good docs on how to write plugins - I can only point you at the example of the flow debugger - GitHub - node-red/node-red-debugger: A flow debugger for Node-RED 2.x or nrlint - GitHub - node-red/nrlint: Node-RED Flow Linter

Taking nrlint as an example, in the package.json, you have a plugins section under node-red - nrlint/package.json at master · node-red/nrlint · GitHub

That should point to either a .js or .html file (depending if it is a runtime or editor plugin).

For an editor plugin, you should call RED.plugins.registerPlugin - nrlint/nrlint-core.html at bb60347c4a11e5e0bbc77ea20e75535677c5bddd · node-red/nrlint · GitHub

That defines an onadd function that is called by Node-RED when the plugin is added to the editor. You can setup whatever you want at that point.

1 Like

@knolleary writing a plugin just to show an alert seems a bit too much work. I gave it a thought and if I alter my approach as below:
Approach 1:
calculate token expiry in my app -> make a REST call to custom Node Red Admin API endpoint using RED.httpAdmin.post (not sure where to write this) -> within post call use RED.notify
Will this work?
OR
Approach 2:
If I can get a count of logged in users from Node Red then if count(users logged in) === 0 then I will terminate instances.
Kindly suggest if any of above is feasible!!

Any custom admin api endpoint you add will be in the runtime side. RED.notify is an editor API - you cannot call it from the runtime.

writing a plugin just to show an alert seems a bit too much work
...
not sure where to write this

Well... a plugin is the standard way of adding custom code to the runtime and editor.

I'm not sure that is exposed in any meaningful way.

This can easily be worked around in your node's editor javascript. There are some examples in uibuilder. You call the API and use the response to work out whether the notification requires calling.

Agree that this would likely be the best approach and would also be potentially reusable.

The plugin is a separate js file that is part of the package your node comes in and is declared in the package.json file under the node-red section if I remember correctly.

I think that you would need to collect this yourself via middleware on the node-red admin ExpressJS instance. the httpAdminMiddleware setting in settings.js should allow you to insert some code to capture unique users as long as you can think of a way to identify them. I'm not sure if adminAuth passes anything useful or whether you would need a custom function for adminAuth (sorry, lost track of whether you are already doing that). If you use a custom function for adminAuth, you might not need the extra middleware.

Assuming you can find some information to identify unique users and so keep a count (and we haven't thought about the process(es) for user logout/session-expiry handling), you then have the issue of making that available to the Editor. That might need the middleware again to provide a custom API (not hard to do). Then the editor could query that?

hmm, seems like writing a plugin is the only option for now!! Thanks @knolleary, really appreciate your help and guidance. Will get back if I get stuck in writing a plugin.

@TotallyInformation ... Thanks for the response. For 1st approach, I know it can be done for a node/custom nodes, but it would still not work with pre-built nodes that comes with Node-Red. Hence was looking for a common place from where info could be gathered for all nodes in all tabs (within a workspace).
For 2nd Approach - I am thinking, probably to keep track of session when I am dynamically creating container (may be through DB) and get the active user count from there rather than going to Node-Red.

Yes, that is probably the best approach. It is trivial to set up a small node.js service that acts as an API that node-red can query. So having a common Docker container containing even just a SQLite db along with the simple API to return the value would probably be plenty.

1 Like