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;
- };
|