@mimik/request-retry 3.0.2 → 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,7 +1,6 @@
1
- const axios = require('axios');
2
- const clone = require('lodash.clone');
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
6
  const options = clone(origOptions);
@@ -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.2",
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,31 +29,28 @@
29
29
  "url": "https://bitbucket.org/mimiktech/request-retry"
30
30
  },
31
31
  "dependencies": {
32
- "@mimik/request-helper": "^1.7.11",
33
- "@mimik/response-helper": "^3.1.0",
34
- "@mimik/sumologic-winston-logger": "^1.6.22",
35
- "axios": "1.7.7",
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
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.12.1",
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",
43
44
  "body-parser": "1.20.3",
44
- "chai": "4.5.0",
45
- "eslint": "8.57.1",
46
- "eslint-config-airbnb": "19.0.4",
45
+ "c8": "10.1.3",
46
+ "chai": "5.2.0",
47
+ "eslint": "9.23.0",
47
48
  "eslint-plugin-import": "2.31.0",
48
- "eslint-plugin-jsx-a11y": "6.10.0",
49
- "eslint-plugin-react": "7.37.1",
50
- "eslint-plugin-react-hooks": "4.6.2",
51
- "express": "4.21.0",
52
- "husky": "9.1.6",
53
- "jsdoc-to-markdown": "9.0.2",
54
- "mocha": "10.7.3",
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": "17.1.0",
57
- "sinon": "19.0.2"
54
+ "sinon": "20.0.0"
58
55
  }
59
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,27 +1,36 @@
1
- const chai = require('chai');
2
- const sinon = require('sinon');
3
- const { beforeEach, afterEach } = require('mocha');
4
- 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';
5
9
 
6
- const logger = require('@mimik/sumologic-winston-logger');
7
- 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;
8
19
 
9
- const mockServer = require('./retryMock');
10
- const { rpRetry } = require('../index');
11
-
12
- const { expect } = chai;
13
- chai.should();
14
-
15
- // const DEFAULT_NO_MESSAGE = 'no message';
16
- // 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
+ */
17
25
 
18
26
  describe('request-retry Unit Tests', () => {
19
27
  const correlationId = getCorrelationId('--request-retry-test--');
20
28
  // let loggerSpyError;
21
29
  let loggerSpyWarn;
22
30
  let loggerSpyInfo;
31
+
23
32
  before(() => {
24
- mockServer.listen();
33
+ listen();
25
34
  });
26
35
 
27
36
  describe('rpRetry(options) options validations prerun', () => {
@@ -35,7 +44,7 @@ describe('request-retry Unit Tests', () => {
35
44
  retry: {},
36
45
  };
37
46
  beforeEach(() => {
38
- loggerSpyWarn = sinon.spy(logger, 'warn');
47
+ loggerSpyWarn = spy(logger, 'warn');
39
48
  });
40
49
  afterEach(() => {
41
50
  options.retry = {};
@@ -44,134 +53,134 @@ describe('request-retry Unit Tests', () => {
44
53
  it('should not generate warning: null retry, using default', () => {
45
54
  options.retry = null;
46
55
  return rpRetry(options).then(() => {
47
- sinon.assert.notCalled(loggerSpyWarn);
56
+ assert.notCalled(loggerSpyWarn);
48
57
  });
49
58
  });
50
59
  it('should not generate warning: empty retry, using default', () => rpRetry(options).then(() => {
51
- sinon.assert.notCalled(loggerSpyWarn);
60
+ assert.notCalled(loggerSpyWarn);
52
61
  }));
53
62
  it('should generate warning: out of scope retries: -1 becoming min', () => {
54
63
  options.retry.retries = -1;
55
64
  return rpRetry(options).then(() => {
56
- sinon.assert.calledOnce(loggerSpyWarn);
57
- const callArgs = loggerSpyWarn.getCall(0).args;
58
- expect(callArgs[0]).to.be.a('string');
59
- 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');
60
69
  });
61
70
  });
62
71
  it('should generate warning: out of scope retries: 20 becoming max', () => {
63
72
  options.retry.retries = 20;
64
73
  return rpRetry(options).then(() => {
65
- sinon.assert.calledOnce(loggerSpyWarn);
66
- const callArgs = loggerSpyWarn.getCall(0).args;
67
- expect(callArgs[0]).to.be.a('string');
68
- 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');
69
78
  });
70
79
  });
71
80
  it('should not generate warning: in scope retries', () => {
72
81
  options.retry.retries = 10;
73
82
  return rpRetry(options).then(() => {
74
- sinon.assert.notCalled(loggerSpyWarn);
83
+ assert.notCalled(loggerSpyWarn);
75
84
  });
76
85
  });
77
86
  it('should generate warning: invalid retries: "notANumber" becoming default', () => {
78
87
  options.retry.retries = 'notANumber';
79
88
  return rpRetry(options).then(() => {
80
- sinon.assert.calledOnce(loggerSpyWarn);
81
- const callArgs = loggerSpyWarn.getCall(0).args;
82
- expect(callArgs[0]).to.be.a('string');
83
- 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');
84
93
  });
85
94
  });
86
95
  it('should generate warning: out of scope delay: 0 becoming min', () => {
87
96
  options.retry.delay = 0;
88
97
  return rpRetry(options).then(() => {
89
- sinon.assert.calledOnce(loggerSpyWarn);
90
- const callArgs = loggerSpyWarn.getCall(0).args;
91
- expect(callArgs[0]).to.be.a('string');
92
- 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');
93
102
  });
94
103
  });
95
104
  it('should generate warning: out of scope delay: 100000 becoming max', () => {
96
105
  options.retry.delay = 100000;
97
106
  return rpRetry(options).then(() => {
98
- sinon.assert.calledOnce(loggerSpyWarn);
99
- const callArgs = loggerSpyWarn.getCall(0).args;
100
- expect(callArgs[0]).to.be.a('string');
101
- 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');
102
111
  });
103
112
  });
104
113
  it('should generate warning: invalid delay: "notANumber" becoming default', () => {
105
114
  options.retry.delay = 'notANumber';
106
115
  return rpRetry(options).then(() => {
107
- sinon.assert.calledOnce(loggerSpyWarn);
108
- const callArgs = loggerSpyWarn.getCall(0).args;
109
- expect(callArgs[0]).to.be.a('string');
110
- 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');
111
120
  });
112
121
  });
113
122
  it('should not generate warning: in scope delay', () => {
114
123
  options.retry.delay = 20000;
115
124
  return rpRetry(options).then(() => {
116
- sinon.assert.notCalled(loggerSpyWarn);
125
+ assert.notCalled(loggerSpyWarn);
117
126
  });
118
127
  });
119
128
  it('should generate warning: out of scope timeout: 0 becoming min', () => {
120
129
  options.retry.timeout = 0;
121
130
  return rpRetry(options).then(() => {
122
- sinon.assert.calledOnce(loggerSpyWarn);
123
- const callArgs = loggerSpyWarn.getCall(0).args;
124
- expect(callArgs[0]).to.be.a('string');
125
- 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');
126
135
  });
127
136
  });
128
137
  it('should generate warning: out of scope timeout: 150 becoming max', () => {
129
138
  options.retry.timeout = 150;
130
139
  return rpRetry(options).then(() => {
131
- sinon.assert.calledOnce(loggerSpyWarn);
132
- const callArgs = loggerSpyWarn.getCall(0).args;
133
- expect(callArgs[0]).to.be.a('string');
134
- 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');
135
144
  });
136
145
  });
137
146
  it('should generate warning: invalid timeout: "notANumber" becoming default', () => {
138
147
  options.retry.timeout = 'notANumber';
139
148
  return rpRetry(options).then(() => {
140
- sinon.assert.calledOnce(loggerSpyWarn);
141
- const callArgs = loggerSpyWarn.getCall(0).args;
142
- expect(callArgs[0]).to.be.a('string');
143
- 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');
144
153
  });
145
154
  });
146
155
  it('should not generate warning: in scope timeout', () => {
147
156
  options.retry.timeout = 50;
148
157
  return rpRetry(options).then(() => {
149
- sinon.assert.notCalled(loggerSpyWarn);
158
+ assert.notCalled(loggerSpyWarn);
150
159
  });
151
160
  });
152
161
  it('should generate warning: invalid retryStrategy: "notANumber" becoming default function', () => {
153
162
  options.retry.retryStrategy = 'notAFunction';
154
163
  return rpRetry(options).then(() => {
155
- sinon.assert.calledOnce(loggerSpyWarn);
156
- const callArgs = loggerSpyWarn.getCall(0).args;
157
- expect(callArgs[0]).to.be.a('string');
158
- 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');
159
168
  });
160
169
  });
161
170
  it('should generate warning: invalid delayStrategy: "notANumber" becoming delay or default', () => {
162
171
  options.retry.delayStrategy = 'notAFunction';
163
172
  return rpRetry(options).then(() => {
164
- sinon.assert.calledOnce(loggerSpyWarn);
165
- const callArgs = loggerSpyWarn.getCall(0).args;
166
- expect(callArgs[0]).to.be.a('string');
167
- 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');
168
177
  });
169
178
  });
170
179
  it('should generate multiple warnings', () => {
171
180
  options.retry.delayStrategy = 'notAFunction';
172
181
  options.retry.retries = 'notANumber';
173
182
  return rpRetry(options).then(() => {
174
- sinon.assert.calledTwice(loggerSpyWarn);
183
+ assert.calledTwice(loggerSpyWarn);
175
184
  });
176
185
  });
177
186
  it('should generate warning: invalid logLevel.request, reset to default', () => {
@@ -179,20 +188,20 @@ describe('request-retry Unit Tests', () => {
179
188
  request: 'unknownLevel',
180
189
  };
181
190
  return rpRetry(options).then(() => {
182
- sinon.assert.calledOnce(loggerSpyWarn);
183
- const callArgs = loggerSpyWarn.getCall(0).args;
184
- expect(callArgs[0]).to.be.a('string');
185
- 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');
186
195
  });
187
196
  });
188
197
  it('should not generate warning: correct logLevel (info)', () => {
189
- loggerSpyInfo = sinon.spy(logger, 'info');
198
+ loggerSpyInfo = spy(logger, 'info');
190
199
  options.retry.logLevel = {
191
200
  response: 'info',
192
201
  };
193
202
  return rpRetry(options).then(() => {
194
- sinon.assert.notCalled(loggerSpyWarn);
195
- sinon.assert.calledOnce(loggerSpyInfo);
203
+ assert.notCalled(loggerSpyWarn);
204
+ assert.calledOnce(loggerSpyInfo);
196
205
  loggerSpyInfo.restore();
197
206
  });
198
207
  });
@@ -201,10 +210,10 @@ describe('request-retry Unit Tests', () => {
201
210
  responseDetails: 'unknownDetails',
202
211
  };
203
212
  return rpRetry(options).then(() => {
204
- sinon.assert.calledOnce(loggerSpyWarn);
205
- const callArgs = loggerSpyWarn.getCall(0).args;
206
- expect(callArgs[0]).to.be.a('string');
207
- 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');
208
217
  });
209
218
  });
210
219
  it('should not generate warning: correct logLevelResponseName', () => {
@@ -212,7 +221,7 @@ describe('request-retry Unit Tests', () => {
212
221
  responseName: 'aName',
213
222
  };
214
223
  return rpRetry(options).then(() => {
215
- sinon.assert.notCalled(loggerSpyWarn);
224
+ assert.notCalled(loggerSpyWarn);
216
225
  });
217
226
  });
218
227
  it('should generate warning: invalid logLevel.responseName (""), reset to default', () => {
@@ -220,10 +229,10 @@ describe('request-retry Unit Tests', () => {
220
229
  responseName: '',
221
230
  };
222
231
  return rpRetry(options).then(() => {
223
- sinon.assert.calledOnce(loggerSpyWarn);
224
- const callArgs = loggerSpyWarn.getCall(0).args;
225
- expect(callArgs[0]).to.be.a('string');
226
- 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');
227
236
  });
228
237
  });
229
238
  it('should generate warning: invalid logLevel.responseName (" ""), reset to default', () => {
@@ -231,15 +240,15 @@ describe('request-retry Unit Tests', () => {
231
240
  responseName: ' ',
232
241
  };
233
242
  return rpRetry(options).then(() => {
234
- sinon.assert.calledOnce(loggerSpyWarn);
235
- const callArgs = loggerSpyWarn.getCall(0).args;
236
- expect(callArgs[0]).to.be.a('string');
237
- 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');
238
247
  });
239
248
  });
240
249
  });
241
- describe('rpRetry(options) options validation run', function test() {
242
- this.timeout(50000);
250
+ describe('rpRetry(options) options validation run', function Test() {
251
+ this.timeout(TIMEOUT);
243
252
  const options = {
244
253
  method: 'GET',
245
254
  headers: {
@@ -250,21 +259,23 @@ describe('request-retry Unit Tests', () => {
250
259
  retry: {},
251
260
  };
252
261
  beforeEach(() => {
253
- loggerSpyWarn = sinon.spy(logger, 'warn');
262
+ loggerSpyWarn = spy(logger, 'warn');
254
263
  });
255
264
  afterEach(() => {
256
265
  options.retry = {};
257
266
  loggerSpyWarn.restore();
258
267
  });
259
268
  it('should generate warning: bad retry strategy (throwing an error), ignoring and using default retries', () => {
260
- options.retry.retryStrategy = () => { throw new Error('this is a test'); };
269
+ options.retry.retryStrategy = () => {
270
+ throw new Error('this is a test');
271
+ };
261
272
  options.retry.retries = 2;
262
273
  return rpRetry(options)
263
274
  .catch(() => {
264
- sinon.assert.called(loggerSpyWarn);
265
- const callArgs = loggerSpyWarn.getCall(0).args;
266
- expect(callArgs[0]).to.be.a('string');
267
- 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');
268
279
  });
269
280
  });
270
281
  it('should generate warning: bad retry strategy (not returning a boolean), ignoring and using default retries', () => {
@@ -272,10 +283,10 @@ describe('request-retry Unit Tests', () => {
272
283
  options.retry.retries = 2;
273
284
  return rpRetry(options)
274
285
  .catch(() => {
275
- sinon.assert.called(loggerSpyWarn);
276
- const callArgs = loggerSpyWarn.getCall(0).args;
277
- expect(callArgs[0]).to.be.a('string');
278
- 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');
279
290
  });
280
291
  });
281
292
  it('should not generate warning: retry strategy returning a boolean', () => {
@@ -283,18 +294,20 @@ describe('request-retry Unit Tests', () => {
283
294
  options.retry.retries = 2;
284
295
  return rpRetry(options)
285
296
  .catch(() => {
286
- sinon.assert.called(loggerSpyWarn);
297
+ assert.called(loggerSpyWarn);
287
298
  });
288
299
  });
289
300
  it('should generate warning: bad delay strategy (throwing an error), ignoring and using default delay', () => {
290
- options.retry.delayStrategy = () => { throw new Error('this is a test'); };
301
+ options.retry.delayStrategy = () => {
302
+ throw new Error('this is a test');
303
+ };
291
304
  options.retry.retries = 2;
292
305
  return rpRetry(options)
293
306
  .catch(() => {
294
- sinon.assert.called(loggerSpyWarn);
295
- const callArgs = loggerSpyWarn.getCall(0).args;
296
- expect(callArgs[0]).to.be.a('string');
297
- 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');
298
311
  });
299
312
  });
300
313
  it('should generate warning: bad delay strategy (not returning a number), ignoring and using default delay', () => {
@@ -302,40 +315,40 @@ describe('request-retry Unit Tests', () => {
302
315
  options.retry.retries = 2;
303
316
  return rpRetry(options)
304
317
  .catch(() => {
305
- sinon.assert.called(loggerSpyWarn);
306
- const callArgs = loggerSpyWarn.getCall(0).args;
307
- expect(callArgs[0]).to.be.a('string');
308
- 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');
309
322
  });
310
323
  });
311
324
  it('should generate warning: bad delay strategy (returning an out of scope number), ignoring and using default delay', () => {
312
- options.retry.delayStrategy = () => -20;
325
+ options.retry.delayStrategy = () => DELAY_STRATEGY_RESPONSE_1;
313
326
  options.retry.retries = 2;
314
327
  return rpRetry(options)
315
328
  .catch(() => {
316
- sinon.assert.called(loggerSpyWarn);
317
- const callArgs = loggerSpyWarn.getCall(0).args;
318
- expect(callArgs[0]).to.be.a('string');
319
- 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');
320
333
  });
321
334
  });
322
335
  it('should not generate warning: delay strategy returning an in scope number', () => {
323
- options.retry.delayStrategy = () => 50;
336
+ options.retry.delayStrategy = () => DELAY_STRATEGY_RESPONSE_2;
324
337
  options.retry.retries = 2;
325
338
  return rpRetry(options)
326
339
  .catch(() => {
327
- sinon.assert.called(loggerSpyWarn);
340
+ assert.called(loggerSpyWarn);
328
341
  });
329
342
  });
330
343
  it('should generate a timeout error', () => {
331
- options.retry.delayStrategy = () => 10000;
332
- options.retry.timeout = 10;
333
- options.retry.retries = 2;
344
+ options.retry.delayStrategy = () => RETRY_DELAY;
345
+ options.retry.timeout = RETRY_TIMEOUT;
346
+ options.retry.retries = RETRY_RETRIES;
334
347
  return rpRetry(options)
335
348
  .catch((err) => {
336
349
  expect(err.name).to.equal('System');
337
350
  expect(err.cause.name).to.equal('TimeoutError');
338
- // sinon.assert.called(loggerSpyWarn);
351
+ // assert.called(loggerSpyWarn);
339
352
  });
340
353
  });
341
354
  it('should stop mock server', () => rpRetry({
@@ -345,7 +358,7 @@ describe('request-retry Unit Tests', () => {
345
358
  },
346
359
  url: 'http://localhost:9070/stop',
347
360
  retry: {
348
- delayStrategy: () => 100,
361
+ delayStrategy: () => DELAY_STRATEGY_RESPONSE_3,
349
362
  retries: 1,
350
363
  },
351
364
  })
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
- }