How to restart flows automatically?

Dear all,

We're encountering a situation whereby if we have loss of connectivity, a number of flows (namely websocket nodes) fail to reconnect, while I realise we could check the source for the problematic nodes and implement a reconnect mechanism, this isn't viable for number of nodes we use (longterm, yes).

Is there a way to restart flows from within Node Red? This would not only be useful to overcome the above, but also for testing purposes... Failing that we're considering triggering a script for the container from within Node Red itself?

Any advice would be greatly appreciated.

You can use the admin http API to get the runtime to reload it's flows. An http post to /flows with the right headers set should do it.

https://nodered.org/docs/api/admin/methods/post/flows/

@swiftnesses did you manage to implement that? I'm trying to do the same thing.

Sadly I didn't get the reloading of flows working from within Node Red (I got bad request 400), perhaps @knolleary has a simple example we can utilise? Currently I use an external script, but it's far from ideal.

Here's an example of what I tried... Sadly, I don't have a clar understanding of the API :blush:

[{"id":"318bc319.545c8c","type":"inject","z":"85ff7c27.d1f9e","name":"","topic":"","payload":"{}","payloadType":"json","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":150,"y":340,"wires":[["6127a9be.73ed48"]]},{"id":"8e46bf1d.9cec7","type":"http request","z":"85ff7c27.d1f9e","name":"POST /auth/token","method":"POST","ret":"txt","url":"http://localhost:1880/auth/token","tls":"","x":570,"y":340,"wires":[["8d950fde.e890c"]]},{"id":"6127a9be.73ed48","type":"change","z":"85ff7c27.d1f9e","name":"","rules":[{"t":"set","p":"payload.client_id","pt":"msg","to":"node-red-editor","tot":"str"},{"t":"set","p":"payload.grant_type","pt":"msg","to":"password","tot":"str"},{"t":"set","p":"payload.scope","pt":"msg","to":"*","tot":"str"},{"t":"set","p":"payload.username","pt":"msg","to":"CHANGE_ME","tot":"str"},{"t":"set","p":"payload.password","pt":"msg","to":"CHANGE_ME","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":340,"y":340,"wires":[["8e46bf1d.9cec7"]]},{"id":"38985da.ce401a2","type":"change","z":"85ff7c27.d1f9e","name":"","rules":[{"t":"set","p":"token","pt":"flow","to":"payload","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":1120,"y":340,"wires":[["88e94d53.649b"]]},{"id":"8d950fde.e890c","type":"json","z":"85ff7c27.d1f9e","name":"","property":"payload","action":"","pretty":false,"x":770,"y":340,"wires":[["af3a2700.a4dc38"]]},{"id":"88e94d53.649b","type":"change","z":"85ff7c27.d1f9e","name":"","rules":[{"t":"delete","p":"headers","pt":"msg"},{"t":"set","p":"headers.Authorization","pt":"msg","to":"token.access_token","tot":"flow"},{"t":"set","p":"headers.Node-RED-Deployment-Type","pt":"msg","to":"reload","tot":"str"},{"t":"set","p":"headers.Node-RED-API-Version","pt":"msg","to":"v1","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":1340,"y":340,"wires":[["134799e1.f6e326"]]},{"id":"af3a2700.a4dc38","type":"function","z":"85ff7c27.d1f9e","name":"Bearer","func":"msg.payload.access_token = \"Bearer \" + msg.payload.access_token\nreturn msg;","outputs":1,"noerr":0,"x":930,"y":340,"wires":[["38985da.ce401a2"]]},{"id":"134799e1.f6e326","type":"http request","z":"85ff7c27.d1f9e","name":"POST /flows","method":"POST","ret":"txt","paytoqs":false,"url":"http://localhost:1880/flows","tls":"","persist":false,"proxy":"","authType":"","x":1550,"y":340,"wires":[["3d8d2c74.71d704"]]},{"id":"3d8d2c74.71d704","type":"debug","z":"85ff7c27.d1f9e","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","x":1730,"y":340,"wires":[]}]

@swiftnesses

I had the same issue, and resolved it with the below code

[{"id":"e3f0c29b.15917","type":"function","z":"45ec8d76.35a444","name":"Request Token","func":"msg.payload = {\n    \"client_id\": \"node-red-editor\",\n    \"grant_type\": \"password\",\n    \"scope\": \"*\",\n    \"username\": \"type or username\",\n    \"password\": \"type your password\"\n}\nreturn msg;","outputs":1,"noerr":0,"x":440,"y":760,"wires":[["40715257.e3114c"]]},{"id":"62e6b42a.d2df5c","type":"inject","z":"45ec8d76.35a444","name":"Manual reload","topic":"","payload":"","payloadType":"str","repeat":"","crontab":"","once":false,"onceDelay":"","x":230,"y":760,"wires":[["e3f0c29b.15917"]]},{"id":"40715257.e3114c","type":"http request","z":"45ec8d76.35a444","name":"Token","method":"POST","ret":"txt","paytoqs":false,"url":"http://localhost:1880/auth/token","tls":"","persist":false,"proxy":"","authType":"","x":630,"y":760,"wires":[["27f2916.2d1306e"]]},{"id":"27f2916.2d1306e","type":"function","z":"45ec8d76.35a444","name":"Confirm token","func":"// get the status of the request\nvar status = msg.statusCode;\n//var token = {};\nvar token = '';\nmsg.headers ={};\n\n//let node = feedback;\n\nswitch(status){\n    case 200:\n        node.log(\"Secure restart\");\n        token = JSON.parse(msg.payload);\n        token = 'Bearer '+token.access_token;\n        msg.headers = {\n            \"Authorization\": token,\n            \"Node-RED-Deployment-Type\":\"reload\"\n        }\nmsg.payload =\"\";\n        break;\n    case 204:\n        node.log(\"Secure without restart\");\n        global.set('result','\tSuccess - with no further content');\n        break;\n    case 400:\n        node.warn(\"Bad request\");\n        break;\n    case 401:\n        node.warn(\"Not authorized\");\n        break;\n    case 403:\n        node.warn(\"Forbidden\");\n        break;\n    case 404:\n        node.log(\"Unsecure restart\");\n        msg.headers = {\n            \"Node-RED-Deployment-Type\":\"reload\"\n        }\n        break;\n    case 409:\n        node.warn(\"Version mismatch\");\n        break;\n    case 500:\n        node.error(\"Server Error\");\n        break;\n    default:\n        node.warn(\"Unknown Error\");\n       break;\n}\n\nmsg.payload = \"\";\nreturn msg;","outputs":1,"noerr":0,"x":820,"y":760,"wires":[["cbf97372.7169f"]],"info":"Restart of Node-Red flows.\nWill check if the action needs security or not.\nNote: if the first 5 attemps return a statuscode 403 'forbidden'\nthen the server will break and only way to recover is then to\nrestart the service"},{"id":"cbf97372.7169f","type":"http request","z":"45ec8d76.35a444","name":"Restart","method":"POST","ret":"txt","paytoqs":false,"url":"http://localhost:1880/flows","tls":"","persist":false,"proxy":"","authType":"","x":1020,"y":760,"wires":[[]]}]

There is still a minor issue with it.
If the function returns within the first 5 attempts a statuscode 403 'forbidden' then the 6th attempt will break the server (code 500 and only way to recover is then to restart the service)

:slight_smile: