@mimik/request-retry 3.0.1 → 4.0.0

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.
@@ -0,0 +1,63 @@
1
+ import importPlugin from 'eslint-plugin-import';
2
+ import js from '@eslint/js';
3
+ import processDoc from '@mimik/eslint-plugin-document-env';
4
+ import stylistic from '@stylistic/eslint-plugin';
5
+
6
+ const MAX_LENGTH_LINE = 180;
7
+ const MAX_FUNCTION_PARAMETERS = 6;
8
+ const MAX_LINES_IN_FILES = 600;
9
+ const MAX_LINES_IN_FUNCTION = 150;
10
+ const MAX_STATEMENTS_IN_FUNCTION = 45;
11
+ const MIN_KEYS_IN_OBJECT = 10;
12
+ const MAX_COMPLEXITY = 30;
13
+
14
+ export default [
15
+ {
16
+ ignores: ['mochawesome-report/**', 'node_modules/**', 'dist/**'],
17
+ },
18
+ importPlugin.flatConfigs.recommended,
19
+ stylistic.configs['recommended-flat'],
20
+ js.configs.all,
21
+ {
22
+ plugins: {
23
+ processDoc,
24
+ },
25
+ languageOptions: {
26
+ ecmaVersion: 2022,
27
+ globals: {
28
+ console: 'readonly',
29
+ describe: 'readonly',
30
+ it: 'readonly',
31
+ require: 'readonly',
32
+ },
33
+ sourceType: 'module',
34
+ },
35
+ rules: {
36
+ '@stylistic/brace-style': ['warn', 'stroustrup', { allowSingleLine: true }],
37
+ '@stylistic/line-comment-position': ['off'],
38
+ '@stylistic/semi': ['error', 'always'],
39
+ 'capitalized-comments': ['off'],
40
+ 'complexity': ['error', MAX_COMPLEXITY],
41
+ 'curly': ['off'],
42
+ 'id-length': ['error', { exceptions: ['x', 'y', 'z', 'i', 'j', 'k'] }],
43
+ 'import/no-extraneous-dependencies': ['error', { devDependencies: true }],
44
+ 'import/no-unresolved': ['error', { amd: true, caseSensitiveStrict: true, commonjs: true }],
45
+ 'init-declarations': ['off'],
46
+ 'linebreak-style': ['off'],
47
+ 'max-len': ['warn', MAX_LENGTH_LINE, { ignoreComments: true }],
48
+ 'max-lines': ['warn', { max: MAX_LINES_IN_FILES, skipComments: true }],
49
+ 'max-lines-per-function': ['warn', { max: MAX_LINES_IN_FUNCTION, skipComments: true }],
50
+ 'max-params': ['error', MAX_FUNCTION_PARAMETERS],
51
+ 'max-statements': ['warn', MAX_STATEMENTS_IN_FUNCTION],
52
+ 'no-confusing-arrow': ['off'], // arrow isnt confusing
53
+ 'no-inline-comments': ['off'],
54
+ 'no-process-env': ['error'],
55
+ 'no-ternary': ['off'],
56
+ 'no-undefined': ['off'],
57
+ 'one-var': ['error', 'never'],
58
+ 'processDoc/validate-document-env': ['error'],
59
+ 'quotes': ['warn', 'single'],
60
+ 'sort-keys': ['error', 'asc', { caseSensitive: true, minKeys: MIN_KEYS_IN_OBJECT, natural: false }],
61
+ },
62
+ },
63
+ ];
package/index.js CHANGED
@@ -1,15 +1,22 @@
1
- const Promise = require('bluebird');
2
-
3
- const logger = require('@mimik/sumologic-winston-logger');
4
- const { getRichError } = require('@mimik/response-helper');
5
- const { getCorrelationId, setUserAgent } = require('@mimik/request-helper');
6
- const {
7
- validateOptions,
1
+ import {
8
2
  calculateDelay,
9
3
  isRetry,
10
4
  setResponse,
11
- } = require('./lib/validate');
12
- const { rp } = require('./lib/rp-axios-wrapper');
5
+ validateOptions,
6
+ } from './lib/validate.js';
7
+ import {
8
+ clearTimeout,
9
+ setTimeout,
10
+ } from 'timers';
11
+ import {
12
+ getCorrelationId,
13
+ setUserAgent,
14
+ } from '@mimik/request-helper';
15
+ import Promise from 'bluebird';
16
+ import { getRichError } from '@mimik/response-helper';
17
+ import logger from '@mimik/sumologic-winston-logger';
18
+ import process from 'process';
19
+ import { rp } from './lib/rp-axios-wrapper.js';
13
20
 
14
21
  const DEFAULT_RESPONSE_NAME = 'response';
15
22
  const DEFAULT_LOGLEVEL_DETAILS = 'full';
@@ -17,6 +24,16 @@ const DEFAULT_LOGLEVEL_RESPONSE = 'info';
17
24
  const DEFAULT_LOGLEVEL_ERROR = 'warn';
18
25
  const DEFAULT_LOGLEVEL_REQUEST = 'info';
19
26
 
27
+ const MILLI_SECONDS = 0;
28
+ const MILLI_NANO_SECONDS = 1;
29
+ const INCR = 1;
30
+ const MILLI = 1000;
31
+ const NANO = 1e6;
32
+ const EMPTY = 0;
33
+ const NONE = 0;
34
+ const OK_RESPONSE = 200;
35
+ const SYSTEM_ERROR = 500;
36
+
20
37
  Promise.config({ cancellation: true });
21
38
 
22
39
  /**
@@ -82,12 +99,12 @@ const rpRetry = (origOptions) => {
82
99
  const criteria = validateOptions(options, correlationId);
83
100
  const { logLevel } = criteria;
84
101
  const logLevelLength = Object.keys(logLevel).length;
85
- let nbRetries = 0;
102
+ let nbRetries = NONE;
86
103
  let mainTimeout;
87
104
  const measure = (statusCode) => {
88
105
  if (metrics && metrics.HTTPRequestDuration) {
89
106
  const elapsedHrTime = process.hrtime(startHrTime);
90
- const elapsedTimeInMs = elapsedHrTime[0] * 1000 + elapsedHrTime[1] / 1e6;
107
+ const elapsedTimeInMs = elapsedHrTime[MILLI_SECONDS] * MILLI + elapsedHrTime[MILLI_NANO_SECONDS] / NANO;
91
108
 
92
109
  metrics.HTTPRequestDuration
93
110
  .labels('rpRetry', options.method, metrics.url || enteredUrl, enteredUrl.includes('?'), statusCode)
@@ -100,7 +117,7 @@ const rpRetry = (origOptions) => {
100
117
  const optionsInfo = { ...options };
101
118
  delete optionsInfo.metrics;
102
119
 
103
- const retryProcess = (nbRetry) => rp(options)
120
+ const retryProcess = nbRetry => rp(options)
104
121
  .then((response) => {
105
122
  const info = { options: optionsInfo, nbRetries, errors };
106
123
 
@@ -108,7 +125,7 @@ const rpRetry = (origOptions) => {
108
125
  info[logLevel.responseName] = setResponse(response, logLevel.responseDetails);
109
126
  logger[logLevel.response]('request response', info, correlationId);
110
127
  }
111
- else if (logLevelLength === 0) {
128
+ else if (logLevelLength === EMPTY) {
112
129
  info[DEFAULT_RESPONSE_NAME] = setResponse(response, DEFAULT_LOGLEVEL_DETAILS);
113
130
  logger[DEFAULT_LOGLEVEL_RESPONSE]('request response', info, correlationId);
114
131
  }
@@ -116,16 +133,16 @@ const rpRetry = (origOptions) => {
116
133
  })
117
134
  .catch((err) => {
118
135
  if ((nbRetry < criteria.retries) && isRetry(options, nbRetry, criteria, err, correlationId)) {
119
- nbRetries = nbRetry + 1;
136
+ nbRetries = nbRetry + INCR;
120
137
  errors.push(err);
121
138
  const delayPromise = Promise.delay(calculateDelay(options, nbRetry, criteria, err, correlationId));
122
139
 
123
140
  delayPromises.unshift(delayPromise);
124
- return delayPromise.then(() => retryProcess(nbRetry + 1));
141
+ return delayPromise.then(() => retryProcess(nbRetry + INCR));
125
142
  }
126
143
  const error = err;
127
144
 
128
- if (nbRetries !== 0) {
145
+ if (nbRetries !== NONE) {
129
146
  if (!error.info) error.info = {};
130
147
  error.info.retry = {
131
148
  nbRetries,
@@ -137,18 +154,18 @@ const rpRetry = (origOptions) => {
137
154
  'request error response',
138
155
  { options: optionsInfo },
139
156
  error,
140
- logLevel.error || ((logLevelLength === 0) ? DEFAULT_LOGLEVEL_ERROR : undefined),
157
+ logLevel.error || ((logLevelLength === EMPTY) ? DEFAULT_LOGLEVEL_ERROR : undefined),
141
158
  correlationId,
142
159
  );
143
160
  });
144
161
 
145
- const retryPromise = retryProcess(0);
162
+ const retryPromise = retryProcess(NONE);
146
163
  const mainTimeoutPromise = new Promise((resolve, reject) => {
147
164
  mainTimeout = setTimeout(() => {
148
- delayPromises.forEach((delayPromise) => delayPromise.cancel(`retry timeout delay, ${criteria.timeout}, ${nbRetries}`));
165
+ delayPromises.forEach(delayPromise => delayPromise.cancel(`retry timeout delay, ${criteria.timeout}, ${nbRetries}`));
149
166
  let error = new Error('retry timeout');
150
167
 
151
- if (nbRetries !== 0) {
168
+ if (nbRetries !== NONE) {
152
169
  error.info = { retry: { nbRetries, errors } };
153
170
  }
154
171
  error.name = 'TimeoutError';
@@ -157,30 +174,30 @@ const rpRetry = (origOptions) => {
157
174
  'request error response',
158
175
  { options: optionsInfo },
159
176
  error,
160
- logLevel.error || ((logLevelLength === 0) ? DEFAULT_LOGLEVEL_ERROR : undefined),
177
+ logLevel.error || ((logLevelLength === EMPTY) ? DEFAULT_LOGLEVEL_ERROR : undefined),
161
178
  correlationId,
162
179
  );
163
180
  reject(error);
164
- }, criteria.timeout * 1000);
181
+ }, criteria.timeout * MILLI);
165
182
  });
166
183
 
167
184
  if (logLevel.request) logger[logLevel.request]('making a request', { options: optionsInfo, criteria }, correlationId);
168
- else if (logLevelLength === 0) logger[DEFAULT_LOGLEVEL_REQUEST]('making a request', { options: optionsInfo, criteria }, correlationId);
185
+ else if (logLevelLength === EMPTY) logger[DEFAULT_LOGLEVEL_REQUEST]('making a request', { options: optionsInfo, criteria }, correlationId);
169
186
  return Promise.race([retryPromise, mainTimeoutPromise])
170
187
  .then((result) => {
171
188
  mainTimeoutPromise.cancel('main timeout');
172
189
  clearTimeout(mainTimeout);
173
- measure(200);
190
+ measure(OK_RESPONSE);
174
191
  return result;
175
192
  })
176
193
  .catch((err) => {
177
194
  mainTimeoutPromise.cancel(`main timeout error: ${err.message}`);
178
195
  clearTimeout(mainTimeout);
179
- measure(err.statusCode || 500);
196
+ measure(err.statusCode || SYSTEM_ERROR);
180
197
  throw err;
181
198
  });
182
199
  };
183
200
 
184
- module.exports = {
201
+ export {
185
202
  rpRetry,
186
203
  };
@@ -1,10 +1,9 @@
1
- const axios = require('axios');
2
- const _ = require('lodash');
3
-
4
- const { getRichError } = require('@mimik/response-helper');
1
+ import axios from 'axios';
2
+ import clone from 'lodash.clone';
3
+ import { getRichError } from '@mimik/response-helper';
5
4
 
6
5
  const rp = (origOptions) => {
7
- const options = _.clone(origOptions);
6
+ const options = clone(origOptions);
8
7
 
9
8
  if (options.uri) options.url = options.uri;
10
9
  delete options.uri;
@@ -43,6 +42,6 @@ const rp = (origOptions) => {
43
42
  });
44
43
  };
45
44
 
46
- module.exports = {
45
+ export {
47
46
  rp,
48
47
  };
package/lib/validate.js CHANGED
@@ -1,23 +1,29 @@
1
- const logger = require('@mimik/sumologic-winston-logger');
1
+ import logger from '@mimik/sumologic-winston-logger';
2
2
 
3
3
  const DETAILS = ['full', 'type', 'count'];
4
- const TYPE = DETAILS[1];
4
+ const [, TYPE/* type */] = DETAILS;
5
5
  const RESPONSE = 'response';
6
- const DEFAULT_LOGLEVEL = logger.LEVELS[5]; // silly
6
+ const [, , , , , DEFAULT_LOGLEVEL/* 'silly' */] = logger.LEVELS;
7
7
  const DEFAULT_RETRIES = 2;
8
8
  const MIN_RETRIES = 0;
9
9
  const MAX_RETRIES = 15;
10
10
  const DEFAULT_DELAY = 1000; // in ms
11
11
  const MIN_DELAY = 20; // in ms
12
12
  const MAX_DELAY = 30000; // in ms
13
+ const NO_DELAY = 0;
13
14
  const DEFAULT_TIMEOUT = 50; // in seconds
14
15
  const MIN_TIMEOUT = 10; // in seconds
15
16
  const MAX_TIMEOUT = 120; // in seconds
17
+ const TOO_MANY_REQUESTS_ERROR = 429;
18
+ const EMPTY = 0;
19
+ const SYSTEM_RANGE = 5;
20
+ const SYSTEM_RANGE_EXTRACT = 100;
21
+ const ARG_ERROR = 1;
16
22
 
17
23
  const defaultRetry = (...args) => {
18
- const { statusCode } = args[1]; // err
24
+ const { statusCode } = args[ARG_ERROR]; // err
19
25
 
20
- return (statusCode && (Math.floor(statusCode / 100) === 5 || statusCode === 429)) || (!statusCode && !args[1].message.includes('Invalid URI'));
26
+ return (statusCode && (Math.floor(statusCode / SYSTEM_RANGE_EXTRACT) === SYSTEM_RANGE || statusCode === TOO_MANY_REQUESTS_ERROR)) || (!statusCode && !args[ARG_ERROR].message.includes('Invalid URI'));
21
27
  };
22
28
  const unknownRetry = () => true;
23
29
  const defaultDelay = () => DEFAULT_DELAY;
@@ -74,7 +80,7 @@ const validateOptions = (options, correlationId) => {
74
80
  };
75
81
  const validateResponseName = (val, name, defaultValue) => {
76
82
  if (!val && val !== '') return defaultValue;
77
- if (typeof val !== 'string' || val.length === 0 || val.trim().length === 0) {
83
+ if (typeof val !== 'string' || val.length === EMPTY || val.trim().length === EMPTY) {
78
84
  logger.warn(`invalid logLevel.${name}, reset to default`, { name, value: val, defaultValue }, correlationId);
79
85
  return defaultValue;
80
86
  }
@@ -86,29 +92,29 @@ const validateOptions = (options, correlationId) => {
86
92
  delay = validateValue(delay, 'delay', DEFAULT_DELAY, MIN_DELAY, MAX_DELAY);
87
93
  retries = validateValue(retries, 'retries', DEFAULT_RETRIES, MIN_RETRIES, MAX_RETRIES);
88
94
  if (typeof delayStrategy !== 'function') {
89
- if (!delayStrategy) delayStrategy = setDelay;
90
- else {
95
+ if (delayStrategy) {
91
96
  logger.warn('invalid delayStrategy, using delay', { strategyType: typeof delayStrategy, delay, default: DEFAULT_DELAY }, correlationId);
92
97
  delayStrategy = setDelay;
93
98
  }
99
+ else delayStrategy = setDelay;
94
100
  }
95
101
  if (typeof retryStrategy !== 'function') {
96
- if (!retryStrategy) retryStrategy = defaultRetry;
97
- else {
102
+ if (retryStrategy) {
98
103
  logger.warn('invalid retryStrategy, ignoring', { strategyType: typeof retryStrategy, using: unknownRetry }, correlationId);
99
104
  retryStrategy = unknownRetry;
100
105
  }
106
+ else retryStrategy = defaultRetry;
101
107
  }
102
- if (!logLevel) {
103
- logLevel = {};
104
- }
105
- else {
108
+ if (logLevel) {
106
109
  logLevel.response = validateLogLevel(logLevel, 'response');
107
110
  logLevel.error = validateLogLevel(logLevel, 'error');
108
111
  logLevel.request = validateLogLevel(logLevel, 'request');
109
112
  logLevel.responseDetails = validateResponseDetails(logLevel.responseDetails, 'responseDetails', TYPE);
110
113
  logLevel.responseName = validateResponseName(logLevel.responseName, 'responseName', RESPONSE);
111
114
  }
115
+ else {
116
+ logLevel = {};
117
+ }
112
118
  return {
113
119
  delay,
114
120
  delayStrategy,
@@ -122,7 +128,9 @@ const validateOptions = (options, correlationId) => {
122
128
  const calculateDelay = (options, nbRetry, criteria, err, correlationId) => {
123
129
  let calcDelay;
124
130
 
125
- try { calcDelay = criteria.delayStrategy(nbRetry, err, options, correlationId); }
131
+ try {
132
+ calcDelay = criteria.delayStrategy(nbRetry, err, options, correlationId);
133
+ }
126
134
  catch (error) {
127
135
  logger.warn('bad delay strategy', { error }, correlationId);
128
136
  calcDelay = criteria.delay;
@@ -131,7 +139,7 @@ const calculateDelay = (options, nbRetry, criteria, err, correlationId) => {
131
139
  logger.warn('bad delay strategy', { error: `return of delayStrategy is a ${typeof calcDelay}` }, correlationId);
132
140
  calcDelay = criteria.delay;
133
141
  }
134
- else if (calcDelay > MAX_DELAY || calcDelay <= 0) {
142
+ else if (calcDelay > MAX_DELAY || calcDelay <= NO_DELAY) {
135
143
  logger.warn('calculated delay out of scope: using delay or default', { calcDelay, delay: criteria.delay, default: DEFAULT_DELAY }, correlationId);
136
144
  calcDelay = criteria.delay;
137
145
  }
@@ -141,7 +149,9 @@ const calculateDelay = (options, nbRetry, criteria, err, correlationId) => {
141
149
  const isRetry = (options, nbRetry, criteria, err, correlationId) => {
142
150
  let iRetry;
143
151
 
144
- try { iRetry = criteria.retryStrategy(nbRetry, err, options, correlationId); }
152
+ try {
153
+ iRetry = criteria.retryStrategy(nbRetry, err, options, correlationId);
154
+ }
145
155
  catch (error) {
146
156
  logger.warn('bad retry strategy', { error }, correlationId);
147
157
  iRetry = true;
@@ -165,9 +175,9 @@ const setResponse = (response, details) => {
165
175
  return response;
166
176
  };
167
177
 
168
- module.exports = {
169
- validateOptions,
178
+ export {
170
179
  calculateDelay,
171
180
  isRetry,
172
181
  setResponse,
182
+ validateOptions,
173
183
  };
@@ -1,6 +1,8 @@
1
1
  /* eslint-disable no-console */
2
- const express = require('express');
3
- const bodyParser = require('body-parser');
2
+ import bodyParser from 'body-parser';
3
+ import express from 'express';
4
+
5
+ const PORT = 9000;
4
6
 
5
7
  const app = express();
6
8
 
@@ -11,6 +13,6 @@ app.get('/success', (req, res) => {
11
13
  res.send({ statusCode: 200 });
12
14
  });
13
15
 
14
- app.listen(9000, () => {
15
- console.log('----->', `retry mock at ${9000}`);
16
+ app.listen(PORT, () => {
17
+ console.log('----->', `retry mock at ${PORT}`);
16
18
  });
@@ -1,7 +1,9 @@
1
1
  /* eslint-disable no-console */
2
- require('./testEnv');
2
+ import './testEnv';
3
3
 
4
- const { rpRetry } = require('../index');
4
+ import { rpRetry } from '../index.js';
5
+
6
+ const DELAY = 1000;
5
7
 
6
8
  const correlationId = `--request-retry-test--/${new Date().toISOString()}`;
7
9
 
@@ -15,9 +17,9 @@ const options = {
15
17
  retry: {},
16
18
  };
17
19
 
18
- options.retry.delayStrategy = () => 1000;
20
+ options.retry.delayStrategy = () => DELAY;
19
21
  options.retry.timeout = 10;
20
22
  options.retry.retries = 2;
21
23
 
22
24
  rpRetry(options)
23
- .catch((err) => console.log(err));
25
+ .catch(err => console.log(err));
@@ -1,6 +1,10 @@
1
1
  /* eslint-disable no-console */
2
- const express = require('express');
3
- const bodyParser = require('body-parser');
2
+ import bodyParser from 'body-parser';
3
+ import express from 'express';
4
+ import { setTimeout } from 'timers';
5
+
6
+ const NONE = 0;
7
+ const INCR = 1;
4
8
 
5
9
  const app = express();
6
10
  const config = {
@@ -23,7 +27,7 @@ let message;
23
27
 
24
28
  app.use(bodyParser.json());
25
29
  app.get(`${config.base}${config.path}`, (req, res) => {
26
- if (nbRequest === 0) message = 'Recieved first request';
30
+ if (nbRequest === NONE) message = 'Recieved first request';
27
31
  else {
28
32
  const timeLap = Date.now() - time;
29
33
 
@@ -37,7 +41,7 @@ app.get(`${config.base}${config.path}`, (req, res) => {
37
41
  res.send({ statusCode: config.get.success });
38
42
  return;
39
43
  }
40
- nbRequest += 1;
44
+ nbRequest += INCR;
41
45
  setTimeout(() => {
42
46
  res.statusCode = config.get.error;
43
47
  res.send({ statusCode: config.get.error });
@@ -1,4 +1,5 @@
1
1
  /* eslint no-process-env: "off" */
2
+ import process from 'process';
2
3
 
3
4
  /**
4
5
  * The following environment variables are set for the test:
@@ -12,9 +13,10 @@
12
13
  * | CONSOLE_LEVEL | log level to diplay | debug
13
14
  * | LOG_MODE | log mode | none
14
15
  */
15
-
16
- // process.env.SUMO_LOGIC_ENDPOINT = 'http://localhost:9080/logs/';
17
- // process.env.SUMO_LOGIC_COLLECTOR_CODE = '1234';
16
+ /*
17
+ *process.env.SUMO_LOGIC_ENDPOINT = 'http://localhost:9080/logs/';
18
+ *process.env.SUMO_LOGIC_COLLECTOR_CODE = '1234';
19
+ */
18
20
  process.env.SUMO_LOGIC_ENDPOINT = null;
19
21
  process.env.SUMO_LOGIC_COLLECTOR_CODE = null;
20
22
  process.env.NO_STACK = 'yes';
@@ -1,9 +1,18 @@
1
1
  /* eslint-disable no-console */
2
+ import {
3
+ clearTimeout,
4
+ setTimeout,
5
+ } from 'timers';
6
+
7
+ const INCR = 1;
8
+ const MAX_INCR = 100000000;
9
+ const NO_RESULT = 0;
10
+
2
11
  const doSomething = () => {
3
12
  let add = 0;
4
13
 
5
- for (let i = 0; i < 100000000; i += 1) {
6
- add += 1;
14
+ for (let i = 0; i < MAX_INCR; i += INCR) {
15
+ add += INCR;
7
16
  console.log(add);
8
17
  }
9
18
  return add;
@@ -16,10 +25,12 @@ const race = () => {
16
25
  throw new Error('timeout');
17
26
  }, timeout);
18
27
 
19
- try { result = doSomething(); }
28
+ try {
29
+ result = doSomething();
30
+ }
20
31
  catch (err) {
21
32
  console.log(err);
22
- result = 0;
33
+ result = NO_RESULT;
23
34
  }
24
35
  clearTimeout(mainTimeout);
25
36
  return result;
@@ -1,6 +1,7 @@
1
1
  /* eslint-disable no-console */
2
- require('../test/testEnv');
3
- const { rpRetry } = require('../index');
2
+ import '../test/testEnv.js';
3
+
4
+ import { rpRetry } from '../index.js';
4
5
 
5
6
  const options = {
6
7
  method: 'GET',
@@ -10,51 +11,53 @@ const options = {
10
11
  },
11
12
  json: true,
12
13
  timeout: 20000,
13
- // retry: {
14
- // all default: maxRetry: 2, retryDelay: 1000ms, maxTimeout: 50s, logLevel: 3 silly, type response, retryDelayStrategy: setDelay, retryStrategy: defaultRetry
15
- // retries: -1, // => 0
16
- // retries: 20, // => 15
17
- // retries: 'joe', // => 2
18
- // retries: 0, // OK
19
- // delay: 0, // => 20ms
20
- // delay: 100000, // => 30000ms
21
- // delay: 'joe', // => 1000ms
22
- // delay: 1, // => 20ms
23
- // delayStrategy: 'joe', // => setDelay returning retryDelay
24
- // delayStrategy: function badDelay() { return 'joe' }, // => no change then bad delay strategy => retryDelay
25
- // delayStrategy: function userDelay(...args) { return (Math.pow(2, args[0]) * 100) + Math.floor(Math.random() * 50) }, // OK
26
- // retryStrategy: 'joe', // => unknowRetry returning false
27
- // retryStrategy: function badRetry() { return 'joe' }, // => no change then bad retry strategy => false
28
- // retryStrategy: function userRetry(...args) { // OK
29
- // const { statusCode } = args[1]; // err
30
- //
31
- // return statusCode && (Math.floor(statusCode/100) !== 5 || statusCode !== 429); // retry if there is no statusCode or if there is 500 range statucCode or 429
32
- // },
33
- // retryStrategy: function invalidRetry(...args) { // defaultRetry
34
- // const { statusCode } = args[34]; // null value
35
- //
36
- // return true // no retry
37
- // },
38
- // timeout: 0, // => 10s
39
- // timeout: 150, // => 120s
40
- // timeout: 'joe', // => 50s
41
- // logLevel: {
42
- // response: 'test', // silly with warning
43
- // error: 1234, // => silly with warning
44
- // request: null, // => silly no warning
45
- // responseDetails: 'test', // => type with warning
46
- // responseName: '', // => response with warning
47
- // },
48
- // logLevel: {
49
- // response: 'info', // ok all the other value to default no warning
50
- // },
51
- // }
14
+ /*
15
+ * retry: {
16
+ * all default: maxRetry: 2, retryDelay: 1000ms, maxTimeout: 50s, logLevel: 3 silly, type response, retryDelayStrategy: setDelay, retryStrategy: defaultRetry
17
+ * retries: -1, // => 0
18
+ * retries: 20, // => 15
19
+ * retries: 'joe', // => 2
20
+ * retries: 0, // OK
21
+ * delay: 0, // => 20ms
22
+ * delay: 100000, // => 30000ms
23
+ * delay: 'joe', // => 1000ms
24
+ * delay: 1, // => 20ms
25
+ * delayStrategy: 'joe', // => setDelay returning retryDelay
26
+ * delayStrategy: function badDelay() { return 'joe' }, // => no change then bad delay strategy => retryDelay
27
+ * delayStrategy: function userDelay(...args) { return (Math.pow(2, args[0]) * 100) + Math.floor(Math.random() * 50) }, // OK
28
+ * retryStrategy: 'joe', // => unknowRetry returning false
29
+ * retryStrategy: function badRetry() { return 'joe' }, // => no change then bad retry strategy => false
30
+ * retryStrategy: function userRetry(...args) { // OK
31
+ * const { statusCode } = args[1]; // err
32
+ *
33
+ * return statusCode && (Math.floor(statusCode/100) !== 5 || statusCode !== 429); // retry if there is no statusCode or if there is 500 range statucCode or 429
34
+ * },
35
+ * retryStrategy: function invalidRetry(...args) { // defaultRetry
36
+ * const { statusCode } = args[34]; // null value
37
+ *
38
+ * return true // no retry
39
+ * },
40
+ * timeout: 0, // => 10s
41
+ * timeout: 150, // => 120s
42
+ * timeout: 'joe', // => 50s
43
+ * logLevel: {
44
+ * response: 'test', // silly with warning
45
+ * error: 1234, // => silly with warning
46
+ * request: null, // => silly no warning
47
+ * responseDetails: 'test', // => type with warning
48
+ * responseName: '', // => response with warning
49
+ * },
50
+ * logLevel: {
51
+ * response: 'info', // ok all the other value to default no warning
52
+ * },
53
+ * }
54
+ */
52
55
  };
53
56
 
54
57
  const sDate = Date.now();
55
58
 
56
59
  rpRetry(options)
57
- .then((response) => console.log('success', { response: typeof response }, Date.now() - sDate))
60
+ .then(response => console.log('success', { response: typeof response }, Date.now() - sDate))
58
61
  .catch((err) => {
59
62
  console.log('failure', { error: err, info: err.info }, Date.now() - sDate);
60
63
  });
package/package.json CHANGED
@@ -1,16 +1,16 @@
1
1
  {
2
2
  "name": "@mimik/request-retry",
3
- "version": "3.0.1",
3
+ "version": "4.0.0",
4
4
  "description": "Request retry wrapping axios",
5
- "main": "index.js",
5
+ "main": "./index.js",
6
+ "type": "module",
6
7
  "scripts": {
7
- "lint": "eslint --ignore-path .gitignore .",
8
+ "lint": "eslint . --no-error-on-unmatched-pattern",
8
9
  "docs": "jsdoc2md index.js > README.md",
9
10
  "test": "mocha --reporter mochawesome --bail --check-leaks test/",
10
- "test-ci": "nyc --reporter=lcov --reporter=text npm test",
11
+ "test-ci": "c8 --reporter=lcov --reporter=text npm test --exit",
11
12
  "prepublishOnly": "npm run docs && npm run lint && npm run test-ci",
12
- "commit-ready": "npm run docs && npm run lint && npm run test-ci",
13
- "prepare": "husky install"
13
+ "commit-ready": "npm run docs && npm run lint && npm run test-ci"
14
14
  },
15
15
  "husky": {
16
16
  "hooks": {
@@ -29,32 +29,28 @@
29
29
  "url": "https://bitbucket.org/mimiktech/request-retry"
30
30
  },
31
31
  "dependencies": {
32
- "@mimik/request-helper": "^1.7.10",
33
- "@mimik/response-helper": "^3.0.1",
34
- "@mimik/sumologic-winston-logger": "^1.6.20",
35
- "axios": "1.6.2",
32
+ "@mimik/request-helper": "^2.0.1",
33
+ "@mimik/response-helper": "^4.0.0",
34
+ "@mimik/sumologic-winston-logger": "^2.0.2",
35
+ "axios": "1.8.4",
36
36
  "bluebird": "3.7.2",
37
- "lodash": "4.17.21"
37
+ "lodash.clone": "4.5.0"
38
38
  },
39
39
  "devDependencies": {
40
- "@mimik/eslint-plugin-dependencies": "^2.4.6",
41
- "@mimik/eslint-plugin-document-env": "^1.0.6",
42
- "acorn": "8.11.2",
43
- "body-parser": "1.20.2",
44
- "chai": "4.3.10",
45
- "eslint": "8.55.0",
46
- "eslint-config-airbnb": "19.0.4",
47
- "eslint-plugin-import": "2.29.0",
48
- "eslint-plugin-jsx-a11y": "6.8.0",
49
- "eslint-plugin-react": "7.33.2",
50
- "eslint-plugin-react-hooks": "4.6.0",
51
- "express": "4.18.2",
52
- "husky": "8.0.3",
53
- "jsdoc-to-markdown": "8.0.0",
54
- "mocha": "10.2.0",
40
+ "@eslint/js": "9.23.0",
41
+ "@mimik/eslint-plugin-document-env": "^2.0.5",
42
+ "@stylistic/eslint-plugin": "4.2.0",
43
+ "acorn": "8.14.1",
44
+ "body-parser": "1.20.3",
45
+ "c8": "10.1.3",
46
+ "chai": "5.2.0",
47
+ "eslint": "9.23.0",
48
+ "eslint-plugin-import": "2.31.0",
49
+ "express": "4.21.2",
50
+ "husky": "9.1.7",
51
+ "jsdoc-to-markdown": "9.1.1",
52
+ "mocha": "11.1.0",
55
53
  "mochawesome": "7.1.3",
56
- "nyc": "15.1.0",
57
- "sinon": "17.0.1",
58
- "verror": "1.10.1"
54
+ "sinon": "20.0.0"
59
55
  }
60
56
  }
package/test/retryMock.js CHANGED
@@ -1,6 +1,13 @@
1
1
  /* eslint-disable no-console */
2
- const express = require('express');
3
- const bodyParser = require('body-parser');
2
+ import bodyParser from 'body-parser';
3
+ import express from 'express';
4
+ import process from 'process';
5
+ import { setTimeout } from 'timers';
6
+
7
+ const NONE = 0;
8
+ const INCR = 1;
9
+ const TIMEOUT = 3000;
10
+ const EXIT_NORMAL = 0;
4
11
 
5
12
  const app = express();
6
13
  const config = {
@@ -22,7 +29,7 @@ let message;
22
29
 
23
30
  app.use(bodyParser.json());
24
31
  app.get(`${config.base}${config.path}`, (req, res) => {
25
- if (nbRequest === 0) message = 'Recieved first request';
32
+ if (nbRequest === NONE) message = 'Recieved first request';
26
33
  else {
27
34
  const timeLap = Date.now() - time;
28
35
 
@@ -36,7 +43,7 @@ app.get(`${config.base}${config.path}`, (req, res) => {
36
43
  res.send({ statusCode: config.get.success });
37
44
  return;
38
45
  }
39
- nbRequest += 1;
46
+ nbRequest += INCR;
40
47
  res.statusCode = config.get.error;
41
48
 
42
49
  res.send({ statusCode: config.get.error });
@@ -51,8 +58,8 @@ app.get('/stop', (req, res) => {
51
58
  res.statusCode = config.get.success;
52
59
  res.send({ statusCode: config.get.success });
53
60
  setTimeout(() => {
54
- process.exit(0);
55
- }, 3000);
61
+ process.exit(EXIT_NORMAL);
62
+ }, TIMEOUT);
56
63
  });
57
64
 
58
65
  const listen = () => {
@@ -61,6 +68,6 @@ const listen = () => {
61
68
  });
62
69
  };
63
70
 
64
- module.exports = {
71
+ export {
65
72
  listen,
66
73
  };
@@ -1,28 +1,36 @@
1
- const chai = require('chai');
2
- const sinon = require('sinon');
3
- const VError = require('verror');
4
- const { beforeEach, afterEach } = require('mocha');
5
- require('./testEnv');
1
+ import './testEnv.js';
2
+ import { afterEach, before, beforeEach, describe, it } from 'mocha';
3
+ import { assert, spy } from 'sinon';
4
+ import { expect, should } from 'chai';
5
+ import { getCorrelationId } from '@mimik/request-helper';
6
+ import { listen } from './retryMock.js';
7
+ import logger from '@mimik/sumologic-winston-logger';
8
+ import { rpRetry } from '../index.js';
6
9
 
7
- const logger = require('@mimik/sumologic-winston-logger');
8
- const { getCorrelationId } = require('@mimik/request-helper');
10
+ const TIMEOUT = 50000;
11
+ const RETRY_DELAY = 10000;
12
+ const RETRY_TIMEOUT = 10;
13
+ const RETRY_RETRIES = 2;
14
+ const DELAY_STRATEGY_RESPONSE_1 = -20;
15
+ const DELAY_STRATEGY_RESPONSE_2 = 50;
16
+ const DELAY_STRATEGY_RESPONSE_3 = 100;
17
+ const CALL_ARG_MESSAGE = 0;
18
+ const FIRST_CALL = 0;
9
19
 
10
- const mockServer = require('./retryMock');
11
- const { rpRetry } = require('../index');
12
-
13
- const { expect } = chai;
14
- chai.should();
15
-
16
- // const DEFAULT_NO_MESSAGE = 'no message';
17
- // const NO_ERROR = 'not an error object';
20
+ should();
21
+ /*
22
+ * const DEFAULT_NO_MESSAGE = 'no message';
23
+ * const NO_ERROR = 'not an error object';
24
+ */
18
25
 
19
26
  describe('request-retry Unit Tests', () => {
20
27
  const correlationId = getCorrelationId('--request-retry-test--');
21
28
  // let loggerSpyError;
22
29
  let loggerSpyWarn;
23
30
  let loggerSpyInfo;
31
+
24
32
  before(() => {
25
- mockServer.listen();
33
+ listen();
26
34
  });
27
35
 
28
36
  describe('rpRetry(options) options validations prerun', () => {
@@ -36,7 +44,7 @@ describe('request-retry Unit Tests', () => {
36
44
  retry: {},
37
45
  };
38
46
  beforeEach(() => {
39
- loggerSpyWarn = sinon.spy(logger, 'warn');
47
+ loggerSpyWarn = spy(logger, 'warn');
40
48
  });
41
49
  afterEach(() => {
42
50
  options.retry = {};
@@ -45,134 +53,134 @@ describe('request-retry Unit Tests', () => {
45
53
  it('should not generate warning: null retry, using default', () => {
46
54
  options.retry = null;
47
55
  return rpRetry(options).then(() => {
48
- sinon.assert.notCalled(loggerSpyWarn);
56
+ assert.notCalled(loggerSpyWarn);
49
57
  });
50
58
  });
51
59
  it('should not generate warning: empty retry, using default', () => rpRetry(options).then(() => {
52
- sinon.assert.notCalled(loggerSpyWarn);
60
+ assert.notCalled(loggerSpyWarn);
53
61
  }));
54
62
  it('should generate warning: out of scope retries: -1 becoming min', () => {
55
63
  options.retry.retries = -1;
56
64
  return rpRetry(options).then(() => {
57
- sinon.assert.calledOnce(loggerSpyWarn);
58
- const callArgs = loggerSpyWarn.getCall(0).args;
59
- expect(callArgs[0]).to.be.a('string');
60
- expect(callArgs[0]).to.equal('out of scope retries, reset to min');
65
+ assert.calledOnce(loggerSpyWarn);
66
+ const callArgs = loggerSpyWarn.getCall(FIRST_CALL).args;
67
+ expect(callArgs[CALL_ARG_MESSAGE]).to.be.a('string');
68
+ expect(callArgs[CALL_ARG_MESSAGE]).to.equal('out of scope retries, reset to min');
61
69
  });
62
70
  });
63
71
  it('should generate warning: out of scope retries: 20 becoming max', () => {
64
72
  options.retry.retries = 20;
65
73
  return rpRetry(options).then(() => {
66
- sinon.assert.calledOnce(loggerSpyWarn);
67
- const callArgs = loggerSpyWarn.getCall(0).args;
68
- expect(callArgs[0]).to.be.a('string');
69
- expect(callArgs[0]).to.equal('out of scope retries, reset to max');
74
+ assert.calledOnce(loggerSpyWarn);
75
+ const callArgs = loggerSpyWarn.getCall(FIRST_CALL).args;
76
+ expect(callArgs[CALL_ARG_MESSAGE]).to.be.a('string');
77
+ expect(callArgs[CALL_ARG_MESSAGE]).to.equal('out of scope retries, reset to max');
70
78
  });
71
79
  });
72
80
  it('should not generate warning: in scope retries', () => {
73
81
  options.retry.retries = 10;
74
82
  return rpRetry(options).then(() => {
75
- sinon.assert.notCalled(loggerSpyWarn);
83
+ assert.notCalled(loggerSpyWarn);
76
84
  });
77
85
  });
78
86
  it('should generate warning: invalid retries: "notANumber" becoming default', () => {
79
87
  options.retry.retries = 'notANumber';
80
88
  return rpRetry(options).then(() => {
81
- sinon.assert.calledOnce(loggerSpyWarn);
82
- const callArgs = loggerSpyWarn.getCall(0).args;
83
- expect(callArgs[0]).to.be.a('string');
84
- expect(callArgs[0]).to.equal('invalid retries, reset to default');
89
+ assert.calledOnce(loggerSpyWarn);
90
+ const callArgs = loggerSpyWarn.getCall(FIRST_CALL).args;
91
+ expect(callArgs[CALL_ARG_MESSAGE]).to.be.a('string');
92
+ expect(callArgs[CALL_ARG_MESSAGE]).to.equal('invalid retries, reset to default');
85
93
  });
86
94
  });
87
95
  it('should generate warning: out of scope delay: 0 becoming min', () => {
88
96
  options.retry.delay = 0;
89
97
  return rpRetry(options).then(() => {
90
- sinon.assert.calledOnce(loggerSpyWarn);
91
- const callArgs = loggerSpyWarn.getCall(0).args;
92
- expect(callArgs[0]).to.be.a('string');
93
- expect(callArgs[0]).to.equal('out of scope delay, reset to min');
98
+ assert.calledOnce(loggerSpyWarn);
99
+ const callArgs = loggerSpyWarn.getCall(FIRST_CALL).args;
100
+ expect(callArgs[CALL_ARG_MESSAGE]).to.be.a('string');
101
+ expect(callArgs[CALL_ARG_MESSAGE]).to.equal('out of scope delay, reset to min');
94
102
  });
95
103
  });
96
104
  it('should generate warning: out of scope delay: 100000 becoming max', () => {
97
105
  options.retry.delay = 100000;
98
106
  return rpRetry(options).then(() => {
99
- sinon.assert.calledOnce(loggerSpyWarn);
100
- const callArgs = loggerSpyWarn.getCall(0).args;
101
- expect(callArgs[0]).to.be.a('string');
102
- expect(callArgs[0]).to.equal('out of scope delay, reset to max');
107
+ assert.calledOnce(loggerSpyWarn);
108
+ const callArgs = loggerSpyWarn.getCall(FIRST_CALL).args;
109
+ expect(callArgs[CALL_ARG_MESSAGE]).to.be.a('string');
110
+ expect(callArgs[CALL_ARG_MESSAGE]).to.equal('out of scope delay, reset to max');
103
111
  });
104
112
  });
105
113
  it('should generate warning: invalid delay: "notANumber" becoming default', () => {
106
114
  options.retry.delay = 'notANumber';
107
115
  return rpRetry(options).then(() => {
108
- sinon.assert.calledOnce(loggerSpyWarn);
109
- const callArgs = loggerSpyWarn.getCall(0).args;
110
- expect(callArgs[0]).to.be.a('string');
111
- expect(callArgs[0]).to.equal('invalid delay, reset to default');
116
+ assert.calledOnce(loggerSpyWarn);
117
+ const callArgs = loggerSpyWarn.getCall(FIRST_CALL).args;
118
+ expect(callArgs[CALL_ARG_MESSAGE]).to.be.a('string');
119
+ expect(callArgs[CALL_ARG_MESSAGE]).to.equal('invalid delay, reset to default');
112
120
  });
113
121
  });
114
122
  it('should not generate warning: in scope delay', () => {
115
123
  options.retry.delay = 20000;
116
124
  return rpRetry(options).then(() => {
117
- sinon.assert.notCalled(loggerSpyWarn);
125
+ assert.notCalled(loggerSpyWarn);
118
126
  });
119
127
  });
120
128
  it('should generate warning: out of scope timeout: 0 becoming min', () => {
121
129
  options.retry.timeout = 0;
122
130
  return rpRetry(options).then(() => {
123
- sinon.assert.calledOnce(loggerSpyWarn);
124
- const callArgs = loggerSpyWarn.getCall(0).args;
125
- expect(callArgs[0]).to.be.a('string');
126
- expect(callArgs[0]).to.equal('out of scope timeout, reset to min');
131
+ assert.calledOnce(loggerSpyWarn);
132
+ const callArgs = loggerSpyWarn.getCall(FIRST_CALL).args;
133
+ expect(callArgs[CALL_ARG_MESSAGE]).to.be.a('string');
134
+ expect(callArgs[CALL_ARG_MESSAGE]).to.equal('out of scope timeout, reset to min');
127
135
  });
128
136
  });
129
137
  it('should generate warning: out of scope timeout: 150 becoming max', () => {
130
138
  options.retry.timeout = 150;
131
139
  return rpRetry(options).then(() => {
132
- sinon.assert.calledOnce(loggerSpyWarn);
133
- const callArgs = loggerSpyWarn.getCall(0).args;
134
- expect(callArgs[0]).to.be.a('string');
135
- expect(callArgs[0]).to.equal('out of scope timeout, reset to max');
140
+ assert.calledOnce(loggerSpyWarn);
141
+ const callArgs = loggerSpyWarn.getCall(FIRST_CALL).args;
142
+ expect(callArgs[CALL_ARG_MESSAGE]).to.be.a('string');
143
+ expect(callArgs[CALL_ARG_MESSAGE]).to.equal('out of scope timeout, reset to max');
136
144
  });
137
145
  });
138
146
  it('should generate warning: invalid timeout: "notANumber" becoming default', () => {
139
147
  options.retry.timeout = 'notANumber';
140
148
  return rpRetry(options).then(() => {
141
- sinon.assert.calledOnce(loggerSpyWarn);
142
- const callArgs = loggerSpyWarn.getCall(0).args;
143
- expect(callArgs[0]).to.be.a('string');
144
- expect(callArgs[0]).to.equal('invalid timeout, reset to default');
149
+ assert.calledOnce(loggerSpyWarn);
150
+ const callArgs = loggerSpyWarn.getCall(FIRST_CALL).args;
151
+ expect(callArgs[CALL_ARG_MESSAGE]).to.be.a('string');
152
+ expect(callArgs[CALL_ARG_MESSAGE]).to.equal('invalid timeout, reset to default');
145
153
  });
146
154
  });
147
155
  it('should not generate warning: in scope timeout', () => {
148
156
  options.retry.timeout = 50;
149
157
  return rpRetry(options).then(() => {
150
- sinon.assert.notCalled(loggerSpyWarn);
158
+ assert.notCalled(loggerSpyWarn);
151
159
  });
152
160
  });
153
161
  it('should generate warning: invalid retryStrategy: "notANumber" becoming default function', () => {
154
162
  options.retry.retryStrategy = 'notAFunction';
155
163
  return rpRetry(options).then(() => {
156
- sinon.assert.calledOnce(loggerSpyWarn);
157
- const callArgs = loggerSpyWarn.getCall(0).args;
158
- expect(callArgs[0]).to.be.a('string');
159
- expect(callArgs[0]).to.equal('invalid retryStrategy, ignoring');
164
+ assert.calledOnce(loggerSpyWarn);
165
+ const callArgs = loggerSpyWarn.getCall(FIRST_CALL).args;
166
+ expect(callArgs[CALL_ARG_MESSAGE]).to.be.a('string');
167
+ expect(callArgs[CALL_ARG_MESSAGE]).to.equal('invalid retryStrategy, ignoring');
160
168
  });
161
169
  });
162
170
  it('should generate warning: invalid delayStrategy: "notANumber" becoming delay or default', () => {
163
171
  options.retry.delayStrategy = 'notAFunction';
164
172
  return rpRetry(options).then(() => {
165
- sinon.assert.calledOnce(loggerSpyWarn);
166
- const callArgs = loggerSpyWarn.getCall(0).args;
167
- expect(callArgs[0]).to.be.a('string');
168
- expect(callArgs[0]).to.equal('invalid delayStrategy, using delay');
173
+ assert.calledOnce(loggerSpyWarn);
174
+ const callArgs = loggerSpyWarn.getCall(FIRST_CALL).args;
175
+ expect(callArgs[CALL_ARG_MESSAGE]).to.be.a('string');
176
+ expect(callArgs[CALL_ARG_MESSAGE]).to.equal('invalid delayStrategy, using delay');
169
177
  });
170
178
  });
171
179
  it('should generate multiple warnings', () => {
172
180
  options.retry.delayStrategy = 'notAFunction';
173
181
  options.retry.retries = 'notANumber';
174
182
  return rpRetry(options).then(() => {
175
- sinon.assert.calledTwice(loggerSpyWarn);
183
+ assert.calledTwice(loggerSpyWarn);
176
184
  });
177
185
  });
178
186
  it('should generate warning: invalid logLevel.request, reset to default', () => {
@@ -180,20 +188,20 @@ describe('request-retry Unit Tests', () => {
180
188
  request: 'unknownLevel',
181
189
  };
182
190
  return rpRetry(options).then(() => {
183
- sinon.assert.calledOnce(loggerSpyWarn);
184
- const callArgs = loggerSpyWarn.getCall(0).args;
185
- expect(callArgs[0]).to.be.a('string');
186
- expect(callArgs[0]).to.equal('invalid logLevel.request, reset to default');
191
+ assert.calledOnce(loggerSpyWarn);
192
+ const callArgs = loggerSpyWarn.getCall(FIRST_CALL).args;
193
+ expect(callArgs[CALL_ARG_MESSAGE]).to.be.a('string');
194
+ expect(callArgs[CALL_ARG_MESSAGE]).to.equal('invalid logLevel.request, reset to default');
187
195
  });
188
196
  });
189
197
  it('should not generate warning: correct logLevel (info)', () => {
190
- loggerSpyInfo = sinon.spy(logger, 'info');
198
+ loggerSpyInfo = spy(logger, 'info');
191
199
  options.retry.logLevel = {
192
200
  response: 'info',
193
201
  };
194
202
  return rpRetry(options).then(() => {
195
- sinon.assert.notCalled(loggerSpyWarn);
196
- sinon.assert.calledOnce(loggerSpyInfo);
203
+ assert.notCalled(loggerSpyWarn);
204
+ assert.calledOnce(loggerSpyInfo);
197
205
  loggerSpyInfo.restore();
198
206
  });
199
207
  });
@@ -202,10 +210,10 @@ describe('request-retry Unit Tests', () => {
202
210
  responseDetails: 'unknownDetails',
203
211
  };
204
212
  return rpRetry(options).then(() => {
205
- sinon.assert.calledOnce(loggerSpyWarn);
206
- const callArgs = loggerSpyWarn.getCall(0).args;
207
- expect(callArgs[0]).to.be.a('string');
208
- expect(callArgs[0]).to.equal('invalid logLevel.responseDetails, reset to default');
213
+ assert.calledOnce(loggerSpyWarn);
214
+ const callArgs = loggerSpyWarn.getCall(FIRST_CALL).args;
215
+ expect(callArgs[CALL_ARG_MESSAGE]).to.be.a('string');
216
+ expect(callArgs[CALL_ARG_MESSAGE]).to.equal('invalid logLevel.responseDetails, reset to default');
209
217
  });
210
218
  });
211
219
  it('should not generate warning: correct logLevelResponseName', () => {
@@ -213,7 +221,7 @@ describe('request-retry Unit Tests', () => {
213
221
  responseName: 'aName',
214
222
  };
215
223
  return rpRetry(options).then(() => {
216
- sinon.assert.notCalled(loggerSpyWarn);
224
+ assert.notCalled(loggerSpyWarn);
217
225
  });
218
226
  });
219
227
  it('should generate warning: invalid logLevel.responseName (""), reset to default', () => {
@@ -221,10 +229,10 @@ describe('request-retry Unit Tests', () => {
221
229
  responseName: '',
222
230
  };
223
231
  return rpRetry(options).then(() => {
224
- sinon.assert.calledOnce(loggerSpyWarn);
225
- const callArgs = loggerSpyWarn.getCall(0).args;
226
- expect(callArgs[0]).to.be.a('string');
227
- expect(callArgs[0]).to.equal('invalid logLevel.responseName, reset to default');
232
+ assert.calledOnce(loggerSpyWarn);
233
+ const callArgs = loggerSpyWarn.getCall(FIRST_CALL).args;
234
+ expect(callArgs[CALL_ARG_MESSAGE]).to.be.a('string');
235
+ expect(callArgs[CALL_ARG_MESSAGE]).to.equal('invalid logLevel.responseName, reset to default');
228
236
  });
229
237
  });
230
238
  it('should generate warning: invalid logLevel.responseName (" ""), reset to default', () => {
@@ -232,15 +240,15 @@ describe('request-retry Unit Tests', () => {
232
240
  responseName: ' ',
233
241
  };
234
242
  return rpRetry(options).then(() => {
235
- sinon.assert.calledOnce(loggerSpyWarn);
236
- const callArgs = loggerSpyWarn.getCall(0).args;
237
- expect(callArgs[0]).to.be.a('string');
238
- expect(callArgs[0]).to.equal('invalid logLevel.responseName, reset to default');
243
+ assert.calledOnce(loggerSpyWarn);
244
+ const callArgs = loggerSpyWarn.getCall(FIRST_CALL).args;
245
+ expect(callArgs[CALL_ARG_MESSAGE]).to.be.a('string');
246
+ expect(callArgs[CALL_ARG_MESSAGE]).to.equal('invalid logLevel.responseName, reset to default');
239
247
  });
240
248
  });
241
249
  });
242
- describe('rpRetry(options) options validation run', function test() {
243
- this.timeout(50000);
250
+ describe('rpRetry(options) options validation run', function Test() {
251
+ this.timeout(TIMEOUT);
244
252
  const options = {
245
253
  method: 'GET',
246
254
  headers: {
@@ -251,21 +259,23 @@ describe('request-retry Unit Tests', () => {
251
259
  retry: {},
252
260
  };
253
261
  beforeEach(() => {
254
- loggerSpyWarn = sinon.spy(logger, 'warn');
262
+ loggerSpyWarn = spy(logger, 'warn');
255
263
  });
256
264
  afterEach(() => {
257
265
  options.retry = {};
258
266
  loggerSpyWarn.restore();
259
267
  });
260
268
  it('should generate warning: bad retry strategy (throwing an error), ignoring and using default retries', () => {
261
- options.retry.retryStrategy = () => { throw new Error('this is a test'); };
269
+ options.retry.retryStrategy = () => {
270
+ throw new Error('this is a test');
271
+ };
262
272
  options.retry.retries = 2;
263
273
  return rpRetry(options)
264
274
  .catch(() => {
265
- sinon.assert.called(loggerSpyWarn);
266
- const callArgs = loggerSpyWarn.getCall(0).args;
267
- expect(callArgs[0]).to.be.a('string');
268
- expect(callArgs[0]).to.equal('bad retry strategy');
275
+ assert.called(loggerSpyWarn);
276
+ const callArgs = loggerSpyWarn.getCall(FIRST_CALL).args;
277
+ expect(callArgs[CALL_ARG_MESSAGE]).to.be.a('string');
278
+ expect(callArgs[CALL_ARG_MESSAGE]).to.equal('bad retry strategy');
269
279
  });
270
280
  });
271
281
  it('should generate warning: bad retry strategy (not returning a boolean), ignoring and using default retries', () => {
@@ -273,10 +283,10 @@ describe('request-retry Unit Tests', () => {
273
283
  options.retry.retries = 2;
274
284
  return rpRetry(options)
275
285
  .catch(() => {
276
- sinon.assert.called(loggerSpyWarn);
277
- const callArgs = loggerSpyWarn.getCall(0).args;
278
- expect(callArgs[0]).to.be.a('string');
279
- expect(callArgs[0]).to.equal('bad retry strategy');
286
+ assert.called(loggerSpyWarn);
287
+ const callArgs = loggerSpyWarn.getCall(FIRST_CALL).args;
288
+ expect(callArgs[CALL_ARG_MESSAGE]).to.be.a('string');
289
+ expect(callArgs[CALL_ARG_MESSAGE]).to.equal('bad retry strategy');
280
290
  });
281
291
  });
282
292
  it('should not generate warning: retry strategy returning a boolean', () => {
@@ -284,18 +294,20 @@ describe('request-retry Unit Tests', () => {
284
294
  options.retry.retries = 2;
285
295
  return rpRetry(options)
286
296
  .catch(() => {
287
- sinon.assert.called(loggerSpyWarn);
297
+ assert.called(loggerSpyWarn);
288
298
  });
289
299
  });
290
300
  it('should generate warning: bad delay strategy (throwing an error), ignoring and using default delay', () => {
291
- options.retry.delayStrategy = () => { throw new Error('this is a test'); };
301
+ options.retry.delayStrategy = () => {
302
+ throw new Error('this is a test');
303
+ };
292
304
  options.retry.retries = 2;
293
305
  return rpRetry(options)
294
306
  .catch(() => {
295
- sinon.assert.called(loggerSpyWarn);
296
- const callArgs = loggerSpyWarn.getCall(0).args;
297
- expect(callArgs[0]).to.be.a('string');
298
- expect(callArgs[0]).to.equal('bad delay strategy');
307
+ assert.called(loggerSpyWarn);
308
+ const callArgs = loggerSpyWarn.getCall(FIRST_CALL).args;
309
+ expect(callArgs[CALL_ARG_MESSAGE]).to.be.a('string');
310
+ expect(callArgs[CALL_ARG_MESSAGE]).to.equal('bad delay strategy');
299
311
  });
300
312
  });
301
313
  it('should generate warning: bad delay strategy (not returning a number), ignoring and using default delay', () => {
@@ -303,40 +315,40 @@ describe('request-retry Unit Tests', () => {
303
315
  options.retry.retries = 2;
304
316
  return rpRetry(options)
305
317
  .catch(() => {
306
- sinon.assert.called(loggerSpyWarn);
307
- const callArgs = loggerSpyWarn.getCall(0).args;
308
- expect(callArgs[0]).to.be.a('string');
309
- expect(callArgs[0]).to.equal('bad delay strategy');
318
+ assert.called(loggerSpyWarn);
319
+ const callArgs = loggerSpyWarn.getCall(FIRST_CALL).args;
320
+ expect(callArgs[CALL_ARG_MESSAGE]).to.be.a('string');
321
+ expect(callArgs[CALL_ARG_MESSAGE]).to.equal('bad delay strategy');
310
322
  });
311
323
  });
312
324
  it('should generate warning: bad delay strategy (returning an out of scope number), ignoring and using default delay', () => {
313
- options.retry.delayStrategy = () => -20;
325
+ options.retry.delayStrategy = () => DELAY_STRATEGY_RESPONSE_1;
314
326
  options.retry.retries = 2;
315
327
  return rpRetry(options)
316
328
  .catch(() => {
317
- sinon.assert.called(loggerSpyWarn);
318
- const callArgs = loggerSpyWarn.getCall(0).args;
319
- expect(callArgs[0]).to.be.a('string');
320
- expect(callArgs[0]).to.equal('calculated delay out of scope: using delay or default');
329
+ assert.called(loggerSpyWarn);
330
+ const callArgs = loggerSpyWarn.getCall(FIRST_CALL).args;
331
+ expect(callArgs[CALL_ARG_MESSAGE]).to.be.a('string');
332
+ expect(callArgs[CALL_ARG_MESSAGE]).to.equal('calculated delay out of scope: using delay or default');
321
333
  });
322
334
  });
323
335
  it('should not generate warning: delay strategy returning an in scope number', () => {
324
- options.retry.delayStrategy = () => 50;
336
+ options.retry.delayStrategy = () => DELAY_STRATEGY_RESPONSE_2;
325
337
  options.retry.retries = 2;
326
338
  return rpRetry(options)
327
339
  .catch(() => {
328
- sinon.assert.called(loggerSpyWarn);
340
+ assert.called(loggerSpyWarn);
329
341
  });
330
342
  });
331
343
  it('should generate a timeout error', () => {
332
- options.retry.delayStrategy = () => 10000;
333
- options.retry.timeout = 10;
334
- options.retry.retries = 2;
344
+ options.retry.delayStrategy = () => RETRY_DELAY;
345
+ options.retry.timeout = RETRY_TIMEOUT;
346
+ options.retry.retries = RETRY_RETRIES;
335
347
  return rpRetry(options)
336
348
  .catch((err) => {
337
349
  expect(err.name).to.equal('System');
338
- expect(VError.cause(err).name).to.equal('TimeoutError');
339
- // sinon.assert.called(loggerSpyWarn);
350
+ expect(err.cause.name).to.equal('TimeoutError');
351
+ // assert.called(loggerSpyWarn);
340
352
  });
341
353
  });
342
354
  it('should stop mock server', () => rpRetry({
@@ -346,13 +358,13 @@ describe('request-retry Unit Tests', () => {
346
358
  },
347
359
  url: 'http://localhost:9070/stop',
348
360
  retry: {
349
- delayStrategy: () => 100,
361
+ delayStrategy: () => DELAY_STRATEGY_RESPONSE_3,
350
362
  retries: 1,
351
363
  },
352
364
  })
353
365
  .catch((err) => {
354
366
  expect(err.name).to.equal('System');
355
- expect(VError.cause(err).name).to.equal('TimeoutError');
367
+ expect(err.cause.name).to.equal('TimeoutError');
356
368
  }));
357
369
  });
358
370
  });
package/test/testEnv.js CHANGED
@@ -1,4 +1,5 @@
1
1
  /* eslint no-process-env: "off" */
2
+ import process from 'process';
2
3
 
3
4
  /**
4
5
  * The following environment variables are set for the test:
@@ -13,8 +14,10 @@
13
14
  * | LOG_MODE | log mode | none
14
15
  */
15
16
 
16
- // process.env.SUMO_LOGIC_ENDPOINT = 'http://localhost:9080/logs/';
17
- // process.env.SUMO_LOGIC_COLLECTOR_CODE = '1234';
17
+ /*
18
+ * process.env.SUMO_LOGIC_ENDPOINT = 'http://localhost:9080/logs/';
19
+ * process.env.SUMO_LOGIC_COLLECTOR_CODE = '1234';
20
+ */
18
21
  process.env.SUMO_LOGIC_ENDPOINT = null;
19
22
  process.env.SUMO_LOGIC_COLLECTOR_CODE = null;
20
23
  process.env.NO_STACK = 'yes';
package/.eslintrc DELETED
@@ -1,43 +0,0 @@
1
- {
2
- "plugins": [
3
- "@mimik/document-env",
4
- "@mimik/dependencies"
5
- ],
6
- "env": {
7
- "node": true
8
- },
9
- "parserOptions": {
10
- "ecmaVersion": 2020
11
- },
12
- "extends": "airbnb",
13
- "rules": {
14
- "import/no-extraneous-dependencies": ["error", {"devDependencies": true}],
15
- "import/no-unresolved": ["error", { "amd": true, "commonjs": true, "caseSensitiveStrict": true }],
16
- "brace-style": [1, "stroustrup", {"allowSingleLine": true}],
17
- "no-confusing-arrow": [0], // arrow isnt confusing
18
- "max-len": [1, 180, { "ignoreComments": true }],
19
- "linebreak-style": 0,
20
- "quotes": [1, "single"],
21
- "semi": [1, "always"],
22
- "no-process-env": ["error"],
23
- "@mimik/document-env/validate-document-env": 2,
24
- "@mimik/dependencies/case-sensitive": 2,
25
- "@mimik/dependencies/no-cycles": 2,
26
- "@mimik/dependencies/require-json-ext": 2
27
- },
28
- "settings":{
29
- "react": {
30
- "version": "detect"
31
- }
32
- },
33
- "globals": {
34
- "module": true,
35
- "require": true,
36
- "const": false,
37
- "it": false,
38
- "describe": false,
39
- "before": true,
40
- "after": true,
41
- "JSON": true
42
- }
43
- }