|  |  | 
|  | /** | 
|  | * Expose `Backoff`. | 
|  | */ | 
|  |  | 
|  | module.exports = Backoff; | 
|  |  | 
|  | /** | 
|  | * Initialize backoff timer with `opts`. | 
|  | * | 
|  | * - `min` initial timeout in milliseconds [100] | 
|  | * - `max` max timeout [10000] | 
|  | * - `jitter` [0] | 
|  | * - `factor` [2] | 
|  | * | 
|  | * @param {Object} opts | 
|  | * @api public | 
|  | */ | 
|  |  | 
|  | function Backoff(opts) { | 
|  | opts = opts || {}; | 
|  | this.ms = opts.min || 100; | 
|  | this.max = opts.max || 10000; | 
|  | this.factor = opts.factor || 2; | 
|  | this.jitter = opts.jitter > 0 && opts.jitter <= 1 ? opts.jitter : 0; | 
|  | this.attempts = 0; | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Return the backoff duration. | 
|  | * | 
|  | * @return {Number} | 
|  | * @api public | 
|  | */ | 
|  |  | 
|  | Backoff.prototype.duration = function(){ | 
|  | var ms = this.ms * Math.pow(this.factor, this.attempts++); | 
|  | if (this.jitter) { | 
|  | var rand =  Math.random(); | 
|  | var deviation = Math.floor(rand * this.jitter * ms); | 
|  | ms = (Math.floor(rand * 10) & 1) == 0  ? ms - deviation : ms + deviation; | 
|  | } | 
|  | return Math.min(ms, this.max) | 0; | 
|  | }; | 
|  |  | 
|  | /** | 
|  | * Reset the number of attempts. | 
|  | * | 
|  | * @api public | 
|  | */ | 
|  |  | 
|  | Backoff.prototype.reset = function(){ | 
|  | this.attempts = 0; | 
|  | }; | 
|  |  | 
|  | /** | 
|  | * Set the minimum duration | 
|  | * | 
|  | * @api public | 
|  | */ | 
|  |  | 
|  | Backoff.prototype.setMin = function(min){ | 
|  | this.ms = min; | 
|  | }; | 
|  |  | 
|  | /** | 
|  | * Set the maximum duration | 
|  | * | 
|  | * @api public | 
|  | */ | 
|  |  | 
|  | Backoff.prototype.setMax = function(max){ | 
|  | this.max = max; | 
|  | }; | 
|  |  | 
|  | /** | 
|  | * Set the jitter | 
|  | * | 
|  | * @api public | 
|  | */ | 
|  |  | 
|  | Backoff.prototype.setJitter = function(jitter){ | 
|  | this.jitter = jitter; | 
|  | }; | 
|  |  |