@mimik/request-retry 4.0.3 → 4.0.4
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/README.md +46 -33
- package/eslint.config.js +12 -6
- package/index.js +62 -49
- package/lib/common.js +13 -0
- package/lib/rp-axios-wrapper.js +3 -1
- package/lib/validate.js +8 -9
- package/manual-test/httpMock.js +3 -2
- package/manual-test/man.js +4 -2
- package/manual-test/retryMockMan.js +14 -11
- package/manual-test/testRace.js +5 -6
- package/manual-test/testRetry.js +3 -1
- package/package.json +10 -10
- package/test/retryMock.js +14 -13
- package/test/rpRetry.spec.js +21 -16
- package/test/testEnv.js +1 -1
package/README.md
CHANGED
|
@@ -10,53 +10,66 @@ import rp from '@mimik/request-retry';
|
|
|
10
10
|
<a name="module_request-retry..rpRetry"></a>
|
|
11
11
|
|
|
12
12
|
### request-retry~rpRetry(options) ⇒ <code>Promise</code>
|
|
13
|
-
Make a request with
|
|
13
|
+
Make a request with retries.
|
|
14
14
|
|
|
15
15
|
**Kind**: inner method of [<code>request-retry</code>](#module_request-retry)
|
|
16
|
-
**Returns**: <code>Promise</code> - .
|
|
17
16
|
**Category**: async
|
|
18
17
|
**Throws**:
|
|
19
18
|
|
|
20
|
-
- <code>
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
-
|
|
25
|
-
|
|
26
|
-
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
- *
|
|
32
|
-
-
|
|
33
|
-
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
19
|
+
- <code>Error</code> An error produced by `getRichError`, wrapping an error from
|
|
20
|
+
[request-promise](https://www.npmjs.com/package/request-promise) or a `TimeoutError`.
|
|
21
|
+
|
|
22
|
+
The following properties may be added to the `options` object under the `retry` property:
|
|
23
|
+
- retries `{int}`: Maximum number of retries, independent of the `retryStrategy`. Default: `2`.
|
|
24
|
+
If the value is `< 0` it is set to `0`; if `> 15` it is set to `15`.
|
|
25
|
+
- delay `{int}`: Delay between retries in milliseconds when no `delayStrategy` is provided. Default: `1000`.
|
|
26
|
+
If the value is `< 20` it is set to `20`; if `> 30000` it is set to `30000`.
|
|
27
|
+
- delayStrategy `{function}`: A function that returns the delay (in milliseconds) to wait before the next retry.
|
|
28
|
+
Signature: `(nbRetry, err, options, correlationId)`. Must return a number `> 0` and `< 30000`; otherwise `delay` is used.
|
|
29
|
+
- logLevel `{object}`: Controls logging behavior:
|
|
30
|
+
- *response*: Log level for responses. Default: `silly` (invalid values fall back to `silly`).
|
|
31
|
+
- *error*: Log level for errors. Default: `silly` (invalid values fall back to `silly`).
|
|
32
|
+
- *request*: Log level for requests. Default: `silly` (invalid values fall back to `silly`).
|
|
33
|
+
- *responseDetails*: Detail level when displaying the response: `count`, `type`, or `full`. Default: `type`
|
|
34
|
+
(invalid values fall back to `type`).
|
|
35
|
+
- *responseName*: Label associated with the response. Default: `response`
|
|
36
|
+
(non-string or empty values fall back to `response`).
|
|
37
|
+
- timeout `{int}`: Request timeout (in seconds) applied to the initial request and all retries.
|
|
38
|
+
If reached, a `TimeoutError` is thrown. Default: `50`. Values `< 10` are set to `10`; values `> 120` are set to `120`.
|
|
39
|
+
- retryStrategy `{function}`: A function that decides whether to retry. Signature:
|
|
40
|
+
`(nbRetry, err, options, correlationId)`. Must return a boolean; otherwise it is ignored.
|
|
41
|
+
|
|
42
|
+
The following properties may be added to the `options` object under the `metrics` property:
|
|
43
|
+
- HTTPRequestDuration `{function}`: A `prom-client` metric function to measure request duration.
|
|
44
|
+
- url `{string}`: Optional URL label for the metric. If omitted, the request URL is used.
|
|
45
|
+
|
|
46
|
+
The **default** `retryStrategy` is:
|
|
47
|
+
|
|
48
|
+
```javascript
|
|
41
49
|
defaultRetry = (...args) => {
|
|
42
50
|
const { statusCode } = args[1]; // err
|
|
43
|
-
|
|
44
|
-
return (statusCode && (Math.floor(statusCode / 100) === 5 || statusCode === 429))
|
|
51
|
+
// Retry on 5xx and 429. If there is no statusCode, retry unless it's an "Invalid URI" error.
|
|
52
|
+
return (statusCode && (Math.floor(statusCode / 100) === 5 || statusCode === 429))
|
|
53
|
+
|| (!statusCode && !args[1].message.includes('Invalid URI'));
|
|
45
54
|
};
|
|
46
55
|
```
|
|
47
|
-
If logLevel is empty, request and response will be logged as info and the response will be in response property with full details. Error on the request will generate a warning. If logLevel is not empty but not complete, logLevel will take control over default.
|
|
48
56
|
|
|
49
|
-
If
|
|
57
|
+
If `logLevel` is empty, requests and responses are logged at `info`, the response is logged with full details
|
|
58
|
+
under the `response` property, and request errors generate a `warn`. If `logLevel` is provided but incomplete,
|
|
59
|
+
the provided keys override the defaults.
|
|
60
|
+
|
|
61
|
+
If not already set, the `User-Agent` header is set to:
|
|
62
|
+
`mimik-{serverType}/{serverVersion}/{serverId} {architecture} {node}`.
|
|
50
63
|
|
|
51
|
-
To
|
|
52
|
-
- `uri` takes
|
|
53
|
-
- `
|
|
54
|
-
- `qs` is
|
|
64
|
+
To ease migration from `request-promise`, the following adjustments are applied to `options`:
|
|
65
|
+
- `uri` takes precedence over `url`.
|
|
66
|
+
- If `json` is an object, `body` takes precedence over `json`; both are mapped to Axios `data`.
|
|
67
|
+
- `qs` is mapped to Axios `params`.
|
|
55
68
|
|
|
56
69
|
**Requires**: <code>module:@mimik/sumologic-winston-logger</code>, <code>module:@mimik/response-helper</code>
|
|
57
|
-
**Fulfil**: <code>object</code> -
|
|
70
|
+
**Fulfil**: <code>object</code> - The Axios response when `resolveWithFullResponse` is `true`; otherwise `response.data`.
|
|
58
71
|
|
|
59
72
|
| Param | Type | Description |
|
|
60
73
|
| --- | --- | --- |
|
|
61
|
-
| options | <code>object</code> | Options for the request
|
|
74
|
+
| options | <code>object</code> | Options for the request (similar to [axios](https://www.npmjs.com/package/axios)). The `validateStatus` option is disabled: an error is thrown for status codes outside **[200, 300)**. An additional option, `resolveWithFullResponse`, controls the return shape: when `true`, the full Axios response object is returned; when `false` or omitted, only `response.data` is returned. |
|
|
62
75
|
|
package/eslint.config.js
CHANGED
|
@@ -10,6 +10,9 @@ const MAX_LINES_IN_FUNCTION = 150;
|
|
|
10
10
|
const MAX_STATEMENTS_IN_FUNCTION = 45;
|
|
11
11
|
const MIN_KEYS_IN_OBJECT = 10;
|
|
12
12
|
const MAX_COMPLEXITY = 30;
|
|
13
|
+
const ECMA_VERSION = 2022;
|
|
14
|
+
const MAX_DEPTH = 6;
|
|
15
|
+
const ALLOWED_CONSTANTS = [0, 1, -1];
|
|
13
16
|
|
|
14
17
|
export default [
|
|
15
18
|
{
|
|
@@ -23,7 +26,7 @@ export default [
|
|
|
23
26
|
processDoc,
|
|
24
27
|
},
|
|
25
28
|
languageOptions: {
|
|
26
|
-
ecmaVersion:
|
|
29
|
+
ecmaVersion: ECMA_VERSION,
|
|
27
30
|
globals: {
|
|
28
31
|
console: 'readonly',
|
|
29
32
|
describe: 'readonly',
|
|
@@ -35,6 +38,7 @@ export default [
|
|
|
35
38
|
rules: {
|
|
36
39
|
'@stylistic/brace-style': ['warn', 'stroustrup', { allowSingleLine: true }],
|
|
37
40
|
'@stylistic/line-comment-position': ['off'],
|
|
41
|
+
'@stylistic/max-len': ['warn', MAX_LENGTH_LINE, { ignoreComments: true, ignoreStrings: true, ignoreRegExpLiterals: true }],
|
|
38
42
|
'@stylistic/semi': ['error', 'always'],
|
|
39
43
|
'capitalized-comments': ['off'],
|
|
40
44
|
'complexity': ['error', MAX_COMPLEXITY],
|
|
@@ -44,20 +48,22 @@ export default [
|
|
|
44
48
|
'import/no-unresolved': ['error', { amd: true, caseSensitiveStrict: true, commonjs: true }],
|
|
45
49
|
'init-declarations': ['off'],
|
|
46
50
|
'linebreak-style': ['off'],
|
|
47
|
-
'max-
|
|
48
|
-
'max-lines': ['warn', { max: MAX_LINES_IN_FILES, skipComments: true }],
|
|
49
|
-
'max-lines-per-function': ['warn', { max: MAX_LINES_IN_FUNCTION, skipComments: true }],
|
|
51
|
+
'max-depth': ['error', MAX_DEPTH],
|
|
52
|
+
'max-lines': ['warn', { max: MAX_LINES_IN_FILES, skipComments: true, skipBlankLines: true }],
|
|
53
|
+
'max-lines-per-function': ['warn', { max: MAX_LINES_IN_FUNCTION, skipComments: true, skipBlankLines: true }],
|
|
50
54
|
'max-params': ['error', MAX_FUNCTION_PARAMETERS],
|
|
51
55
|
'max-statements': ['warn', MAX_STATEMENTS_IN_FUNCTION],
|
|
52
|
-
'no-confusing-arrow': ['off'],
|
|
56
|
+
'no-confusing-arrow': ['off'],
|
|
53
57
|
'no-inline-comments': ['off'],
|
|
58
|
+
'no-magic-numbers': ['error', { ignore: ALLOWED_CONSTANTS, enforceConst: true, detectObjects: true }],
|
|
54
59
|
'no-process-env': ['error'],
|
|
55
60
|
'no-ternary': ['off'],
|
|
56
61
|
'no-undefined': ['off'],
|
|
57
62
|
'one-var': ['error', 'never'],
|
|
58
63
|
'processDoc/validate-document-env': ['error'],
|
|
59
64
|
'quotes': ['warn', 'single'],
|
|
60
|
-
'sort-
|
|
65
|
+
'sort-imports': ['error', { allowSeparatedGroups: true }],
|
|
66
|
+
'sort-keys': ['error', 'asc', { caseSensitive: true, minKeys: MIN_KEYS_IN_OBJECT, natural: false, allowLineSeparatedGroups: true }],
|
|
61
67
|
},
|
|
62
68
|
},
|
|
63
69
|
];
|
package/index.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { OK, SYSTEM_ERROR } from './lib/common.js';
|
|
1
2
|
import {
|
|
2
3
|
calculateDelay,
|
|
3
4
|
isRetry,
|
|
@@ -7,7 +8,7 @@ import {
|
|
|
7
8
|
import {
|
|
8
9
|
clearTimeout,
|
|
9
10
|
setTimeout,
|
|
10
|
-
} from 'timers';
|
|
11
|
+
} from 'node:timers';
|
|
11
12
|
import {
|
|
12
13
|
getCorrelationId,
|
|
13
14
|
setUserAgent,
|
|
@@ -15,7 +16,7 @@ import {
|
|
|
15
16
|
import Promise from 'bluebird';
|
|
16
17
|
import { getRichError } from '@mimik/response-helper';
|
|
17
18
|
import logger from '@mimik/sumologic-winston-logger';
|
|
18
|
-
import process from 'process';
|
|
19
|
+
import process from 'node:process';
|
|
19
20
|
import { rp } from './lib/rp-axios-wrapper.js';
|
|
20
21
|
|
|
21
22
|
const DEFAULT_RESPONSE_NAME = 'response';
|
|
@@ -26,13 +27,8 @@ const DEFAULT_LOGLEVEL_REQUEST = 'info';
|
|
|
26
27
|
|
|
27
28
|
const MILLI_SECONDS = 0;
|
|
28
29
|
const MILLI_NANO_SECONDS = 1;
|
|
29
|
-
const INCR = 1;
|
|
30
30
|
const MILLI = 1000;
|
|
31
31
|
const NANO = 1e6;
|
|
32
|
-
const EMPTY = 0;
|
|
33
|
-
const NONE = 0;
|
|
34
|
-
const OK_RESPONSE = 200;
|
|
35
|
-
const SYSTEM_ERROR = 500;
|
|
36
32
|
|
|
37
33
|
Promise.config({ cancellation: true });
|
|
38
34
|
|
|
@@ -45,50 +41,67 @@ Promise.config({ cancellation: true });
|
|
|
45
41
|
*/
|
|
46
42
|
|
|
47
43
|
/**
|
|
48
|
-
* Make a request with
|
|
44
|
+
* Make a request with retries.
|
|
49
45
|
*
|
|
50
46
|
* @function rpRetry
|
|
51
47
|
* @requires @mimik/sumologic-winston-logger
|
|
52
48
|
* @requires @mimik/response-helper
|
|
53
49
|
* @category async
|
|
54
|
-
* @param {object} options - Options for the request
|
|
55
|
-
*
|
|
56
|
-
*
|
|
57
|
-
*
|
|
50
|
+
* @param {object} options - Options for the request (similar to [axios](https://www.npmjs.com/package/axios)).
|
|
51
|
+
* The `validateStatus` option is disabled: an error is thrown for status codes outside **[200, 300)**.
|
|
52
|
+
* An additional option, `resolveWithFullResponse`, controls the return shape:
|
|
53
|
+
* when `true`, the full Axios response object is returned; when `false` or omitted, only `response.data` is returned.
|
|
54
|
+
* @return {Promise}
|
|
55
|
+
* @fulfil {object} - The Axios response when `resolveWithFullResponse` is `true`; otherwise `response.data`.
|
|
56
|
+
* @throws {Error} An error produced by `getRichError`, wrapping an error from
|
|
57
|
+
* [request-promise](https://www.npmjs.com/package/request-promise) or a `TimeoutError`.
|
|
58
58
|
*
|
|
59
|
-
* The following properties
|
|
60
|
-
* - retries `{int}`:
|
|
61
|
-
*
|
|
62
|
-
* -
|
|
63
|
-
*
|
|
64
|
-
*
|
|
65
|
-
*
|
|
66
|
-
*
|
|
67
|
-
* - *
|
|
68
|
-
* - *
|
|
69
|
-
*
|
|
70
|
-
*
|
|
71
|
-
*
|
|
72
|
-
*
|
|
73
|
-
*
|
|
59
|
+
* The following properties may be added to the `options` object under the `retry` property:
|
|
60
|
+
* - retries `{int}`: Maximum number of retries, independent of the `retryStrategy`. Default: `2`.
|
|
61
|
+
* If the value is `< 0` it is set to `0`; if `> 15` it is set to `15`.
|
|
62
|
+
* - delay `{int}`: Delay between retries in milliseconds when no `delayStrategy` is provided. Default: `1000`.
|
|
63
|
+
* If the value is `< 20` it is set to `20`; if `> 30000` it is set to `30000`.
|
|
64
|
+
* - delayStrategy `{function}`: A function that returns the delay (in milliseconds) to wait before the next retry.
|
|
65
|
+
* Signature: `(nbRetry, err, options, correlationId)`. Must return a number `> 0` and `< 30000`; otherwise `delay` is used.
|
|
66
|
+
* - logLevel `{object}`: Controls logging behavior:
|
|
67
|
+
* - *response*: Log level for responses. Default: `silly` (invalid values fall back to `silly`).
|
|
68
|
+
* - *error*: Log level for errors. Default: `silly` (invalid values fall back to `silly`).
|
|
69
|
+
* - *request*: Log level for requests. Default: `silly` (invalid values fall back to `silly`).
|
|
70
|
+
* - *responseDetails*: Detail level when displaying the response: `count`, `type`, or `full`. Default: `type`
|
|
71
|
+
* (invalid values fall back to `type`).
|
|
72
|
+
* - *responseName*: Label associated with the response. Default: `response`
|
|
73
|
+
* (non-string or empty values fall back to `response`).
|
|
74
|
+
* - timeout `{int}`: Request timeout (in seconds) applied to the initial request and all retries.
|
|
75
|
+
* If reached, a `TimeoutError` is thrown. Default: `50`. Values `< 10` are set to `10`; values `> 120` are set to `120`.
|
|
76
|
+
* - retryStrategy `{function}`: A function that decides whether to retry. Signature:
|
|
77
|
+
* `(nbRetry, err, options, correlationId)`. Must return a boolean; otherwise it is ignored.
|
|
74
78
|
*
|
|
75
|
-
* The `
|
|
79
|
+
* The following properties may be added to the `options` object under the `metrics` property:
|
|
80
|
+
* - HTTPRequestDuration `{function}`: A `prom-client` metric function to measure request duration.
|
|
81
|
+
* - url `{string}`: Optional URL label for the metric. If omitted, the request URL is used.
|
|
76
82
|
*
|
|
77
|
-
|
|
83
|
+
* The **default** `retryStrategy` is:
|
|
84
|
+
*
|
|
85
|
+
* ```javascript
|
|
78
86
|
* defaultRetry = (...args) => {
|
|
79
87
|
* const { statusCode } = args[1]; // err
|
|
80
|
-
*
|
|
81
|
-
* return (statusCode && (Math.floor(statusCode / 100) === 5 || statusCode === 429))
|
|
88
|
+
* // Retry on 5xx and 429. If there is no statusCode, retry unless it's an "Invalid URI" error.
|
|
89
|
+
* return (statusCode && (Math.floor(statusCode / 100) === 5 || statusCode === 429))
|
|
90
|
+
* || (!statusCode && !args[1].message.includes('Invalid URI'));
|
|
82
91
|
* };
|
|
83
|
-
|
|
84
|
-
*
|
|
92
|
+
* ```
|
|
93
|
+
*
|
|
94
|
+
* If `logLevel` is empty, requests and responses are logged at `info`, the response is logged with full details
|
|
95
|
+
* under the `response` property, and request errors generate a `warn`. If `logLevel` is provided but incomplete,
|
|
96
|
+
* the provided keys override the defaults.
|
|
85
97
|
*
|
|
86
|
-
* If not
|
|
98
|
+
* If not already set, the `User-Agent` header is set to:
|
|
99
|
+
* `mimik-{serverType}/{serverVersion}/{serverId} {architecture} {node}`.
|
|
87
100
|
*
|
|
88
|
-
* To
|
|
89
|
-
* - `uri` takes
|
|
90
|
-
* - `
|
|
91
|
-
* - `qs` is
|
|
101
|
+
* To ease migration from `request-promise`, the following adjustments are applied to `options`:
|
|
102
|
+
* - `uri` takes precedence over `url`.
|
|
103
|
+
* - If `json` is an object, `body` takes precedence over `json`; both are mapped to Axios `data`.
|
|
104
|
+
* - `qs` is mapped to Axios `params`.
|
|
92
105
|
*/
|
|
93
106
|
export const rpRetry = (origOptions) => {
|
|
94
107
|
const startHrTime = process.hrtime();
|
|
@@ -101,7 +114,7 @@ export const rpRetry = (origOptions) => {
|
|
|
101
114
|
const criteria = validateOptions(options, correlationId);
|
|
102
115
|
const { logLevel } = criteria;
|
|
103
116
|
const logLevelLength = Object.keys(logLevel).length;
|
|
104
|
-
let nbRetries =
|
|
117
|
+
let nbRetries = 0;
|
|
105
118
|
let mainTimeout;
|
|
106
119
|
const measure = (statusCode) => {
|
|
107
120
|
if (metrics && metrics.HTTPRequestDuration) {
|
|
@@ -127,7 +140,7 @@ export const rpRetry = (origOptions) => {
|
|
|
127
140
|
info[logLevel.responseName] = setResponse(response, logLevel.responseDetails);
|
|
128
141
|
logger[logLevel.response]('request response', info, correlationId);
|
|
129
142
|
}
|
|
130
|
-
else if (logLevelLength ===
|
|
143
|
+
else if (logLevelLength === 0) {
|
|
131
144
|
info[DEFAULT_RESPONSE_NAME] = setResponse(response, DEFAULT_LOGLEVEL_DETAILS);
|
|
132
145
|
logger[DEFAULT_LOGLEVEL_RESPONSE]('request response', info, correlationId);
|
|
133
146
|
}
|
|
@@ -135,16 +148,16 @@ export const rpRetry = (origOptions) => {
|
|
|
135
148
|
})
|
|
136
149
|
.catch((err) => {
|
|
137
150
|
if ((nbRetry < criteria.retries) && isRetry(options, nbRetry, criteria, err, correlationId)) {
|
|
138
|
-
nbRetries = nbRetry +
|
|
151
|
+
nbRetries = nbRetry + 1;
|
|
139
152
|
errors.push(err);
|
|
140
153
|
const delayPromise = Promise.delay(calculateDelay(options, nbRetry, criteria, err, correlationId));
|
|
141
154
|
|
|
142
155
|
delayPromises.unshift(delayPromise);
|
|
143
|
-
return delayPromise.then(() => retryProcess(nbRetry +
|
|
156
|
+
return delayPromise.then(() => retryProcess(nbRetry + 1));
|
|
144
157
|
}
|
|
145
158
|
const error = err;
|
|
146
159
|
|
|
147
|
-
if (nbRetries !==
|
|
160
|
+
if (nbRetries !== 0) {
|
|
148
161
|
if (!error.info) error.info = {};
|
|
149
162
|
error.info.retry = {
|
|
150
163
|
nbRetries,
|
|
@@ -156,18 +169,18 @@ export const rpRetry = (origOptions) => {
|
|
|
156
169
|
'request error response',
|
|
157
170
|
{ options: optionsInfo },
|
|
158
171
|
error,
|
|
159
|
-
logLevel.error || ((logLevelLength ===
|
|
172
|
+
logLevel.error || ((logLevelLength === 0) ? DEFAULT_LOGLEVEL_ERROR : undefined),
|
|
160
173
|
correlationId,
|
|
161
174
|
);
|
|
162
175
|
});
|
|
163
176
|
|
|
164
|
-
const retryPromise = retryProcess(
|
|
177
|
+
const retryPromise = retryProcess(0);
|
|
165
178
|
const mainTimeoutPromise = new Promise((resolve, reject) => {
|
|
166
179
|
mainTimeout = setTimeout(() => {
|
|
167
180
|
delayPromises.forEach(delayPromise => delayPromise.cancel(`retry timeout delay, ${criteria.timeout}, ${nbRetries}`));
|
|
168
181
|
let error = new Error('retry timeout');
|
|
169
182
|
|
|
170
|
-
if (nbRetries !==
|
|
183
|
+
if (nbRetries !== 0) {
|
|
171
184
|
error.info = { retry: { nbRetries, errors } };
|
|
172
185
|
}
|
|
173
186
|
error.name = 'TimeoutError';
|
|
@@ -176,7 +189,7 @@ export const rpRetry = (origOptions) => {
|
|
|
176
189
|
'request error response',
|
|
177
190
|
{ options: optionsInfo },
|
|
178
191
|
error,
|
|
179
|
-
logLevel.error || ((logLevelLength ===
|
|
192
|
+
logLevel.error || ((logLevelLength === 0) ? DEFAULT_LOGLEVEL_ERROR : undefined),
|
|
180
193
|
correlationId,
|
|
181
194
|
);
|
|
182
195
|
reject(error);
|
|
@@ -184,12 +197,12 @@ export const rpRetry = (origOptions) => {
|
|
|
184
197
|
});
|
|
185
198
|
|
|
186
199
|
if (logLevel.request) logger[logLevel.request]('making a request', { options: optionsInfo, criteria }, correlationId);
|
|
187
|
-
else if (logLevelLength ===
|
|
200
|
+
else if (logLevelLength === 0) logger[DEFAULT_LOGLEVEL_REQUEST]('making a request', { options: optionsInfo, criteria }, correlationId);
|
|
188
201
|
return Promise.race([retryPromise, mainTimeoutPromise])
|
|
189
202
|
.then((result) => {
|
|
190
203
|
mainTimeoutPromise.cancel('main timeout');
|
|
191
204
|
clearTimeout(mainTimeout);
|
|
192
|
-
measure(
|
|
205
|
+
measure(OK);
|
|
193
206
|
return result;
|
|
194
207
|
})
|
|
195
208
|
.catch((err) => {
|
package/lib/common.js
ADDED
package/lib/rp-axios-wrapper.js
CHANGED
package/lib/validate.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { TOO_MANY_REQUESTS_ERROR } from './common.js';
|
|
1
2
|
import logger from '@mimik/sumologic-winston-logger';
|
|
2
3
|
|
|
3
4
|
const DETAILS = ['full', 'type', 'count'];
|
|
@@ -7,15 +8,13 @@ const [, , , , , DEFAULT_LOGLEVEL/* 'silly' */] = logger.LEVELS;
|
|
|
7
8
|
const DEFAULT_RETRIES = 2;
|
|
8
9
|
const MIN_RETRIES = 0;
|
|
9
10
|
const MAX_RETRIES = 15;
|
|
10
|
-
const DEFAULT_DELAY = 1000; // in
|
|
11
|
-
const MIN_DELAY = 20; // in
|
|
12
|
-
const MAX_DELAY = 30000; // in
|
|
11
|
+
const DEFAULT_DELAY = 1000; // in millisecond
|
|
12
|
+
const MIN_DELAY = 20; // in millisecond
|
|
13
|
+
const MAX_DELAY = 30000; // in millisecond
|
|
13
14
|
const NO_DELAY = 0;
|
|
14
|
-
const DEFAULT_TIMEOUT = 50; // in
|
|
15
|
-
const MIN_TIMEOUT = 10; // in
|
|
16
|
-
const MAX_TIMEOUT = 120; // in
|
|
17
|
-
const TOO_MANY_REQUESTS_ERROR = 429;
|
|
18
|
-
const EMPTY = 0;
|
|
15
|
+
const DEFAULT_TIMEOUT = 50; // in second
|
|
16
|
+
const MIN_TIMEOUT = 10; // in second
|
|
17
|
+
const MAX_TIMEOUT = 120; // in second
|
|
19
18
|
const SYSTEM_RANGE = 5;
|
|
20
19
|
const SYSTEM_RANGE_EXTRACT = 100;
|
|
21
20
|
const ARG_ERROR = 1;
|
|
@@ -80,7 +79,7 @@ const validateOptions = (options, correlationId) => {
|
|
|
80
79
|
};
|
|
81
80
|
const validateResponseName = (val, name, defaultValue) => {
|
|
82
81
|
if (!val && val !== '') return defaultValue;
|
|
83
|
-
if (typeof val !== 'string' || val.length ===
|
|
82
|
+
if (typeof val !== 'string' || val.length === 0 || val.trim().length === 0) {
|
|
84
83
|
logger.warn(`invalid logLevel.${name}, reset to default`, { name, value: val, defaultValue }, correlationId);
|
|
85
84
|
return defaultValue;
|
|
86
85
|
}
|
package/manual-test/httpMock.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
/* eslint-disable no-console */
|
|
2
|
+
import { OK } from '../lib/common.js';
|
|
2
3
|
import bodyParser from 'body-parser';
|
|
3
4
|
import express from 'express';
|
|
4
5
|
|
|
@@ -8,9 +9,9 @@ const app = express();
|
|
|
8
9
|
|
|
9
10
|
app.use(bodyParser.json());
|
|
10
11
|
app.get('/success', (req, res) => {
|
|
11
|
-
res.statusCode =
|
|
12
|
+
res.statusCode = OK;
|
|
12
13
|
|
|
13
|
-
res.send({ statusCode:
|
|
14
|
+
res.send({ statusCode: OK });
|
|
14
15
|
});
|
|
15
16
|
|
|
16
17
|
app.listen(PORT, () => {
|
package/manual-test/man.js
CHANGED
|
@@ -3,6 +3,8 @@ import './testEnv';
|
|
|
3
3
|
import { rpRetry } from '../index.js';
|
|
4
4
|
|
|
5
5
|
const DELAY = 1000;
|
|
6
|
+
const RETRY_TIMEOUT = 10;
|
|
7
|
+
const RETRY_RETRIES = 2;
|
|
6
8
|
|
|
7
9
|
const correlationId = `--request-retry-test--/${new Date().toISOString()}`;
|
|
8
10
|
|
|
@@ -17,8 +19,8 @@ const options = {
|
|
|
17
19
|
};
|
|
18
20
|
|
|
19
21
|
options.retry.delayStrategy = () => DELAY;
|
|
20
|
-
options.retry.timeout =
|
|
21
|
-
options.retry.retries =
|
|
22
|
+
options.retry.timeout = RETRY_TIMEOUT;
|
|
23
|
+
options.retry.retries = RETRY_RETRIES;
|
|
22
24
|
|
|
23
25
|
rpRetry(options)
|
|
24
26
|
.catch(err => console.log(err));
|
|
@@ -1,24 +1,27 @@
|
|
|
1
1
|
/* eslint-disable no-console */
|
|
2
|
+
import { CREATED, OK, SYSTEM_ERROR } from '../lib/common.js';
|
|
2
3
|
import bodyParser from 'body-parser';
|
|
3
4
|
import express from 'express';
|
|
4
|
-
import { setTimeout } from 'timers';
|
|
5
|
+
import { setTimeout } from 'node:timers';
|
|
5
6
|
|
|
6
|
-
const
|
|
7
|
-
const
|
|
7
|
+
const PORT = 9080;
|
|
8
|
+
const GET_NB_RETRY = 400;
|
|
9
|
+
const GET_TIMEOUT = 4000;
|
|
8
10
|
|
|
9
11
|
const app = express();
|
|
12
|
+
|
|
10
13
|
const config = {
|
|
11
|
-
port:
|
|
14
|
+
port: PORT,
|
|
12
15
|
path: '/retry',
|
|
13
16
|
base: '/test',
|
|
14
17
|
get: {
|
|
15
|
-
nbRetry:
|
|
16
|
-
success:
|
|
17
|
-
error:
|
|
18
|
-
timeout:
|
|
18
|
+
nbRetry: GET_NB_RETRY,
|
|
19
|
+
success: OK,
|
|
20
|
+
error: SYSTEM_ERROR,
|
|
21
|
+
timeout: GET_TIMEOUT,
|
|
19
22
|
},
|
|
20
23
|
post: {
|
|
21
|
-
success:
|
|
24
|
+
success: CREATED,
|
|
22
25
|
},
|
|
23
26
|
};
|
|
24
27
|
let nbRequest = 0;
|
|
@@ -27,7 +30,7 @@ let message;
|
|
|
27
30
|
|
|
28
31
|
app.use(bodyParser.json());
|
|
29
32
|
app.get(`${config.base}${config.path}`, (req, res) => {
|
|
30
|
-
if (nbRequest ===
|
|
33
|
+
if (nbRequest === 0) message = 'Recieved first request';
|
|
31
34
|
else {
|
|
32
35
|
const timeLap = Date.now() - time;
|
|
33
36
|
|
|
@@ -41,7 +44,7 @@ app.get(`${config.base}${config.path}`, (req, res) => {
|
|
|
41
44
|
res.send({ statusCode: config.get.success });
|
|
42
45
|
return;
|
|
43
46
|
}
|
|
44
|
-
nbRequest +=
|
|
47
|
+
nbRequest += 1;
|
|
45
48
|
setTimeout(() => {
|
|
46
49
|
res.statusCode = config.get.error;
|
|
47
50
|
res.send({ statusCode: config.get.error });
|
package/manual-test/testRace.js
CHANGED
|
@@ -4,20 +4,19 @@ import {
|
|
|
4
4
|
setTimeout,
|
|
5
5
|
} from 'timers';
|
|
6
6
|
|
|
7
|
-
const INCR = 1;
|
|
8
7
|
const MAX_INCR = 100000000;
|
|
9
|
-
const
|
|
8
|
+
const MAIN_TIMEOUT = 1; // in millisecond
|
|
10
9
|
|
|
11
10
|
const doSomething = () => {
|
|
12
11
|
let add = 0;
|
|
13
12
|
|
|
14
|
-
for (let i = 0; i < MAX_INCR; i +=
|
|
15
|
-
add +=
|
|
13
|
+
for (let i = 0; i < MAX_INCR; i += 1) {
|
|
14
|
+
add += 1;
|
|
16
15
|
console.log(add);
|
|
17
16
|
}
|
|
18
17
|
return add;
|
|
19
18
|
};
|
|
20
|
-
const timeout =
|
|
19
|
+
const timeout = MAIN_TIMEOUT;
|
|
21
20
|
|
|
22
21
|
const race = () => {
|
|
23
22
|
let result;
|
|
@@ -30,7 +29,7 @@ const race = () => {
|
|
|
30
29
|
}
|
|
31
30
|
catch (err) {
|
|
32
31
|
console.log(err);
|
|
33
|
-
result =
|
|
32
|
+
result = 0;
|
|
34
33
|
}
|
|
35
34
|
clearTimeout(mainTimeout);
|
|
36
35
|
return result;
|
package/manual-test/testRetry.js
CHANGED
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
import '../test/testEnv.js';
|
|
3
3
|
import { rpRetry } from '../index.js';
|
|
4
4
|
|
|
5
|
+
const TIMEOUT = 20000; // in millisecond
|
|
6
|
+
|
|
5
7
|
const options = {
|
|
6
8
|
method: 'GET',
|
|
7
9
|
url: 'http://api.swaggerhub.com/apis/mimik/Boxes/1.2.1', // 'http://www.google.com', // 'http://blah.com', // 'http://localhost:9070/test/retry', // 'http://www.google.com', // 'http://localhost:8080/mIT/v1/admin/healthCheck1', // 'http://blah.com'
|
|
@@ -9,7 +11,7 @@ const options = {
|
|
|
9
11
|
'x-correlation-id': '---test-request-retry---',
|
|
10
12
|
},
|
|
11
13
|
json: true,
|
|
12
|
-
timeout:
|
|
14
|
+
timeout: TIMEOUT,
|
|
13
15
|
/*
|
|
14
16
|
* retry: {
|
|
15
17
|
* all default: maxRetry: 2, retryDelay: 1000ms, maxTimeout: 50s, logLevel: 3 silly, type response, retryDelayStrategy: setDelay, retryStrategy: defaultRetry
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mimik/request-retry",
|
|
3
|
-
"version": "4.0.
|
|
3
|
+
"version": "4.0.4",
|
|
4
4
|
"description": "Request retry wrapping axios",
|
|
5
5
|
"main": "./index.js",
|
|
6
6
|
"type": "module",
|
|
@@ -30,26 +30,26 @@
|
|
|
30
30
|
},
|
|
31
31
|
"dependencies": {
|
|
32
32
|
"@mimik/request-helper": "^2.0.2",
|
|
33
|
-
"@mimik/response-helper": "^4.0.
|
|
34
|
-
"@mimik/sumologic-winston-logger": "^2.
|
|
35
|
-
"axios": "1.
|
|
33
|
+
"@mimik/response-helper": "^4.0.6",
|
|
34
|
+
"@mimik/sumologic-winston-logger": "^2.1.6",
|
|
35
|
+
"axios": "1.12.1",
|
|
36
36
|
"bluebird": "3.7.2",
|
|
37
|
-
"
|
|
37
|
+
"rfdc": "1.4.1"
|
|
38
38
|
},
|
|
39
39
|
"devDependencies": {
|
|
40
|
-
"@eslint/js": "9.
|
|
40
|
+
"@eslint/js": "9.35.0",
|
|
41
41
|
"@mimik/eslint-plugin-document-env": "^2.0.8",
|
|
42
|
-
"@stylistic/eslint-plugin": "5.
|
|
42
|
+
"@stylistic/eslint-plugin": "5.3.1",
|
|
43
43
|
"acorn": "8.15.0",
|
|
44
44
|
"body-parser": "2.2.0",
|
|
45
45
|
"c8": "10.1.3",
|
|
46
|
-
"chai": "
|
|
47
|
-
"eslint": "9.
|
|
46
|
+
"chai": "6.0.1",
|
|
47
|
+
"eslint": "9.35.0",
|
|
48
48
|
"eslint-plugin-import": "2.32.0",
|
|
49
49
|
"express": "5.1.0",
|
|
50
50
|
"husky": "9.1.7",
|
|
51
51
|
"jsdoc-to-markdown": "9.1.2",
|
|
52
|
-
"mocha": "11.7.
|
|
52
|
+
"mocha": "11.7.2",
|
|
53
53
|
"mochawesome": "7.1.3",
|
|
54
54
|
"sinon": "21.0.0"
|
|
55
55
|
}
|
package/test/retryMock.js
CHANGED
|
@@ -1,26 +1,27 @@
|
|
|
1
1
|
/* eslint-disable no-console */
|
|
2
|
+
import { CREATED, OK, SYSTEM_ERROR } from '../lib/common.js';
|
|
2
3
|
import bodyParser from 'body-parser';
|
|
3
4
|
import express from 'express';
|
|
4
|
-
import process from 'process';
|
|
5
|
-
import { setTimeout } from 'timers';
|
|
5
|
+
import process from 'node:process';
|
|
6
|
+
import { setTimeout } from 'node:timers';
|
|
6
7
|
|
|
7
|
-
const NONE = 0;
|
|
8
|
-
const INCR = 1;
|
|
9
8
|
const TIMEOUT = 3000;
|
|
10
|
-
const
|
|
9
|
+
const EXIT_OK = 0;
|
|
10
|
+
const PORT = 9070;
|
|
11
|
+
const GET_NB_RETRY = 400;
|
|
11
12
|
|
|
12
13
|
const app = express();
|
|
13
14
|
const config = {
|
|
14
|
-
port:
|
|
15
|
+
port: PORT,
|
|
15
16
|
path: '/retry',
|
|
16
17
|
base: '/test',
|
|
17
18
|
get: {
|
|
18
|
-
nbRetry:
|
|
19
|
-
success:
|
|
20
|
-
error:
|
|
19
|
+
nbRetry: GET_NB_RETRY,
|
|
20
|
+
success: OK,
|
|
21
|
+
error: SYSTEM_ERROR,
|
|
21
22
|
},
|
|
22
23
|
post: {
|
|
23
|
-
success:
|
|
24
|
+
success: CREATED,
|
|
24
25
|
},
|
|
25
26
|
};
|
|
26
27
|
let nbRequest = 0;
|
|
@@ -29,7 +30,7 @@ let message;
|
|
|
29
30
|
|
|
30
31
|
app.use(bodyParser.json());
|
|
31
32
|
app.get(`${config.base}${config.path}`, (req, res) => {
|
|
32
|
-
if (nbRequest ===
|
|
33
|
+
if (nbRequest === 0) message = 'Recieved first request';
|
|
33
34
|
else {
|
|
34
35
|
const timeLap = Date.now() - time;
|
|
35
36
|
|
|
@@ -43,7 +44,7 @@ app.get(`${config.base}${config.path}`, (req, res) => {
|
|
|
43
44
|
res.send({ statusCode: config.get.success });
|
|
44
45
|
return;
|
|
45
46
|
}
|
|
46
|
-
nbRequest +=
|
|
47
|
+
nbRequest += 1;
|
|
47
48
|
res.statusCode = config.get.error;
|
|
48
49
|
|
|
49
50
|
res.send({ statusCode: config.get.error });
|
|
@@ -58,7 +59,7 @@ app.get('/stop', (req, res) => {
|
|
|
58
59
|
res.statusCode = config.get.success;
|
|
59
60
|
res.send({ statusCode: config.get.success });
|
|
60
61
|
setTimeout(() => {
|
|
61
|
-
process.exit(
|
|
62
|
+
process.exit(EXIT_OK);
|
|
62
63
|
}, TIMEOUT);
|
|
63
64
|
});
|
|
64
65
|
|
package/test/rpRetry.spec.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
|
+
/* eslint-disable max-lines-per-function */
|
|
1
2
|
import './testEnv.js';
|
|
2
3
|
import { afterEach, before, beforeEach, describe, it } from 'mocha';
|
|
3
4
|
import { assert, spy } from 'sinon';
|
|
4
|
-
import { expect
|
|
5
|
+
import { expect } from 'chai';
|
|
5
6
|
import { getCorrelationId } from '@mimik/request-helper';
|
|
6
7
|
import { listen } from './retryMock.js';
|
|
7
8
|
import logger from '@mimik/sumologic-winston-logger';
|
|
@@ -9,15 +10,19 @@ import { rpRetry } from '../index.js';
|
|
|
9
10
|
|
|
10
11
|
const TIMEOUT = 50000;
|
|
11
12
|
const RETRY_DELAY = 10000;
|
|
13
|
+
const OUT_OF_SCOPE_RETRY_DELAY = 100000;
|
|
14
|
+
const IN_SCOPE_RETRY_DELAY = 20000;
|
|
12
15
|
const RETRY_TIMEOUT = 10;
|
|
16
|
+
const OUT_OF_SCOPE_RETRY_TIMEOUT = 150;
|
|
17
|
+
const IN_SCOPE_RETRY_TIMEOUT = 50;
|
|
13
18
|
const RETRY_RETRIES = 2;
|
|
19
|
+
const OUT_OF_SCOPE_RETRIES = 20;
|
|
20
|
+
const IN_SCOPE_RETRIES = 10;
|
|
14
21
|
const DELAY_STRATEGY_RESPONSE_1 = -20;
|
|
15
22
|
const DELAY_STRATEGY_RESPONSE_2 = 50;
|
|
16
23
|
const DELAY_STRATEGY_RESPONSE_3 = 100;
|
|
17
24
|
const CALL_ARG_MESSAGE = 0;
|
|
18
25
|
const FIRST_CALL = 0;
|
|
19
|
-
|
|
20
|
-
should();
|
|
21
26
|
/*
|
|
22
27
|
* const DEFAULT_NO_MESSAGE = 'no message';
|
|
23
28
|
* const NO_ERROR = 'not an error object';
|
|
@@ -69,7 +74,7 @@ describe('request-retry Unit Tests', () => {
|
|
|
69
74
|
});
|
|
70
75
|
});
|
|
71
76
|
it('should generate warning: out of scope retries: 20 becoming max', () => {
|
|
72
|
-
options.retry.retries =
|
|
77
|
+
options.retry.retries = OUT_OF_SCOPE_RETRIES;
|
|
73
78
|
return rpRetry(options).then(() => {
|
|
74
79
|
assert.calledOnce(loggerSpyWarn);
|
|
75
80
|
const callArgs = loggerSpyWarn.getCall(FIRST_CALL).args;
|
|
@@ -78,7 +83,7 @@ describe('request-retry Unit Tests', () => {
|
|
|
78
83
|
});
|
|
79
84
|
});
|
|
80
85
|
it('should not generate warning: in scope retries', () => {
|
|
81
|
-
options.retry.retries =
|
|
86
|
+
options.retry.retries = IN_SCOPE_RETRIES;
|
|
82
87
|
return rpRetry(options).then(() => {
|
|
83
88
|
assert.notCalled(loggerSpyWarn);
|
|
84
89
|
});
|
|
@@ -102,7 +107,7 @@ describe('request-retry Unit Tests', () => {
|
|
|
102
107
|
});
|
|
103
108
|
});
|
|
104
109
|
it('should generate warning: out of scope delay: 100000 becoming max', () => {
|
|
105
|
-
options.retry.delay =
|
|
110
|
+
options.retry.delay = OUT_OF_SCOPE_RETRY_DELAY;
|
|
106
111
|
return rpRetry(options).then(() => {
|
|
107
112
|
assert.calledOnce(loggerSpyWarn);
|
|
108
113
|
const callArgs = loggerSpyWarn.getCall(FIRST_CALL).args;
|
|
@@ -120,7 +125,7 @@ describe('request-retry Unit Tests', () => {
|
|
|
120
125
|
});
|
|
121
126
|
});
|
|
122
127
|
it('should not generate warning: in scope delay', () => {
|
|
123
|
-
options.retry.delay =
|
|
128
|
+
options.retry.delay = IN_SCOPE_RETRY_DELAY;
|
|
124
129
|
return rpRetry(options).then(() => {
|
|
125
130
|
assert.notCalled(loggerSpyWarn);
|
|
126
131
|
});
|
|
@@ -135,7 +140,7 @@ describe('request-retry Unit Tests', () => {
|
|
|
135
140
|
});
|
|
136
141
|
});
|
|
137
142
|
it('should generate warning: out of scope timeout: 150 becoming max', () => {
|
|
138
|
-
options.retry.timeout =
|
|
143
|
+
options.retry.timeout = OUT_OF_SCOPE_RETRY_TIMEOUT;
|
|
139
144
|
return rpRetry(options).then(() => {
|
|
140
145
|
assert.calledOnce(loggerSpyWarn);
|
|
141
146
|
const callArgs = loggerSpyWarn.getCall(FIRST_CALL).args;
|
|
@@ -153,7 +158,7 @@ describe('request-retry Unit Tests', () => {
|
|
|
153
158
|
});
|
|
154
159
|
});
|
|
155
160
|
it('should not generate warning: in scope timeout', () => {
|
|
156
|
-
options.retry.timeout =
|
|
161
|
+
options.retry.timeout = IN_SCOPE_RETRY_TIMEOUT;
|
|
157
162
|
return rpRetry(options).then(() => {
|
|
158
163
|
assert.notCalled(loggerSpyWarn);
|
|
159
164
|
});
|
|
@@ -269,7 +274,7 @@ describe('request-retry Unit Tests', () => {
|
|
|
269
274
|
options.retry.retryStrategy = () => {
|
|
270
275
|
throw new Error('this is a test');
|
|
271
276
|
};
|
|
272
|
-
options.retry.retries =
|
|
277
|
+
options.retry.retries = RETRY_RETRIES;
|
|
273
278
|
return rpRetry(options)
|
|
274
279
|
.catch(() => {
|
|
275
280
|
assert.called(loggerSpyWarn);
|
|
@@ -280,7 +285,7 @@ describe('request-retry Unit Tests', () => {
|
|
|
280
285
|
});
|
|
281
286
|
it('should generate warning: bad retry strategy (not returning a boolean), ignoring and using default retries', () => {
|
|
282
287
|
options.retry.retryStrategy = () => 'notABoolean';
|
|
283
|
-
options.retry.retries =
|
|
288
|
+
options.retry.retries = RETRY_RETRIES;
|
|
284
289
|
return rpRetry(options)
|
|
285
290
|
.catch(() => {
|
|
286
291
|
assert.called(loggerSpyWarn);
|
|
@@ -291,7 +296,7 @@ describe('request-retry Unit Tests', () => {
|
|
|
291
296
|
});
|
|
292
297
|
it('should not generate warning: retry strategy returning a boolean', () => {
|
|
293
298
|
options.retry.retryStrategy = () => false;
|
|
294
|
-
options.retry.retries =
|
|
299
|
+
options.retry.retries = RETRY_RETRIES;
|
|
295
300
|
return rpRetry(options)
|
|
296
301
|
.catch(() => {
|
|
297
302
|
assert.called(loggerSpyWarn);
|
|
@@ -301,7 +306,7 @@ describe('request-retry Unit Tests', () => {
|
|
|
301
306
|
options.retry.delayStrategy = () => {
|
|
302
307
|
throw new Error('this is a test');
|
|
303
308
|
};
|
|
304
|
-
options.retry.retries =
|
|
309
|
+
options.retry.retries = RETRY_RETRIES;
|
|
305
310
|
return rpRetry(options)
|
|
306
311
|
.catch(() => {
|
|
307
312
|
assert.called(loggerSpyWarn);
|
|
@@ -312,7 +317,7 @@ describe('request-retry Unit Tests', () => {
|
|
|
312
317
|
});
|
|
313
318
|
it('should generate warning: bad delay strategy (not returning a number), ignoring and using default delay', () => {
|
|
314
319
|
options.retry.delayStrategy = () => 'notANumber';
|
|
315
|
-
options.retry.retries =
|
|
320
|
+
options.retry.retries = RETRY_RETRIES;
|
|
316
321
|
return rpRetry(options)
|
|
317
322
|
.catch(() => {
|
|
318
323
|
assert.called(loggerSpyWarn);
|
|
@@ -323,7 +328,7 @@ describe('request-retry Unit Tests', () => {
|
|
|
323
328
|
});
|
|
324
329
|
it('should generate warning: bad delay strategy (returning an out of scope number), ignoring and using default delay', () => {
|
|
325
330
|
options.retry.delayStrategy = () => DELAY_STRATEGY_RESPONSE_1;
|
|
326
|
-
options.retry.retries =
|
|
331
|
+
options.retry.retries = RETRY_RETRIES;
|
|
327
332
|
return rpRetry(options)
|
|
328
333
|
.catch(() => {
|
|
329
334
|
assert.called(loggerSpyWarn);
|
|
@@ -334,7 +339,7 @@ describe('request-retry Unit Tests', () => {
|
|
|
334
339
|
});
|
|
335
340
|
it('should not generate warning: delay strategy returning an in scope number', () => {
|
|
336
341
|
options.retry.delayStrategy = () => DELAY_STRATEGY_RESPONSE_2;
|
|
337
|
-
options.retry.retries =
|
|
342
|
+
options.retry.retries = RETRY_RETRIES;
|
|
338
343
|
return rpRetry(options)
|
|
339
344
|
.catch(() => {
|
|
340
345
|
assert.called(loggerSpyWarn);
|
package/test/testEnv.js
CHANGED