Request retrying
Request retrying in Alette Signal is a feature allowing request blueprints to rerun the failing request with identical request settings when a retry condition is met.
Retrying requests
To retry a request, pass the retry()
middleware to the request blueprint:
const deletePost = mutation(
retry({
times: 2,
})
)
DANGER
While a request is being retried, no errors are thrown.
WARNING
While a request is being retried, debouncing and throttling are ignored.
WARNING
The retry()
middleware override previous retry()
middleware:
const deletePost = mutation(
retry({
times: 2,
})
)
const deleteDraftPost = deletePost.with(
// This will override the "retry()" inferited
// from the "deletePost" request blueprint
retry({
times: 5,
})
)
Status-based retrying
To retry a failing request when a certain HTTP status is returned, configure the whenStatus
property of the retry()
middleware:
const deletePost = mutation(
retry({
times: 2,
whenStatus: [401, 500, 429]
})
)
To retry a request based unless a certain HTTP status is returned, configure the unlessStatus
property of the retry()
middleware:
const deletePost = mutation(
retry({
times: 2,
unlessStatus: [401, 500, 429]
})
)
DANGER
The whenStatus
property overrides the unlessStatus
property of the retry()
middleware:
const deletePost = mutation(
retry({
times: 2,
whenStatus: [401],
// "unlessStatus" will be ignored
unlessStatus: [401, 500, 429]
})
)
Delay between retries
To add a delay between request retry attempts, configure the backoff
property of the retry()
middleware:
const deletePost = mutation(
retry({
times: 5,
backoff: ["1 second", "5 seconds", "10 seconds"],
})
)
// 1st retry
// Wait 1 second...
// 2nd retry
// Wait 5 seconds...
// 3rd retry
// Wait 10 seconds...
// 4th retry
// Wait 10 seconds...
// 5th retry
await deletePost.execute()
Retry condition
A retry condition is a function taking information about the failed request and returning true
to allow for the request retry, or false
to prohibit the request from being retried:
async ({ error, attempt }, { args: postId, path }) => {
if (error.getStatus() === 429) {
return true;
}
return postId === 5;
}
Custom retry
To create a custom retry, pass a retry condition to the retryWhen
middleware:
import { wait, retryWhen, input, path } from '@alette/signal';
// ...
const deletePost = mutation(
input(as<number>()),
path('/posts'),
retryWhen(async ({ error, attempt }, { args: postId, path }) => {
if (error.getStatus() === 429) {
await wait("5 seconds");
return true;
}
return postId === 5;
})
)
await deletePost.execute({ args: 3 })
To add a delay between retries inside a retryWhen()
retry condition, use the wait()
function provided by Alette Signal:
import { wait, /* ... */ } from '@alette/signal';
retryWhen(async ({ attempt }) => {
if (attempt === 0) {
await wait(1000);
}
if (attempt === 1) {
await wait("5 seconds");
}
await wait("10 seconds");
return true;
})
TIP
Request data is available as a second argument of the retryWhen()
retry condition:
retryWhen(async (_, { args: postId, path, context }) => {
/* ... */
})
WARNING
While a request is being retried, debouncing and throttling are ignored.
WARNING
The retryWhen()
middleware override previous retryWhen()
middleware:
const deletePost = mutation(
retryWhen(() => true)
)
const deleteDraftPost = deletePost.with(
// This will override the "retryWhen()" inferited
// from the "deletePost" request blueprint
retryWhen(() => false)
)
Disabling retrying
To disable retrying per request, set the skipRetry
request setting to true
:
const deletePost = mutation(
retryWhen(() => true)
);
// Won't be retried
await deletePost.execute({ skipRetry: true });
// Will be retried
await deletePost.execute();
TIP
The skipRetry
request setting works with both retry()
and retryWhen()
middleware.