| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158 | function RetryOperation(timeouts, options) {  // Compatibility for the old (timeouts, retryForever) signature  if (typeof options === 'boolean') {    options = { forever: options };  }  this._originalTimeouts = JSON.parse(JSON.stringify(timeouts));  this._timeouts = timeouts;  this._options = options || {};  this._maxRetryTime = options && options.maxRetryTime || Infinity;  this._fn = null;  this._errors = [];  this._attempts = 1;  this._operationTimeout = null;  this._operationTimeoutCb = null;  this._timeout = null;  this._operationStart = null;  if (this._options.forever) {    this._cachedTimeouts = this._timeouts.slice(0);  }}module.exports = RetryOperation;RetryOperation.prototype.reset = function() {  this._attempts = 1;  this._timeouts = this._originalTimeouts;}RetryOperation.prototype.stop = function() {  if (this._timeout) {    clearTimeout(this._timeout);  }  this._timeouts       = [];  this._cachedTimeouts = null;};RetryOperation.prototype.retry = function(err) {  if (this._timeout) {    clearTimeout(this._timeout);  }  if (!err) {    return false;  }  var currentTime = new Date().getTime();  if (err && currentTime - this._operationStart >= this._maxRetryTime) {    this._errors.unshift(new Error('RetryOperation timeout occurred'));    return false;  }  this._errors.push(err);  var timeout = this._timeouts.shift();  if (timeout === undefined) {    if (this._cachedTimeouts) {      // retry forever, only keep last error      this._errors.splice(this._errors.length - 1, this._errors.length);      this._timeouts = this._cachedTimeouts.slice(0);      timeout = this._timeouts.shift();    } else {      return false;    }  }  var self = this;  var timer = setTimeout(function() {    self._attempts++;    if (self._operationTimeoutCb) {      self._timeout = setTimeout(function() {        self._operationTimeoutCb(self._attempts);      }, self._operationTimeout);      if (self._options.unref) {          self._timeout.unref();      }    }    self._fn(self._attempts);  }, timeout);  if (this._options.unref) {      timer.unref();  }  return true;};RetryOperation.prototype.attempt = function(fn, timeoutOps) {  this._fn = fn;  if (timeoutOps) {    if (timeoutOps.timeout) {      this._operationTimeout = timeoutOps.timeout;    }    if (timeoutOps.cb) {      this._operationTimeoutCb = timeoutOps.cb;    }  }  var self = this;  if (this._operationTimeoutCb) {    this._timeout = setTimeout(function() {      self._operationTimeoutCb();    }, self._operationTimeout);  }  this._operationStart = new Date().getTime();  this._fn(this._attempts);};RetryOperation.prototype.try = function(fn) {  console.log('Using RetryOperation.try() is deprecated');  this.attempt(fn);};RetryOperation.prototype.start = function(fn) {  console.log('Using RetryOperation.start() is deprecated');  this.attempt(fn);};RetryOperation.prototype.start = RetryOperation.prototype.try;RetryOperation.prototype.errors = function() {  return this._errors;};RetryOperation.prototype.attempts = function() {  return this._attempts;};RetryOperation.prototype.mainError = function() {  if (this._errors.length === 0) {    return null;  }  var counts = {};  var mainError = null;  var mainErrorCount = 0;  for (var i = 0; i < this._errors.length; i++) {    var error = this._errors[i];    var message = error.message;    var count = (counts[message] || 0) + 1;    counts[message] = count;    if (count >= mainErrorCount) {      mainError = error;      mainErrorCount = count;    }  }  return mainError;};
 |