https://github.com/kessler/exponential-backoff
Opinionated exponential backoff retry driver
https://github.com/kessler/exponential-backoff
exponential-backoff nodejs nodejs-modules npm-package
Last synced: 22 days ago
JSON representation
Opinionated exponential backoff retry driver
- Host: GitHub
- URL: https://github.com/kessler/exponential-backoff
- Owner: kessler
- License: mit
- Created: 2017-07-07T20:43:41.000Z (almost 8 years ago)
- Default Branch: master
- Last Pushed: 2020-11-19T03:09:25.000Z (over 4 years ago)
- Last Synced: 2025-04-04T03:31:51.115Z (28 days ago)
- Topics: exponential-backoff, nodejs, nodejs-modules, npm-package
- Language: JavaScript
- Size: 22.5 KB
- Stars: 6
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
## @kessler/exponential-backoff
**Opinionated modern exponential backoff retry driver**
[](https://www.npmjs.org/package/@kessler/exponential-backoff) [](http://travis-ci.org/kessler/exponential-backoff) [](https://david-dm.org/kessler/@kessler/exponential-backoff)
As of version `3.x` callback support is dropped.
### install
```
npm i -S @kessler/exponential-backoff
```### simplest example
```js
const backoff = require('@kessler/exponential-backoff')async function main() {
// if an error is thrown then work will be retried
// with an appropriate delay
// after `maxAttempts` is exceeded
// an 'operation failed, exceeded maximum attempts' Error
// is thrown and the retry process stops
const work = () => httpRequest('http://example.com')
const response = await backoff(work)
}```
### changing the retry behavior
```js
const backoff = require('@kessler/exponential-backoff')async function main() {
const work = () => httpRequest('http://example.com')
// more details about these options below
const response = await backoff(work, {
maxAttempts: 100,
maxExponent: 10
})
}
```
#### configuration options- **maxAttempts** (Default 100) - maximum number of attempts before giving up. Meaning, if the 100th attempt fails an error will be thrown.
- **throwMaxAttemptsError** (Default true) - if set to false, no error will be thrown when maxAttempts is exceeded
- **delayInterval** (Default 100) - minimum delay unit, random(0, Math.pow(base, attemptNumber or maxAttempts)) * delayInterval = next delay
- **base** (Default 2) - base exponent for backoff algorithm
- **maxExponent** (Default 10) - in exponential backoff the number of attempts is used as the exponent, this is the maximum value that can be used even if retries exceed this value
- **unrefTimer** (Default false) - retry delay is achieved using setTimeout(). by default it will be unrefed, so the process will not wait for these timers to finish### iteration API
You can also _iterate_ over the attempts for better insight into and control over the process.
```js
const backoff = require('@kessler/exponential-backoff')async function main() {
const work = () => httpRequest('http://example.com')
const iterator = backoff.iterator(work /*, { you can provide options here } */)
for await (let attempt of iterator) {
console.log(`this is attempt #${attempt}`)
if (attempt > 0) {
console.log(iterator.lastError)
}if (attempt > 2) {
break;
}
}// proceed from attempt #2 until maxAttempts
for await (let attempt of iterator) {}
console.log(iterator.result)
}```
### optimized version
The startup code in `backoff()` has a cost. You can see the code in [bench.js](bench.js). In situations where you need a performence optimization, use the cached version (but remember: _preoptimization is the root of all evil!_):
```js
const backoff = require('@kessler/exponential-backoff')async function main() {
const retry = backoff.cached(/* options */)
const work = () => httpRequest('http://example.com')
for (let i = 0; i < 1000; i++) {
const response = await retry(work)
}
}```
also cached iterator:
```js
const backoff = require('@kessler/exponential-backoff')async function main() {
const createIterator = backoff.cachedIterator(/* options */)
const work = () => httpRequest('http://example.com')
for (let i = 0; i < 1000; i++) {
const iterator = createIterator(work)
for await (const attempt of iterator) {}
}
}```
### infinite max attempts
Specifiying maxAttempts = Infinity can be handy in situations where you want to retry forever or control the maximum attempts dynamically.This, however, will never through a `operation failed, exceeded maximum attempts` error and implicitly ignores `throwMaxAttemptsError` flag
```js
const backoff = require('@kessler/exponential-backoff')async function main() {
const work = attempt => {
if (attempt > computeMaxAttemptSomehow()) {
return
}return httpRequest('http://example.com')
}
const response = await backoff(work, { maxAttempts: Infinity })
}```
### debug log
This module uses [debug](https://github.com/visionmedia/debug) module. set `DEBUG=@kessler/exponential-backoff` to show debug messages.
### other stuff
This module is based on the [wikipedia article for exponential backoff](https://en.wikipedia.org/wiki/Exponential_backoff)
The use of the word _attempt_ is used in the code instead of _retry_ mostly because of the wikipedia article.
## license
[MIT](http://opensource.org/licenses/MIT) © Yaniv Kessler