5XX Retry Logic Best Practices - NodeJS
Review best practices to deal with 5XX errors in NodeJS
Method 1 - Recursive request structure
To begin, we'll be making a request from within a failed request. This requires the use of recursion. Recursion is when a function calls itself.
For example, if we wanted to infinitely keep trying to make a request it might look like this:
The else
block returns the myRequest
function. Since most modern HTTP request implementations are promise-based, we can return the result.
Add retry to Fetch
First, start with the browser's Fetch API. The fetch implementation will be similar to the recursion example above. Let's implement that same example, but using fetch and a status check.
This will work to infinitely retry failed requests. Note: a return
will break out of the current block, so we don't need an else statement after return res.json()
.
For setting up max number of retries
Add the retries
argument to the function, with a default value of 3. Then, rather than automatically calling the function on failure, check if any retries
are remaining. If so, call fetchRetry
. The new retries value passed to the next attempt is the current retries
minus 1. This ensures that our "loop" decrements, and eventually will stop. Without this, it would run infinitely until the request succeeds. Finally, if retries
are not greater than zero, throw a new error for .catch
to handle.
The incremental back-off delay between each request
To handle the "wait" mechanic before retrying the request, you can use setTimeout
. First, we add our new configuration argument (1). Then, set up the setTimeout
and use the backoff
value as the delay. Finally, when the retry occurs we also pass in the back-off with a modifier. In this case, backoff * 2
. This means each new retry will wait twice as long as the previous.
Add retry to Node's native http module
You could use a fetch-equivalent library like node-fetch. To make things interesting, let's look at applying the same concepts above to Node.js' native http module.
Here's a basic GET using http.get: **
To summarize, it requests a url. If the statusCode isn't in a defined "success range" (Fetch has the ok property to handle this) it throws an error. Otherwise, it builds a response and logs to the console. Let's look at what this looks like "promisified". To make it easier to follow, we'll leave off some of the additional error handling.
Final code to retryGet
Source & for more details - Check Here
Method 2 - Add Retries to API Calls using Async Await in NodeJS
Async functions are available natively in Node and are denoted by the async keyword in their declaration. They always return a promise, even if you don’t explicitly write them to do so. Also, the await keyword is only available inside async functions at the moment - it cannot be used in the global scope. _**_In an async function, you can await any Promise or catch its rejection cause.
_**_So if you had some logic implemented with promises:
You can make it look like synchronous code using async/await:
Currently, in Node you get a warning about unhandled promise rejections, so you don’t necessarily need to bother with creating a listener. However, it is recommended to crash your app in this case as when you don’t handle an error, your app is in an unknown state. This can be done either by using the --unhandled-rejections=strict CLI flag, or by implementing something like this:
Retry with exponential backoff:
Implementing retry logic is pretty clumsy with Promises, but async/await makes it a lot more simple:
You can read more about Async & Await in This Article from RisingStack.
NodeJS - Re-Calling function on error callback pseudo code
This is a fairly simple retry scheme, it just retries on a fixed interval for a fixed number of times. More complicated schemes implement a back-off algorithm where they start with fairly quick retries, but then back-off to a longer period of time between retries after the first few failures to give the server a better chance of recovering.
If there happens to be lots and lots of clients all doing rapid retries, then as soon as your server has a hiccup, you can get an avalanche failure as all the clients suddenly start rapidly retrying which just puts your server in even more trouble trying to handle all those requests. The back-off algorithm is designed to allow a server a better chance of preventing an avalanche failure and make it easier for it to recover.
The back-off scheme is also more appropriate if you're waiting for the service to come back online after it's been down a little while.
Also, Here is an asynchronous loop for retrying a specific number of times:
To loop it 10 times, call it as follows:
Pass your error condition in place of range and check it inside the loop.
Last updated