Retrying
Optional Feature
This feature is optional and must be enabled to use it.
APIHive provides an optional retry feature that can be enabled using the RetryFeature
class from the @apihive/core/features
module.
import { HTTPRequestFactory } from '@apihive/core';
import { RetryFeature } from '@apihive/core/features';
const factory = new HTTPRequestFactory()
.use(new RetryFeature());
Configuration
One way to configure the retry feature is to use the withRetry
method on the factory, request, or by setting the retry
property on an APIConfig
.
import { HTTPRequestFactory } from '@apihive/core';
import { RetryFeature } from '@apihive/core/features';
const factory = new HTTPRequestFactory()
.use(new RetryFeature())
.withRetry({
attempts: 3
Pretty straightforward. Every requests created by the factory that fails with a 500 status code will be retried up to 3 times with a delay of 1 second.
Optionally, you can also set more detailed configuration:
const factory = new HTTPRequestFactory()
.use(new RetryFeature())
.withRetry({
attempts: 3,
retryDelay: 1000,
retryCondition: (error) => error instanceof HTTPError
&& error.status === 500
});
Default Config
It's also possible to set default retry settings on the feature instance.
const retryFeature = new RetryFeature()
.withDefaultAttempts(3)
.withDefaultRetryDelay(1000)
.withDefaultRetryCondition((error) => error instanceof HTTPError
&& error.status === 500);
These defaults will be applied to all requests created by the factory in the absence of more granular configuration.
Retry Condition
The retry condition is a function that takes an error as a parameter and returns a boolean indicating whether the request should be retried.
const retryFeature = new RetryFeature()
.withDefaultRetryCondition((error) => error instanceof HTTPError
&& error.status >= 500);
Dynamic Configuration
It's also possible to set retry settings on a per request basis using the builder strategy. Just pass a function to withRetry
or on APIConfig.retry
and the retry strategy will be evaluated just before a request is executed.
const api : APIConfig = {
name: 'default',
retry: (config) => {
if(config.api.endpointName.startsWith('user:'))
return {
attempts: 3
};
},
endpoints: {
//...
}
}
Meta Config
It's also possible to leverage the meta config feature to enable retries on a per endpoint basis.
const retryFeature = new RetryFeature()
.withMetaConfig({
defaults: {
attempts: 3,
retryDelay: 1000,
retryCondition: (error) => error instanceof HTTPError
&& error.status === 500
}
});
const factory = new HTTPRequestFactory()
.use(retryFeature)
.withAPIConfig({
name : 'default',
endpoints: {
'getItems': {
target: '/items',
meta: {
retry: true
}
},
'postItem': {
target: '/items',
method: 'POST'
}
}
});
factory.createAPIRequest('getItems')
.execute();//this will retry
factory.createAPIRequest('postItem')
.execute();//this won't
Warning
Meta-based retrying will be ignored when a request has a retry policy set either directly or via APIConfig
or the factory.
Custom meta evaluator
By default the retry feature will evaluate the meta.retry
property to determine whether to retry a request. It's possible to provide a custom evaluator to determine whether to retry a request based on the request's meta object.
The evaluation goes hand in hand with the normally
optional property of the RetryMetaConfig
interface. normally
can be either 'on'
or 'off'
and it determines the behaviour applied according to the evaluation result.
For instance with normally: 'on'
, a true
or undefined
evaluation result will result in a retry, while a false
evaluation result will result in no retry. Conversely, with normally: 'off'
, a false
or undefined
evaluation result will result in no retry, while a true
evaluation result will result in a retry.
const retryFeature = new RetryFeature()
.withMetaConfig({
evaluator: (meta) => meta.retry,
defaults: {
attempts: 3,
retryDelay: 1000,
retryCondition: (error) => error instanceof HTTPError
&& error.status === 500
}
})
const factory = new HTTPRequestFactory()
.use(retryFeature)
.withAPIConfig({
name : 'default',
endpoints: {
'getItems': {
target: '/items',
meta: {
retry: true
}
},
'postItem': {
target: '/items',
method: 'POST'
}
}
});
factory.createAPIRequest('getItems')
.execute();//this will retry
factory.createAPIRequest('postItem')
.execute();//this won't
Cascading defaults
The retry feature can be configured with defaults that will be applied to all requests created by the factory in the absence of more granular configuration.
When using meta retry configuration, for instance, if some settings are not passed to the default
property, they will be taken from the feature's defaults.
const retryFeature = new RetryFeature()
.withDefaultAttempts(5)
.withDefaultRetryDelay(300)
.withMetaConfig()
Backoff Strategies
The feature provides two complex backoff strategies out of the box, beyond a simple fixed delay: exponentialBackoff
and linearBackoff
.
INFO
You can read this article about the exponential backoff strategy for more information.
They can be imported and used as follows:
import { exponentialBackoff } from '@apihive/core/features/retry';
const retryFeature = new RetryFeature()
.withDefaultRetryDelay(exponentialBackoff({
initialDelay: 100,
multiplier: 2,
maxDelay: 30000,
jitter: true
}))
or
import { linearBackoff } from '@apihive/core/features/retry';
const factory = new HTTPRequestFactory()
.use(new RetryFeature())
.withRetry({
attempts: 3,
retryDelay: linearBackoff(1000)
});