2.4.2 • Published 10 months ago
typescript-retry-decorator v2.4.2
A simple retry decorator for typescript with 0 dependency.
This is inspired by the Spring-Retry project. Written in Typescript, 100% Test Coverage.
Import and use it. Retry for Promise
is supported as long as the runtime
has promise(nodejs/evergreen-browser).
Install
npm install typescript-retry-decorator
Options
Exponential options
The exponentialOption
allows you to fine-tune the exponential backoff strategy using several options:
maxInterval
: The maximum interval between two retries. The default value is 2000 ms.multiplier
: The multiplier to use to generate the next backoff interval from the last one. The default value is 2.backoffStrategy
: Optional. If specified, determines the strategy used to introduce "jitter" between retry intervals. For an explanation of the available strategies and why you might select one over the other, check out this article.ExponentialBackoffStrategy.FullJitter
: The base backoff interval is multiplied by a random number between 0 and 1.ExponentialBackoffStrategy.EqualJitter
: The backoff interval is (base interval / 2) + (random value between 0 and base interval / 2).
Example
import { Retryable, BackOffPolicy } from 'typescript-retry-decorator';
let count: number = 1;
class RetryExample {
@Retryable({ maxAttempts: 3 })
static async noDelayRetry() {
console.info(`Calling noDelayRetry for the ${count++} time at ${new Date().toLocaleTimeString()}`);
throw new Error('I failed!');
}
@Retryable({
maxAttempts: 3,
value: [SyntaxError, ReferenceError]
})
static async noDelaySpecificRetry(): Promise<void> {
console.info(`Calling noDelaySpecificRetry for the ${count++} time at ${new Date().toLocaleTimeString()}`);
throw new SyntaxError('I failed with SyntaxError!');
}
@Retryable({
maxAttempts: 3,
backOff: 1000,
doRetry: (e: Error) => {
return e.message === 'Error: 429';
}
})
static async doRetry() {
console.info(`Calling doRetry for the ${count++} time at ${new Date().toLocaleTimeString()}`);
throw new Error('Error: 429');
}
@Retryable({
maxAttempts: 3,
backOff: 1000,
doRetry: (e: Error) => {
return e.message === 'Error: 429';
}
})
static async doNotRetry() {
console.info(`Calling doNotRetry for the ${count++} time at ${new Date().toLocaleTimeString()}`);
throw new Error('Error: 404');
}
@Retryable({
maxAttempts: 3,
backOffPolicy: BackOffPolicy.FixedBackOffPolicy,
backOff: 1000
})
static async fixedBackOffRetry() {
console.info(`Calling fixedBackOffRetry 1s for the ${count++} time at ${new Date().toLocaleTimeString()}`);
throw new Error('I failed!');
}
@Retryable({
maxAttempts: 3,
backOffPolicy: BackOffPolicy.ExponentialBackOffPolicy,
backOff: 1000,
exponentialOption: { maxInterval: 4000, multiplier: 3 }
})
static async ExponentialBackOffRetry() {
console.info(`Calling ExponentialBackOffRetry backOff 1s, multiplier=3 for the ${count++} time at ${new Date().toLocaleTimeString()}`);
throw new Error('I failed!');
}
@Retryable({
maxAttempts: 3,
backOffPolicy: BackOffPolicy.ExponentialBackOffPolicy,
backOff: 1000,
exponentialOption: { maxInterval: 4000, multiplier: 2, backoffStrategy: ExponentialBackoffStrategy.EqualJitter }
})
static async ExponentialBackOffWithJitterRetry() {
console.info(`Calling ExponentialBackOffWithJitterRetry backOff 1s, multiplier=2 for the ${count++} time at ${new Date().toLocaleTimeString()}`);
throw new Error('I failed!');
}
}
(async () => {
try {
resetCount();
await RetryExample.noDelayRetry();
} catch (e) {
console.info(`All retry done as expected, final message: '${e.message}'`);
}
try {
resetCount();
await RetryExample.doRetry();
} catch (e) {
console.info(`All retry done as expected, final message: '${e.message}'`);
}
try {
resetCount();
await RetryExample.doNotRetry();
} catch (e) {
console.info(`All retry done as expected, final message: '${e.message}'`);
}
try {
resetCount();
await RetryExample.fixedBackOffRetry();
} catch (e) {
console.info(`All retry done as expected, final message: '${e.message}'`);
}
try {
resetCount();
await RetryExample.ExponentialBackOffRetry();
} catch (e) {
console.info(`All retry done as expected, final message: '${e.message}'`);
}
try {
resetCount();
await RetryExample.ExponentialBackOffWithJitterRetry();
} catch (e) {
console.info(`All retry done as expected, final message: '${e.message}'`);
}
})();
function resetCount() {
count = 1;
}
Run the above code with ts-node
, then output will be:
Calling noDelayRetry for the 1 time at 4:12:49 PM
Calling noDelayRetry for the 2 time at 4:12:49 PM
Calling noDelayRetry for the 3 time at 4:12:49 PM
Calling noDelayRetry for the 4 time at 4:12:49 PM
I failed!
All retry done as expected, final message: 'Failed for 'noDelayRetry' for 3 times.'
Calling noDelayRetry for the 1 time at 4:12:49 PM
Calling noDelayRetry for the 2 time at 4:12:49 PM
Calling noDelayRetry for the 3 time at 4:12:49 PM
Calling noDelayRetry for the 4 time at 4:12:49 PM
I failed with SyntaxError!
All retry done as expected, final message: 'Failed for 'noDelaySpecificRetry' for 3 times.'
Calling doRetry for the 1 time at 4:12:49 PM
Calling doRetry for the 2 time at 4:12:50 PM
Calling doRetry for the 3 time at 4:12:51 PM
Calling doRetry for the 4 time at 4:12:52 PM
Error: 429
All retry done as expected, final message: 'Failed for 'doRetry' for 3 times.'
Calling doNotRetry for the 1 time at 4:12:52 PM
All retry done as expected, final message: 'Error: 404'
Calling fixedBackOffRetry 1s for the 1 time at 4:12:52 PM
Calling fixedBackOffRetry 1s for the 2 time at 4:12:53 PM
Calling fixedBackOffRetry 1s for the 3 time at 4:12:54 PM
Calling fixedBackOffRetry 1s for the 4 time at 4:12:55 PM
I failed!
All retry done as expected, final message: 'Failed for 'fixedBackOffRetry' for 3 times.'
Calling ExponentialBackOffRetry backOff 1s, multiplier=3 for the 1 time at 4:12:55 PM
Calling ExponentialBackOffRetry backOff 1s, multiplier=3 for the 2 time at 4:12:56 PM
Calling ExponentialBackOffRetry backOff 1s, multiplier=3 for the 3 time at 4:12:59 PM
Calling ExponentialBackOffRetry backOff 1s, multiplier=3 for the 4 time at 4:13:03 PM
I failed!
All retry done as expected, final message: 'Failed for 'ExponentialBackOffRetry' for 3 times.'
Calling ExponentialBackOffWithJitterRetry backOff 1s, multiplier=2 for the 1 time at 4:13:03 PM
Calling ExponentialBackOffWithJitterRetry backOff 1s, multiplier=2 for the 2 time at 4:13:03 PM
Calling ExponentialBackOffWithJitterRetry backOff 1s, multiplier=2 for the 3 time at 4:13:05 PM
Calling ExponentialBackOffWithJitterRetry backOff 1s, multiplier=2 for the 4 time at 4:13:09 PM
I failed!
All retry done as expected, final message: 'Failed for 'ExponentialBackOffWithJitterRetry' for 3 times.'
2.3.0
12 months ago
2.4.0
10 months ago
2.4.2
10 months ago
2.2.0
1 year ago
2.1.0
1 year ago
2.0.6
2 years ago
2.0.5
2 years ago
2.0.3
3 years ago
2.0.2
3 years ago
2.0.0
3 years ago
1.5.1
3 years ago
1.5.0
3 years ago
1.3.2
4 years ago
1.3.1
4 years ago
1.3.0
4 years ago
1.2.1
5 years ago
1.2.0
5 years ago
1.0.5
5 years ago
1.0.4
5 years ago
1.0.3
5 years ago
1.0.2
5 years ago
1.0.1
5 years ago
1.0.0
5 years ago