@servisbot/sb-fetch-retry
v2.1.1
Published
A module for performing fetch calls with configurable retry behavior.
Downloads
241
Readme
sb-fetch-retry
A module for performing fetch calls with configurable retry behavior.
Prerequisites
The module was originally designed to work with AWS Lambdas and uses the following environment variables if no client metadata is provided in the fetch retry options:
SERVISBOT_REGION=eu-private-4
AWS_LAMBDA_FUNCTION_NAME=some-lambda-name
SBFetchRetry
The SbFetchRetry class is the main entry point for making fetch calls with retry functionality.
To correctly instantiate a SBFetchRetry object you must provide the following to the constructor of the class:
- The node-fetch module for making fetch calls, which can be found here: https://www.npmjs.com/package/node-fetch
- An instance of the ServisBOT logger, which can be found here: https://github.com/servisbot/sb-logger
- Any logger containing debug, info, warn & error functions will also work.
An example of instantiating an SBFetchRetry object with the correct parameters and environment variables can be seen below.
const Logger = require("@servisbot/sb-logger");
const fetch = require("node-fetch");
const { SBFetchRetry } = require("@servisbot/sb-fetch-retry");
const sbFetchRetry = new SBFetchRetry({ logger: new Logger(), fetch });
To perform a fetch call with configured retry behavior you may do the following:
const {
SBFetchRetry,
SBFetchRetryOptions,
} = require("@servisbot/sb-fetch-retry");
const sbFetchRetry = new SBFetchRetry({ logger: new Logger(), fetch });
const url = new URL('https://test.test');
const fetchOptions = {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({ data: "value" }),
};
const sbFetchRetryOptions = new SBFetchRetryOptions({
statusCodes: [429],
maxRetries: 2,
retryDelay: 2000,
});
// where fetchResponse is a response object from node fetch
const fetchResponse = await sbFetchRetry.fetch(
url,
fetchOptions,
sbFetchRetryOptions
);
if (fetchResponse.ok) {
const jsonBody = await fetchResponse.json();
console.log("Ok!", jsonBody);
} else {
const status = fetchResponse.status;
const errorText = await fetchResponse.text();
console.log(`Bad Response, with status ${status} with reason: ${errorText}`);
}
The above example uses the SBFetchRetryOptions class to configure the behavior of the fetch retry logic. We will discuss these options in more detail in a later section - Configuring SBFetchRetryOptions. For now you can read the example above as follows:
- Retry the fetch call if you receive a network error or a status code of 429.
- Retry the fetch call a maximum of 2 times.
- Add a delay of 2000ms between each retry attempt (2 seconds).
If you do not wish to configure the retry options and would rather use the default options, you can use omit the sbRetryOptions
parameter when calling the fetch
function. An example can be seen below:
const {
SBFetchRetry,
SBFetchRetryOptions,
} = require("@servisbot/sb-fetch-retry");
const sbFetchRetry = new SBFetchRetry({ logger: new Logger(), fetch });
const url = new URL('https://test.test');
const fetchOptions = {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({ data: "value" }),
};
// where fetchResponse is a response object from node fetch
const fetchResponse = await sbFetchRetry.fetch(
url,
fetchOptions
);
if (fetchResponse.ok) {
const jsonBody = await fetchResponse.json();
console.log("Ok!", jsonBody);
} else {
const status = fetchResponse.status;
const errorText = await fetchResponse.text();
console.log(`Bad Response, with status ${status} with reason: ${errorText}`);
}
The above example uses the default SBFetchRetryOptions to configure the behavior of the fetch retry logic. We will discuss these default options in more detail in a later section - Default SBFetchRetryOptions. For now you can read the example above as follows:
- Retry the fetch call a maximum of 3 times. (default value)
- Add a delay of 1000ms between each retry attempt (1 seconds).
It is also possible to use a string
as the URL:
const url = 'https://test.test';
const fetchOptions = {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({ data: "value" }),
};
const sbFetchRetryOptions = new SBFetchRetryOptions({
statusCodes: [429],
maxRetries: 2,
retryDelay: 2000,
});
const fetchResponse = await sbFetchRetry.fetch(
url,
fetchOptions
);
// as above
SBFetchRetryOptions
The SBFetchRetryOptions
class can be used to configure some of the retry behavior of the SBFetchRetry
class. The constructor takes in an object which represents the options to configure. The following options are available:
statusCodes
- an array of status codes to retry on e.g. [429, 400] would cause a retry to occur if the status code from the response is 429 or 400. This is optional and defaults to an empty array. If the array is empty, then the request will not retry based on the status code.maxRetries
- A positive integer representing the maximum number of times to retry the request before returning the response. e.g. specifying 3 here would allow for a maximum of 3 retries to occur before the response the latest response is returned. If a request is successful before this number is reached the successful result will be returned. This is optional and defaults to 3. If the max retries is greater than 10, it will be clamped to 10.retryDelay
- A positive integer representing the delay in milliseconds to add between each retry attempt. This number will increase exponentially for each retry e.g. adding a retry delay of 2000 will wait 2 seconds before the first, 4 seconds before the second etc. This is optional and will default to 1000ms. If the retry delay is smaller than 250 it will be clamped to 250, and if it is greater than 5000 it will be clamped to 5000.clientMetadata
- An instance of theClientMetadata
class. This client metadata will be used to create logs containing client information when network errors are detected.
Default Options
To use the default options you can use the static function constructWithDefaults
method on the SBFetchRetryOptions
class.
const { SBFetchRetryOptions } = require("@servisbot/sb-fetch-retry");
const sbFetchRetryOptions = SBFetchRetryOptions.constructWithDefaults();
The default values are as follows:
statusCodes
- defaults to an empty arraymaxRetries
- defaults to 3.retryDelay
- defaults to 1000ms.clientMetadata
- defaults to using lambda environment variables
Configuring Retry Options
To configure the options you can construct a new instance of the SBFetchRetryOptions
and supply your own retry options. The following options are available to configure:
statusCodes
- an array of status codes to retry on e.g. [429, 400] would cause a retry to occur if the status code from the response is 429 or 400. This is optional and defaults to an empty array.maxRetries
- the maximum number of times to retry the request before returning the response. e.g. specifying 3 here would allow for a maximum of 3 retries to occur before the response the latest response is returned. If a request is successful before this number is reached the successful result will be returned. This is optional and defaults to 3.retryDelay
- the delay in milliseconds to add between each retry attempt. e.g. adding a retry delay of 2000 will wait 2 seconds before each retry attempt. This is optional and will default to 1000ms.clientMetadata
- An instance of theClientMetadata
class. This client metadata will be used to create logs containing client information when network errors are detected.
An example of instantiating an SBFetchRetryOptions
object can be seen below:
const { SBFetchRetryOptions, ClientMetadata } = require("@servisbot/sb-fetch-retry");
const sbFetchRetryOptions = new SBFetchRetryOptions({
statusCodes: [429],
maxRetries: 2,
retryDelay: 2000,
clientMetadata: new ClientMetadata({
organization: 'acme',
sbRegion: 'eu-1',
clientType: 'browser',
clientName: 'venus-runtime'
})
});
The above example shows a SBFetchRetryOptions
object being configured for the following:
- Retry the request when a status code of 429 is received.
- The maximum amount of retries is 2.
- The delay between each request is 2000 milliseconds or 2 seconds.
- When a network error is detected a log will be created using the client metadata provided.
Network Errors
If the module attempts to make a fetch call and it fails in an unexpected manner there will not be a status code to retry on. However the module will retry the call until the request is either successful or has reached the maximum number of retry attempts. If the maximum number of retry attempts is reached and the fetch call is still receiving unexpected errors, the error will be thrown.
Logging Network Errors
If a network error is detected a log is created with the following attributes:
Default
- The module will attempt to use the
SERVISBOT_REGION
andAWS_LAMBDA_FUNCTION_NAME
environment variables to generate the SRN.
{
srn: 'srn:monitor:eu-private-4:helium:lambda:some-lambda',
action: 'network-request',
actionType: 'failed',
details: { attempt: 1, url: 'some-url' }
}
Duration logs
Every network request will log it's duration, failed network requests will have a status of -1:
{ "url": "https://test.com", "duration": 222, "status": 201 }
Provided
- If you provide your own client metadata the log will use the client metadata to build the SRN
- For example, if you pass the following client metadata
const clientMetadata = new ClientMetadata({
organization: 'acme',
sbRegion: 'eu-1',
clientType: 'browser',
clientName: 'venus-runtime'
});
You log will look like the following:
{
srn: 'srn:monitor:eu-private-4:acme:browser:venus-runtime',
action: 'network-request',
actionType: 'failed',
details: { attempt: 1, url: 'some-url' }
}
Servisbot Logger
- If you pass the servisbot logger in to the module it will attempt to log the network error using the following
logger.app.privatePerformance.reliability
- If the logger does not contain
logger.app.privatePerformance.reliability
, thenlogger.info
is used.