typescript-retry-decorator 2.4.0 → 2.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.eslintrc.js +32 -8
- package/.github/workflows/ci.yml +1 -1
- package/.github/workflows/npm-publish.yml +10 -8
- package/README.md +7 -0
- package/dist/example.js +118 -101
- package/dist/example.js.map +1 -1
- package/dist/retry.decorator.d.ts +15 -4
- package/dist/retry.decorator.d.ts.map +1 -1
- package/dist/retry.decorator.js +74 -67
- package/dist/retry.decorator.js.map +1 -1
- package/dist/retry.decorator.test.js +196 -138
- package/dist/retry.decorator.test.js.map +1 -1
- package/jest.config.js +2 -7
- package/package.json +11 -11
- package/src/retry.decorator.test.ts +72 -12
- package/src/retry.decorator.ts +103 -66
- package/tsconfig.json +7 -2
package/.eslintrc.js
CHANGED
|
@@ -1,18 +1,42 @@
|
|
|
1
1
|
module.exports = {
|
|
2
2
|
root: true,
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
env: {
|
|
4
|
+
jest: true,
|
|
5
|
+
node: true,
|
|
6
|
+
},
|
|
7
|
+
parser: '@typescript-eslint/parser',
|
|
8
|
+
plugins: ['@typescript-eslint'],
|
|
5
9
|
extends: [
|
|
6
|
-
|
|
7
|
-
'plugin:@typescript-eslint/recommended', // Uses the recommended rules from the @typescript-eslint/eslint-plugin
|
|
8
|
-
'eslint-config-ts-vcfvct',
|
|
10
|
+
'plugin:@typescript-eslint/recommended',
|
|
9
11
|
],
|
|
10
12
|
parserOptions: {
|
|
11
|
-
ecmaVersion:
|
|
12
|
-
sourceType: 'module',
|
|
13
|
+
ecmaVersion: 2020,
|
|
14
|
+
sourceType: 'module',
|
|
13
15
|
},
|
|
14
16
|
rules: {
|
|
15
|
-
|
|
17
|
+
'@typescript-eslint/no-var-requires': 'off',
|
|
18
|
+
'@typescript-eslint/no-explicit-any': 'off',
|
|
19
|
+
'@typescript-eslint/no-non-null-assertion': 'off',
|
|
20
|
+
'@typescript-eslint/no-use-before-define': 'off',
|
|
21
|
+
'@typescript-eslint/no-empty-interface': 'off',
|
|
22
|
+
'@typescript-eslint/explicit-function-return-type': ['warn', { allowExpressions: true }],
|
|
23
|
+
|
|
24
|
+
indent: ['error', 2],
|
|
25
|
+
'no-trailing-spaces': 'error',
|
|
26
|
+
quotes: ['error', 'single', { allowTemplateLiterals: true }],
|
|
27
|
+
semi: ['error', 'always'],
|
|
28
|
+
'spaced-comment': ['error', 'always'],
|
|
29
|
+
'no-irregular-whitespace': ['error', { skipComments: true }],
|
|
30
|
+
'space-infix-ops': 'error',
|
|
31
|
+
'array-bracket-spacing': 'error',
|
|
32
|
+
'object-curly-spacing': ['error', 'always'],
|
|
33
|
+
'space-before-function-paren': ['error', {
|
|
34
|
+
named: 'never',
|
|
35
|
+
anonymous: 'never',
|
|
36
|
+
asyncArrow: 'always',
|
|
37
|
+
}],
|
|
38
|
+
'comma-dangle': ['warn', 'always-multiline'],
|
|
39
|
+
'no-multiple-empty-lines': 'error',
|
|
16
40
|
},
|
|
17
41
|
};
|
|
18
42
|
|
package/.github/workflows/ci.yml
CHANGED
|
@@ -7,22 +7,26 @@ on:
|
|
|
7
7
|
release:
|
|
8
8
|
types: [created]
|
|
9
9
|
|
|
10
|
+
permissions:
|
|
11
|
+
id-token: write # Required for OIDC / Trusted Publisher
|
|
12
|
+
contents: read
|
|
13
|
+
|
|
10
14
|
jobs:
|
|
11
15
|
publish-npm:
|
|
12
16
|
runs-on: ubuntu-latest
|
|
13
17
|
steps:
|
|
14
|
-
- uses: actions/checkout@
|
|
15
|
-
- name: Install Node.js
|
|
16
|
-
uses: actions/setup-node@
|
|
18
|
+
- uses: actions/checkout@v4
|
|
19
|
+
- name: Install Node.js
|
|
20
|
+
uses: actions/setup-node@v4
|
|
17
21
|
with:
|
|
18
|
-
node-version:
|
|
22
|
+
node-version: 24
|
|
19
23
|
registry-url: https://registry.npmjs.org/
|
|
20
24
|
|
|
21
25
|
- uses: pnpm/action-setup@v2
|
|
22
26
|
name: Install pnpm
|
|
23
27
|
id: pnpm-install
|
|
24
28
|
with:
|
|
25
|
-
version:
|
|
29
|
+
version: 10
|
|
26
30
|
run_install: false
|
|
27
31
|
|
|
28
32
|
- name: Get pnpm store directory
|
|
@@ -42,6 +46,4 @@ jobs:
|
|
|
42
46
|
- run: pnpm install
|
|
43
47
|
- run: npm run build
|
|
44
48
|
- run: npm test
|
|
45
|
-
- run: npm publish
|
|
46
|
-
env:
|
|
47
|
-
NODE_AUTH_TOKEN: ${{secrets.NPM_TOKEN}}
|
|
49
|
+
- run: npm publish --provenance
|
package/README.md
CHANGED
|
@@ -7,6 +7,13 @@ Import and use it. Retry for `Promise` is supported as long as the `runtime` has
|
|
|
7
7
|
### Install
|
|
8
8
|
> npm install typescript-retry-decorator
|
|
9
9
|
|
|
10
|
+
This library supports both TypeScript's legacy ("experimental") decorators and TypeScript 5+ standard decorators.
|
|
11
|
+
|
|
12
|
+
- If your project uses legacy decorators, enable [`experimentalDecorators`](https://www.typescriptlang.org/tsconfig#experimentalDecorators) in `tsconfig.json`.
|
|
13
|
+
- If your project uses TypeScript 5+ standard decorators (no `experimentalDecorators`), it should work without extra config.
|
|
14
|
+
|
|
15
|
+
> TypeScript 5 note: this library also supports the new "standard decorators" call signature (`(value, context)`) at runtime. If you're using TS5+ standard decorators (without `experimentalDecorators`), it should work without extra config — see `ts5-decorator.md` for background.
|
|
16
|
+
|
|
10
17
|
### Options
|
|
11
18
|
| Option Name | Type | Required? | Default | Description |
|
|
12
19
|
|:-----------------:|:------------------------:|:---------:|:---------------------------------------:|:-----------------------------------------------------------------------------------------------------------------:|
|
package/dist/example.js
CHANGED
|
@@ -1,12 +1,37 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var
|
|
3
|
-
var
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
2
|
+
var __runInitializers = (this && this.__runInitializers) || function (thisArg, initializers, value) {
|
|
3
|
+
var useValue = arguments.length > 2;
|
|
4
|
+
for (var i = 0; i < initializers.length; i++) {
|
|
5
|
+
value = useValue ? initializers[i].call(thisArg, value) : initializers[i].call(thisArg);
|
|
6
|
+
}
|
|
7
|
+
return useValue ? value : void 0;
|
|
7
8
|
};
|
|
8
|
-
var
|
|
9
|
-
if (
|
|
9
|
+
var __esDecorate = (this && this.__esDecorate) || function (ctor, descriptorIn, decorators, contextIn, initializers, extraInitializers) {
|
|
10
|
+
function accept(f) { if (f !== void 0 && typeof f !== "function") throw new TypeError("Function expected"); return f; }
|
|
11
|
+
var kind = contextIn.kind, key = kind === "getter" ? "get" : kind === "setter" ? "set" : "value";
|
|
12
|
+
var target = !descriptorIn && ctor ? contextIn["static"] ? ctor : ctor.prototype : null;
|
|
13
|
+
var descriptor = descriptorIn || (target ? Object.getOwnPropertyDescriptor(target, contextIn.name) : {});
|
|
14
|
+
var _, done = false;
|
|
15
|
+
for (var i = decorators.length - 1; i >= 0; i--) {
|
|
16
|
+
var context = {};
|
|
17
|
+
for (var p in contextIn) context[p] = p === "access" ? {} : contextIn[p];
|
|
18
|
+
for (var p in contextIn.access) context.access[p] = contextIn.access[p];
|
|
19
|
+
context.addInitializer = function (f) { if (done) throw new TypeError("Cannot add initializers after decoration has completed"); extraInitializers.push(accept(f || null)); };
|
|
20
|
+
var result = (0, decorators[i])(kind === "accessor" ? { get: descriptor.get, set: descriptor.set } : descriptor[key], context);
|
|
21
|
+
if (kind === "accessor") {
|
|
22
|
+
if (result === void 0) continue;
|
|
23
|
+
if (result === null || typeof result !== "object") throw new TypeError("Object expected");
|
|
24
|
+
if (_ = accept(result.get)) descriptor.get = _;
|
|
25
|
+
if (_ = accept(result.set)) descriptor.set = _;
|
|
26
|
+
if (_ = accept(result.init)) initializers.unshift(_);
|
|
27
|
+
}
|
|
28
|
+
else if (_ = accept(result)) {
|
|
29
|
+
if (kind === "field") initializers.unshift(_);
|
|
30
|
+
else descriptor[key] = _;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
if (target) Object.defineProperty(target, contextIn.name, descriptor);
|
|
34
|
+
done = true;
|
|
10
35
|
};
|
|
11
36
|
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
12
37
|
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
@@ -20,101 +45,93 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
20
45
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
21
46
|
const retry_decorator_1 = require("./retry.decorator");
|
|
22
47
|
let count = 1;
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
__metadata("design:type", Function),
|
|
70
|
-
__metadata("design:paramtypes", []),
|
|
71
|
-
__metadata("design:returntype", Promise)
|
|
72
|
-
], RetryExample, "noDelaySpecificRetry", null);
|
|
73
|
-
__decorate([
|
|
74
|
-
(0, retry_decorator_1.Retryable)({
|
|
75
|
-
maxAttempts: 3,
|
|
76
|
-
backOff: 1000,
|
|
77
|
-
doRetry: (e) => {
|
|
78
|
-
return e.message === 'Error: 429';
|
|
79
|
-
},
|
|
80
|
-
}),
|
|
81
|
-
__metadata("design:type", Function),
|
|
82
|
-
__metadata("design:paramtypes", []),
|
|
83
|
-
__metadata("design:returntype", Promise)
|
|
84
|
-
], RetryExample, "doRetry", null);
|
|
85
|
-
__decorate([
|
|
86
|
-
(0, retry_decorator_1.Retryable)({
|
|
87
|
-
maxAttempts: 3,
|
|
88
|
-
backOff: 1000,
|
|
89
|
-
doRetry: (e) => {
|
|
90
|
-
return e.message === 'Error: 429';
|
|
48
|
+
let RetryExample = (() => {
|
|
49
|
+
var _a;
|
|
50
|
+
let _staticExtraInitializers = [];
|
|
51
|
+
let _static_noDelayRetry_decorators;
|
|
52
|
+
let _static_noDelaySpecificRetry_decorators;
|
|
53
|
+
let _static_doRetry_decorators;
|
|
54
|
+
let _static_doNotRetry_decorators;
|
|
55
|
+
let _static_fixedBackOffRetry_decorators;
|
|
56
|
+
let _static_ExponentialBackOffRetry_decorators;
|
|
57
|
+
return _a = class RetryExample {
|
|
58
|
+
static noDelayRetry() {
|
|
59
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
60
|
+
console.info(`Calling noDelayRetry for the ${count++} time at ${new Date().toLocaleTimeString()}`);
|
|
61
|
+
throw new Error('I failed!');
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
static noDelaySpecificRetry() {
|
|
65
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
66
|
+
console.info(`Calling noDelayRetry for the ${count++} time at ${new Date().toLocaleTimeString()}`);
|
|
67
|
+
throw new SyntaxError('I failed with SyntaxError!');
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
static doRetry() {
|
|
71
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
72
|
+
console.info(`Calling doRetry for the ${count++} time at ${new Date().toLocaleTimeString()}`);
|
|
73
|
+
throw new Error('Error: 429');
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
static doNotRetry() {
|
|
77
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
78
|
+
console.info(`Calling doNotRetry for the ${count++} time at ${new Date().toLocaleTimeString()}`);
|
|
79
|
+
throw new Error('Error: 404');
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
static fixedBackOffRetry() {
|
|
83
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
84
|
+
console.info(`Calling fixedBackOffRetry 1s for the ${count++} time at ${new Date().toLocaleTimeString()}`);
|
|
85
|
+
throw new Error('I failed!');
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
static ExponentialBackOffRetry() {
|
|
89
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
90
|
+
console.info(`Calling ExponentialBackOffRetry backOff 1s, multiplier=3 for the ${count++} time at ${new Date().toLocaleTimeString()}`);
|
|
91
|
+
throw new Error('I failed!');
|
|
92
|
+
});
|
|
93
|
+
}
|
|
91
94
|
},
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
95
|
+
(() => {
|
|
96
|
+
const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(null) : void 0;
|
|
97
|
+
_static_noDelayRetry_decorators = [(0, retry_decorator_1.Retryable)({ maxAttempts: 3 })];
|
|
98
|
+
_static_noDelaySpecificRetry_decorators = [(0, retry_decorator_1.Retryable)({ maxAttempts: 3, value: [SyntaxError, ReferenceError] })];
|
|
99
|
+
_static_doRetry_decorators = [(0, retry_decorator_1.Retryable)({
|
|
100
|
+
maxAttempts: 3,
|
|
101
|
+
backOff: 1000,
|
|
102
|
+
doRetry: (e) => {
|
|
103
|
+
return e.message === 'Error: 429';
|
|
104
|
+
},
|
|
105
|
+
})];
|
|
106
|
+
_static_doNotRetry_decorators = [(0, retry_decorator_1.Retryable)({
|
|
107
|
+
maxAttempts: 3,
|
|
108
|
+
backOff: 1000,
|
|
109
|
+
doRetry: (e) => {
|
|
110
|
+
return e.message === 'Error: 429';
|
|
111
|
+
},
|
|
112
|
+
})];
|
|
113
|
+
_static_fixedBackOffRetry_decorators = [(0, retry_decorator_1.Retryable)({
|
|
114
|
+
maxAttempts: 3,
|
|
115
|
+
backOffPolicy: retry_decorator_1.BackOffPolicy.FixedBackOffPolicy,
|
|
116
|
+
backOff: 1000,
|
|
117
|
+
})];
|
|
118
|
+
_static_ExponentialBackOffRetry_decorators = [(0, retry_decorator_1.Retryable)({
|
|
119
|
+
maxAttempts: 3,
|
|
120
|
+
backOffPolicy: retry_decorator_1.BackOffPolicy.ExponentialBackOffPolicy,
|
|
121
|
+
backOff: 1000,
|
|
122
|
+
exponentialOption: { maxInterval: 4000, multiplier: 3 },
|
|
123
|
+
})];
|
|
124
|
+
__esDecorate(_a, null, _static_noDelayRetry_decorators, { kind: "method", name: "noDelayRetry", static: true, private: false, access: { has: obj => "noDelayRetry" in obj, get: obj => obj.noDelayRetry }, metadata: _metadata }, null, _staticExtraInitializers);
|
|
125
|
+
__esDecorate(_a, null, _static_noDelaySpecificRetry_decorators, { kind: "method", name: "noDelaySpecificRetry", static: true, private: false, access: { has: obj => "noDelaySpecificRetry" in obj, get: obj => obj.noDelaySpecificRetry }, metadata: _metadata }, null, _staticExtraInitializers);
|
|
126
|
+
__esDecorate(_a, null, _static_doRetry_decorators, { kind: "method", name: "doRetry", static: true, private: false, access: { has: obj => "doRetry" in obj, get: obj => obj.doRetry }, metadata: _metadata }, null, _staticExtraInitializers);
|
|
127
|
+
__esDecorate(_a, null, _static_doNotRetry_decorators, { kind: "method", name: "doNotRetry", static: true, private: false, access: { has: obj => "doNotRetry" in obj, get: obj => obj.doNotRetry }, metadata: _metadata }, null, _staticExtraInitializers);
|
|
128
|
+
__esDecorate(_a, null, _static_fixedBackOffRetry_decorators, { kind: "method", name: "fixedBackOffRetry", static: true, private: false, access: { has: obj => "fixedBackOffRetry" in obj, get: obj => obj.fixedBackOffRetry }, metadata: _metadata }, null, _staticExtraInitializers);
|
|
129
|
+
__esDecorate(_a, null, _static_ExponentialBackOffRetry_decorators, { kind: "method", name: "ExponentialBackOffRetry", static: true, private: false, access: { has: obj => "ExponentialBackOffRetry" in obj, get: obj => obj.ExponentialBackOffRetry }, metadata: _metadata }, null, _staticExtraInitializers);
|
|
130
|
+
if (_metadata) Object.defineProperty(_a, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
|
|
131
|
+
__runInitializers(_a, _staticExtraInitializers);
|
|
132
|
+
})(),
|
|
133
|
+
_a;
|
|
134
|
+
})();
|
|
118
135
|
(() => __awaiter(void 0, void 0, void 0, function* () {
|
|
119
136
|
try {
|
|
120
137
|
resetCount();
|
package/dist/example.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"example.js","sourceRoot":"","sources":["../src/example.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"example.js","sourceRoot":"","sources":["../src/example.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,9 +1,21 @@
|
|
|
1
|
+
export interface StandardDecoratorContext {
|
|
2
|
+
kind?: string;
|
|
3
|
+
name?: string | symbol;
|
|
4
|
+
}
|
|
5
|
+
export type LegacyDecoratorFunction = (target: Record<string, any>, propertyKey: string | symbol, descriptor: TypedPropertyDescriptor<any>) => TypedPropertyDescriptor<any> | void;
|
|
6
|
+
export type StandardMethodDecorator = (value: (...args: any[]) => any, context: StandardDecoratorContext) => ((...args: any[]) => any) | void;
|
|
7
|
+
export type RetryableDecorator = LegacyDecoratorFunction & StandardMethodDecorator;
|
|
8
|
+
export type DecoratorFunction = LegacyDecoratorFunction;
|
|
1
9
|
/**
|
|
2
|
-
*
|
|
10
|
+
* Retry decorator (legacy + TypeScript 5 standard decorators).
|
|
11
|
+
*
|
|
12
|
+
* In legacy/"experimentalDecorators" mode, it's applied as
|
|
13
|
+
* (target, propertyKey, descriptor)
|
|
3
14
|
*
|
|
4
|
-
*
|
|
15
|
+
* In TS5+ standard decorators mode, it's applied as
|
|
16
|
+
* (value, context)
|
|
5
17
|
*/
|
|
6
|
-
export declare function Retryable(options: RetryOptions):
|
|
18
|
+
export declare function Retryable(options: RetryOptions): RetryableDecorator;
|
|
7
19
|
export declare class MaxAttemptsError extends Error {
|
|
8
20
|
code: string;
|
|
9
21
|
}
|
|
@@ -46,6 +58,5 @@ export declare enum ExponentialBackoffStrategy {
|
|
|
46
58
|
*/
|
|
47
59
|
EqualJitter = "EqualJitter"
|
|
48
60
|
}
|
|
49
|
-
export declare type DecoratorFunction = (target: Record<string, any>, propertyKey: string, descriptor: TypedPropertyDescriptor<any>) => TypedPropertyDescriptor<any>;
|
|
50
61
|
export {};
|
|
51
62
|
//# sourceMappingURL=retry.decorator.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"retry.decorator.d.ts","sourceRoot":"","sources":["../src/retry.decorator.ts"],"names":[],"mappings":"AAEA
|
|
1
|
+
{"version":3,"file":"retry.decorator.d.ts","sourceRoot":"","sources":["../src/retry.decorator.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,wBAAwB;IACvC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;CACxB;AAED,MAAM,MAAM,uBAAuB,GAAG,CACpC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAC3B,WAAW,EAAE,MAAM,GAAG,MAAM,EAC5B,UAAU,EAAE,uBAAuB,CAAC,GAAG,CAAC,KACrC,uBAAuB,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC;AAEzC,MAAM,MAAM,uBAAuB,GAAG,CACpC,KAAK,EAAE,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,GAAG,EAC9B,OAAO,EAAE,wBAAwB,KAC9B,CAAC,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,GAAG,CAAC,GAAG,IAAI,CAAC;AAEtC,MAAM,MAAM,kBAAkB,GAAG,uBAAuB,GAAG,uBAAuB,CAAC;AAGnF,MAAM,MAAM,iBAAiB,GAAG,uBAAuB,CAAC;AAExD;;;;;;;;GAQG;AACH,wBAAgB,SAAS,CAAC,OAAO,EAAE,YAAY,GAAG,kBAAkB,CAuGnE;AAED,qBAAa,gBAAiB,SAAQ,KAAK;IACzC,IAAI,SAAS;CAMd;AAED,UAAU,kBAAkB;IAC1B,KAAK,GAAG,IAAI,EAAE,GAAG,EAAE,GAAG,KAAK,CAAC;CAC7B;AAED,MAAM,WAAW,YAAY;IAC3B,aAAa,CAAC,EAAE,aAAa,CAAC;IAC9B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,CAAC,CAAC,EAAE,GAAG,KAAK,OAAO,CAAC;IAC9B,iBAAiB,CAAC,EAAE;QAClB,WAAW,EAAE,MAAM,CAAC;QACpB,UAAU,EAAE,MAAM,CAAC;QACnB;;;WAGG;QACH,eAAe,CAAC,EAAE,0BAA0B,CAAC;KAC9C,CAAC;IACF,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,kBAAkB,EAAE,CAAC;IAC7B,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC5B;AAED,oBAAY,aAAa;IACvB,kBAAkB,uBAAuB;IACzC,wBAAwB,6BAA6B;CACtD;AAED;;;GAGG;AACH,oBAAY,0BAA0B;IACpC;;OAEG;IACH,UAAU,eAAe;IACzB;;OAEG;IACH,WAAW,gBAAgB;CAC5B"}
|
package/dist/retry.decorator.js
CHANGED
|
@@ -12,42 +12,42 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
12
12
|
exports.ExponentialBackoffStrategy = exports.BackOffPolicy = exports.MaxAttemptsError = exports.Retryable = void 0;
|
|
13
13
|
const utils_1 = require("./utils");
|
|
14
14
|
/**
|
|
15
|
-
*
|
|
15
|
+
* Retry decorator (legacy + TypeScript 5 standard decorators).
|
|
16
16
|
*
|
|
17
|
-
*
|
|
17
|
+
* In legacy/"experimentalDecorators" mode, it's applied as
|
|
18
|
+
* (target, propertyKey, descriptor)
|
|
19
|
+
*
|
|
20
|
+
* In TS5+ standard decorators mode, it's applied as
|
|
21
|
+
* (value, context)
|
|
18
22
|
*/
|
|
19
23
|
function Retryable(options) {
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
* descriptor: A TypedPropertyDescriptor — see the type, leveraging the Object.defineProperty under the hood.
|
|
24
|
-
*
|
|
25
|
-
* NOTE: It's very important here we do not use arrow function otherwise 'this' will be messed up due
|
|
26
|
-
* to the nature how arrow function defines this inside.
|
|
27
|
-
*
|
|
28
|
-
*/
|
|
29
|
-
return function (target, propertyKey, descriptor) {
|
|
30
|
-
const originalFn = descriptor.value;
|
|
31
|
-
// set default value for ExponentialBackOffPolicy
|
|
32
|
-
if (options.backOffPolicy === BackOffPolicy.ExponentialBackOffPolicy) {
|
|
33
|
-
setExponentialBackOffPolicyDefault();
|
|
24
|
+
function setExponentialBackOffPolicyDefault() {
|
|
25
|
+
if (!options.backOff) {
|
|
26
|
+
options.backOff = 1000;
|
|
34
27
|
}
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
28
|
+
options.exponentialOption = Object.assign({ maxInterval: 2000, multiplier: 2 }, options.exponentialOption);
|
|
29
|
+
}
|
|
30
|
+
function applyBackoffStrategy(baseBackoff) {
|
|
31
|
+
var _a;
|
|
32
|
+
const { backoffStrategy } = (_a = options.exponentialOption) !== null && _a !== void 0 ? _a : {};
|
|
33
|
+
if (backoffStrategy === ExponentialBackoffStrategy.EqualJitter) {
|
|
34
|
+
return baseBackoff / 2 + (Math.random() * baseBackoff / 2);
|
|
35
|
+
}
|
|
36
|
+
if (backoffStrategy === ExponentialBackoffStrategy.FullJitter) {
|
|
37
|
+
return Math.random() * baseBackoff;
|
|
38
|
+
}
|
|
39
|
+
return baseBackoff;
|
|
40
|
+
}
|
|
41
|
+
function canRetry(e) {
|
|
42
|
+
var _a;
|
|
43
|
+
if (options.doRetry && !options.doRetry(e)) {
|
|
44
|
+
return false;
|
|
45
|
+
}
|
|
46
|
+
if (((_a = options.value) === null || _a === void 0 ? void 0 : _a.length) && !options.value.some(errorType => e instanceof errorType)) {
|
|
47
|
+
return false;
|
|
48
|
+
}
|
|
49
|
+
return true;
|
|
50
|
+
}
|
|
51
51
|
function retryAsync(fn, args, maxAttempts, backOff) {
|
|
52
52
|
return __awaiter(this, void 0, void 0, function* () {
|
|
53
53
|
try {
|
|
@@ -55,11 +55,13 @@ function Retryable(options) {
|
|
|
55
55
|
}
|
|
56
56
|
catch (e) {
|
|
57
57
|
if (--maxAttempts < 0) {
|
|
58
|
-
(typeof options.useConsoleLogger !== 'boolean' || options.useConsoleLogger) && (e === null || e === void 0 ? void 0 : e.message)
|
|
59
|
-
|
|
58
|
+
if ((typeof options.useConsoleLogger !== 'boolean' || options.useConsoleLogger) && (e === null || e === void 0 ? void 0 : e.message)) {
|
|
59
|
+
console.error(e.message);
|
|
60
|
+
}
|
|
61
|
+
if (options.useOriginalError) {
|
|
60
62
|
throw e;
|
|
63
|
+
}
|
|
61
64
|
const maxAttemptsErrorInstance = new MaxAttemptsError(e === null || e === void 0 ? void 0 : e.message);
|
|
62
|
-
// Add the existing error stack if present
|
|
63
65
|
if (e === null || e === void 0 ? void 0 : e.stack) {
|
|
64
66
|
maxAttemptsErrorInstance.stack = e.stack;
|
|
65
67
|
}
|
|
@@ -68,44 +70,49 @@ function Retryable(options) {
|
|
|
68
70
|
if (!canRetry(e)) {
|
|
69
71
|
throw e;
|
|
70
72
|
}
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
73
|
+
if (backOff) {
|
|
74
|
+
yield (0, utils_1.sleep)(applyBackoffStrategy(backOff));
|
|
75
|
+
if (options.exponentialOption && options.backOffPolicy === BackOffPolicy.ExponentialBackOffPolicy) {
|
|
76
|
+
backOff = Math.min(backOff * options.exponentialOption.multiplier, options.exponentialOption.maxInterval);
|
|
77
|
+
}
|
|
74
78
|
}
|
|
75
79
|
return retryAsync.apply(this, [fn, args, maxAttempts, backOff]);
|
|
76
80
|
}
|
|
77
81
|
});
|
|
78
82
|
}
|
|
79
|
-
function
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
return false;
|
|
83
|
-
}
|
|
84
|
-
if (((_a = options.value) === null || _a === void 0 ? void 0 : _a.length) && !options.value.some(errorType => e instanceof errorType)) {
|
|
85
|
-
return false;
|
|
83
|
+
function wrapWithRetry(originalFn, name) {
|
|
84
|
+
if (options.backOffPolicy === BackOffPolicy.ExponentialBackOffPolicy) {
|
|
85
|
+
setExponentialBackOffPolicyDefault();
|
|
86
86
|
}
|
|
87
|
-
return
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
87
|
+
return function (...args) {
|
|
88
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
89
|
+
try {
|
|
90
|
+
return yield retryAsync.apply(this, [originalFn, args, options.maxAttempts, options.backOff]);
|
|
91
|
+
}
|
|
92
|
+
catch (e) {
|
|
93
|
+
if (e instanceof MaxAttemptsError) {
|
|
94
|
+
const retryForName = typeof name === 'symbol' ? name.toString() : name;
|
|
95
|
+
const msgPrefix = `Failed for '${retryForName !== null && retryForName !== void 0 ? retryForName : originalFn.name}' for ${options.maxAttempts} times.`;
|
|
96
|
+
e.message = e.message ? `${msgPrefix} Original Error: ${e.message}` : msgPrefix;
|
|
97
|
+
}
|
|
98
|
+
throw e;
|
|
99
|
+
}
|
|
100
|
+
});
|
|
101
|
+
};
|
|
92
102
|
}
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
const { backoffStrategy } = (_a = options.exponentialOption) !== null && _a !== void 0 ? _a : {};
|
|
101
|
-
if (backoffStrategy === ExponentialBackoffStrategy.EqualJitter) {
|
|
102
|
-
return baseBackoff / 2 + (Math.random() * baseBackoff / 2);
|
|
103
|
-
}
|
|
104
|
-
if (backoffStrategy === ExponentialBackoffStrategy.FullJitter) {
|
|
105
|
-
return Math.random() * baseBackoff;
|
|
103
|
+
const decorator = function (...decoratorArgs) {
|
|
104
|
+
// Legacy TypeScript decorators: (target, propertyKey, descriptor)
|
|
105
|
+
if (decoratorArgs.length === 3) {
|
|
106
|
+
const [, propertyKey, descriptor] = decoratorArgs;
|
|
107
|
+
const originalFn = descriptor.value;
|
|
108
|
+
descriptor.value = wrapWithRetry(originalFn, propertyKey);
|
|
109
|
+
return descriptor;
|
|
106
110
|
}
|
|
107
|
-
|
|
108
|
-
|
|
111
|
+
// TypeScript 5 standard decorators: (value, context)
|
|
112
|
+
const [value, context] = decoratorArgs;
|
|
113
|
+
return wrapWithRetry(value, context === null || context === void 0 ? void 0 : context.name);
|
|
114
|
+
};
|
|
115
|
+
return decorator;
|
|
109
116
|
}
|
|
110
117
|
exports.Retryable = Retryable;
|
|
111
118
|
class MaxAttemptsError extends Error {
|
|
@@ -124,7 +131,7 @@ var BackOffPolicy;
|
|
|
124
131
|
(function (BackOffPolicy) {
|
|
125
132
|
BackOffPolicy["FixedBackOffPolicy"] = "FixedBackOffPolicy";
|
|
126
133
|
BackOffPolicy["ExponentialBackOffPolicy"] = "ExponentialBackOffPolicy";
|
|
127
|
-
})(BackOffPolicy
|
|
134
|
+
})(BackOffPolicy || (exports.BackOffPolicy = BackOffPolicy = {}));
|
|
128
135
|
/**
|
|
129
136
|
* Represents different strategies for applying jitter to backoff times.
|
|
130
137
|
* @see https://aws.amazon.com/blogs/architecture/exponential-backoff-and-jitter/
|
|
@@ -139,5 +146,5 @@ var ExponentialBackoffStrategy;
|
|
|
139
146
|
* The backoff time will be (base backoff time / 2) + (random number between 0 and (base backoff time / 2)).
|
|
140
147
|
*/
|
|
141
148
|
ExponentialBackoffStrategy["EqualJitter"] = "EqualJitter";
|
|
142
|
-
})(ExponentialBackoffStrategy
|
|
149
|
+
})(ExponentialBackoffStrategy || (exports.ExponentialBackoffStrategy = ExponentialBackoffStrategy = {}));
|
|
143
150
|
//# sourceMappingURL=retry.decorator.js.map
|