Skip to content

Ignore undefined options so that they don't override defaults #93

@mriedem

Description

@mriedem

We're using the library in a function like this:

  const retryWithExponentialBackoff = async (operation, { retries, minTimeout, maxTimeout, context } = {}) => {
    const op = retry.operation({
      retries: retries !== undefined ? retries : config.natsJetStream.retries,
      minTimeout,
      maxTimeout
    })

    return new Promise((resolve, reject) => {
      op.attempt(async currentAttempt => {
        try {
          const result = await operation()
          resolve(result)
        } catch (err) {
          log.warn({ attempt: currentAttempt, err, context }, 'Operation failed, retrying')
          if (!op.retry(err)) {
            reject(op.mainError())
          }
        }
      })
    })
  }

Where retries defaults to 60 but minTimeout and maxTimeout are undefined by default.

Because of this code:

node-retry/lib/retry.js

Lines 17 to 26 in 11efd6e

var opts = {
retries: 10,
factor: 2,
minTimeout: 1 * 1000,
maxTimeout: Infinity,
randomize: false
};
for (var key in options) {
opts[key] = options[key];
}

We're always wiping out the defaults for minTimeout and maxTimeout and basically never sleep between retry attempts.

Recreate:

> options = { retries: 3, minTimeout: undefined, maxTimeout:undefined }
{ retries: 3, minTimeout: undefined, maxTimeout: undefined }
> const retry2 = require('retry')
undefined
> ro = retry2.operation(options)
RetryOperation {
  _originalTimeouts: [ null, null, null ],
  _timeouts: [ NaN, NaN, NaN ],
  _options: { forever: false, unref: undefined, maxRetryTime: undefined },
  _maxRetryTime: Infinity,
  _fn: null,
  _errors: [],
  _attempts: 1,
  _operationTimeout: null,
  _operationTimeoutCb: null,
  _timeout: null,
  _operationStart: null,
  _timer: null
}
> options.minTimeout = 1000
1000
> ro2 = retry2.operation(options)
RetryOperation {
  _originalTimeouts: [ null, null, null ],
  _timeouts: [ NaN, NaN, NaN ],
  _options: { forever: false, unref: undefined, maxRetryTime: undefined },
  _maxRetryTime: Infinity,
  _fn: null,
  _errors: [],
  _attempts: 1,
  _operationTimeout: null,
  _operationTimeoutCb: null,
  _timeout: null,
  _operationStart: null,
  _timer: null
}
> options
{ retries: 3, minTimeout: 1000, maxTimeout: undefined }
> options.maxTimeout = 5000
5000
> options
{ retries: 3, minTimeout: 1000, maxTimeout: 5000 }
> 
> 
> retry2.operation(options)
RetryOperation {
  _originalTimeouts: [ 1000, 2000, 4000 ],
  _timeouts: [ 1000, 2000, 4000 ],
  _options: { forever: false, unref: undefined, maxRetryTime: undefined },
  _maxRetryTime: Infinity,
  _fn: null,
  _errors: [],
  _attempts: 1,
  _operationTimeout: null,
  _operationTimeoutCb: null,
  _timeout: null,
  _operationStart: null,
  _timer: null
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions