UNPKG

2.22 kBJavaScriptView Raw
1/*
2 * Copyright (c) 2012 Mathieu Turcotte
3 * Licensed under the MIT license.
4 */
5
6var events = require('events');
7var util = require('util');
8
9/**
10 * Backoff driver.
11 * @param backoffStrategy Backoff delay generator/strategy.
12 * @constructor
13 */
14function Backoff(backoffStrategy) {
15 events.EventEmitter.call(this);
16
17 this.backoffStrategy_ = backoffStrategy;
18 this.maxNumberOfRetry_ = -1;
19 this.backoffNumber_ = 0;
20 this.backoffDelay_ = 0;
21 this.timeoutID_ = -1;
22
23 this.handlers = {
24 backoff: this.onBackoff_.bind(this)
25 };
26}
27util.inherits(Backoff, events.EventEmitter);
28
29/**
30 * Sets a limit, greater than 0, on the maximum number of backoffs. A 'fail'
31 * event will be emitted when the limit is reached.
32 * @param maxNumberOfRetry The maximum number of backoffs.
33 */
34Backoff.prototype.failAfter = function(maxNumberOfRetry) {
35 if (maxNumberOfRetry < 1) {
36 throw new Error('Maximum number of retry must be greater than 0. ' +
37 'Actual: ' + maxNumberOfRetry);
38 }
39
40 this.maxNumberOfRetry_ = maxNumberOfRetry;
41};
42
43/**
44 * Starts a backoff operation.
45 * @param err Optional paramater to let the listeners know why the backoff
46 * operation was started.
47 */
48Backoff.prototype.backoff = function(err) {
49 if (this.timeoutID_ !== -1) {
50 throw new Error('Backoff in progress.');
51 }
52
53 if (this.backoffNumber_ === this.maxNumberOfRetry_) {
54 this.emit('fail', err);
55 this.reset();
56 } else {
57 this.backoffDelay_ = this.backoffStrategy_.next();
58 this.timeoutID_ = setTimeout(this.handlers.backoff, this.backoffDelay_);
59 this.emit('backoff', this.backoffNumber_, this.backoffDelay_, err);
60 }
61};
62
63/**
64 * Handles the backoff timeout completion.
65 * @private
66 */
67Backoff.prototype.onBackoff_ = function() {
68 this.timeoutID_ = -1;
69 this.emit('ready', this.backoffNumber_, this.backoffDelay_);
70 this.backoffNumber_++;
71};
72
73/**
74 * Stops any backoff operation and resets the backoff delay to its inital
75 * value.
76 */
77Backoff.prototype.reset = function() {
78 this.backoffNumber_ = 0;
79 this.backoffStrategy_.reset();
80 clearTimeout(this.timeoutID_);
81 this.timeoutID_ = -1;
82};
83
84module.exports = Backoff;