src/lib/backoff-wrapper.js
- import {EventEmitter} from 'events'
- import ExponentialBackoffStrategy from 'backoff/lib/strategy/exponential'
-
- /*
- This is heavily based on:
- https://github.com/MathieuTurcotte/node-backoff/blob/master/lib/backoff.js
-
- ...which holds the following 2-line copyright notice:
- Copyright (c) 2012 Mathieu Turcotte
- Licensed under the MIT license.
-
- This is a very bare-bones version of the file above
- */
-
- /**
- * A wrapper over the ExponentialBackoffStrategy from the backoff module.
- */
- export default class ExponentialBackoff extends EventEmitter {
- /**
- * Constructor.
- */
- constructor() {
- super()
-
- /**
- * ExponentialBackoffStrategy instance.
- * @type {ExponentialBackoffStrategy}
- */
- this._strategy = new ExponentialBackoffStrategy({
- randomisationFactor: 0.3,
- initialDelay: 1000,
- maxDelay: 60000
- })
-
- /**
- * Number of previous failed attempts.
- * @type {Number}
- */
- this._backoffNumber = 0
-
- /**
- * Backoff timeout ID.
- * @type {TimeoutID}
- */
- this._timeoutID = undefined
- }
-
- /**
- * Signals that we tried executing the protected routine and failed, or that we want to start the process.
- * @emits backoff(_backoffNumber, delay) delay is how much time will pass before we try executing the routine.
- */
- backoff() {
- // Backoff already in progress
- if (this._timeoutID) {
- return
- }
-
- const delay = this._strategy.next()
- this._timeoutID = setTimeout(() => {
- this._timeoutID = undefined
- this.emit('retry', this._backoffNumber)
- this._backoffNumber++
- }, delay)
- this.emit('backoff', this._backoffNumber, delay)
- }
-
- /**
- * Resets failed attempt number and cancels a possible pending action (routine execution after backoff).
- */
- reset() {
- // Reset number of backoffs
- this._backoffNumber = 0
-
- // Reset strategy
- this._strategy.reset()
-
- // Clear a possibly running timeout
- if (this._timeoutID !== undefined) {
- clearTimeout(this._timeoutID)
- this._timeoutID = undefined
- }
- }
-
- /**
- * Used to signal the routine was successful.
- * This resets the wrapper.
- * @emits success
- * @see {@link reset}
- */
- success() {
- // Reset state
- this.reset()
-
- // Alert everyone we did it (for now at least)
- this.emit('success')
- }
- }