Customise status code returned while deploying

Hello
Is there any way to customise http status code that Node-RED endpoints return to clients that happen to connect to a Node-RED instance while it is deploying?

I have some "http_in" nodes and as far as I can see they start returning 404 "Cannot GET %endpoint_path%" result while flows are being deployed.
While this might be technically momentarily correct (Node.js unloads those Node-RED flows, so there is really no such endpoint existing at that particular moment), but I think that 503 could be a better option here as we are really just temporarily unavailable.
This way client will know to retry the request and not just give up due to 404.

It's not that simple.

For one, it is not Node RED returning the code - it is the express engine.

When you remove a route from the express engine (which happens during a redeploy) express will return a 404 - as there is no route, and Node RED does not control that.

To start returning different codes for invalid endpoints, will mean changing the way the express core handles invalid routes - which is obviously unfavourable.

As you have said, 404 is correct - because there really isn't a route, so express (not Node RED) returns a 404.

I don't think is much in the way of customisation here.

I was afraid of something like that.
Would such approach be too much of a dirty hack?

if Node-RED.isBeingRedeployed()
    express.returnError(503)
else
    express.returnError(404)

Again - its not that simple, i.e. the route response block that returns that status, would have already been taken down (and yield a 404)

Personally, I don't see this being acted on - BUT i am not a core developer, so you never know.

You could just deploy only modified nodes, if you don't want everything restarting.

1 Like

First, what deployment method are you using?

If the node is redeployed, the route is deleted so the 404 error is correct.

If you want your route to continue to exist during a deployment (without this node having been modified), use the Modified Nodes method.

Usually I deploy everything as I haven't gotten around to study the difference between full and partial deploys and full just seems safer to me.
I guess it would make sense to deploy partially here as actual endpoints (http in nodes) aren't likely to be changed very often.

Does anybody know how would this situation be handled?

  • add a function node immediately after an http in node,
  • deploy only changed nodes,
  • have the http in node be called by a client right at that moment.

In case of a full deploy it would be rather straightforward — return an error (preferably smth like 503) until the service is completely up again and have clients decide whether they want to retry.
With partial deploy I'm not sure. At some point there is no new node deployed, then there is some inconsistent state, then the new flow (with the new node) is up and active. What happens to incoming requests during the deploy, though?
Does anybody know that?

I was thinking more in terms of "always have the express engine return 503 while Node-RED is being deployed". That way there is no need to track individual route response blocks which might or might not be valid after the deploy. And 503 makes sense here as the service isn't completely ready to accept calls.

As I said when a http-in node is redeployed the routes are removed.

Since you use full deploy you force the http-in node to be redeployed.

I understand that and I am not arguing about that.
404 code here is technically correct as the routes are removed from the express engine.
I'm just wondering whether 503 would be a logically better option as our Node-RED flows (and their endpoints) are indeed unavailable at that moment. With 503 code clients would know to retry again, while with 404 they are told "nothing to see here".

In any case, not changing the http in nodes and doing partial redeploy deals with my original problem (clients receiving 404 and sadly walking away from what in a second or two will be a perfectly valid endpoint).
I've tested partial redeploy and it seems to work really well:

  • call endpoint in a loop (while ... curl ... ),
  • change everything behind the endpoint (completely different set of nodes called, returning a different result),
  • do partial redeploy.

No requests are dropped, at some moment they just switch to returning new data.

The problem is that when this node is modified, the runtime can not know which routes remain and which ones are replaced - the runtime closes all the routes and opens the new ones (even if some routes are identical)

I understand that. Error "503 Service Unavailable" would still be correct here.

This discussion will need the Core Team's input.
But here is a potential solution if you wanted to self implement it (untested)

  1. Add the below before the export in the settings.js file
let Deploying = false;
const Deploy503Switch = function () {
  return {
    set: function (value) {
      Deploying = value;
    }
  };
};

  1. Add an entry to the functionGlobalContext, that points to it (again in the settings file)
functionGlobalContext: {
  Deploy503Switch: Deploy503Switch(),
},

  1. Use the below for the httpNodeMiddleware (this is for all HTTP IN Nodes)
 httpNodeMiddleware: function (req, res, next) {
    if (Deploying) {
      res.status(503).end();
    } else {
      next();
    }
  },
  1. Create a function node that has the below
    This will trigger when you do a full deploy (I think)
/* On Stop tab */
const Switch = global.get("Deploy503Switch");
Switch.set(true)
/* On Start tab */
const Switch = global.get("Deploy503Switch");
Switch.set(false)
2 Likes

Oh, awesome, thank you. This looks very interesting. I'll try to test it some time soon.