You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
100 lines
2.3 KiB
100 lines
2.3 KiB
var RetryOperation = require('./retry_operation'); |
|
|
|
exports.operation = function(options) { |
|
var timeouts = exports.timeouts(options); |
|
return new RetryOperation(timeouts, { |
|
forever: options && (options.forever || options.retries === Infinity), |
|
unref: options && options.unref, |
|
maxRetryTime: options && options.maxRetryTime |
|
}); |
|
}; |
|
|
|
exports.timeouts = function(options) { |
|
if (options instanceof Array) { |
|
return [].concat(options); |
|
} |
|
|
|
var opts = { |
|
retries: 10, |
|
factor: 2, |
|
minTimeout: 1 * 1000, |
|
maxTimeout: Infinity, |
|
randomize: false |
|
}; |
|
for (var key in options) { |
|
opts[key] = options[key]; |
|
} |
|
|
|
if (opts.minTimeout > opts.maxTimeout) { |
|
throw new Error('minTimeout is greater than maxTimeout'); |
|
} |
|
|
|
var timeouts = []; |
|
for (var i = 0; i < opts.retries; i++) { |
|
timeouts.push(this.createTimeout(i, opts)); |
|
} |
|
|
|
if (options && options.forever && !timeouts.length) { |
|
timeouts.push(this.createTimeout(i, opts)); |
|
} |
|
|
|
// sort the array numerically ascending |
|
timeouts.sort(function(a,b) { |
|
return a - b; |
|
}); |
|
|
|
return timeouts; |
|
}; |
|
|
|
exports.createTimeout = function(attempt, opts) { |
|
var random = (opts.randomize) |
|
? (Math.random() + 1) |
|
: 1; |
|
|
|
var timeout = Math.round(random * Math.max(opts.minTimeout, 1) * Math.pow(opts.factor, attempt)); |
|
timeout = Math.min(timeout, opts.maxTimeout); |
|
|
|
return timeout; |
|
}; |
|
|
|
exports.wrap = function(obj, options, methods) { |
|
if (options instanceof Array) { |
|
methods = options; |
|
options = null; |
|
} |
|
|
|
if (!methods) { |
|
methods = []; |
|
for (var key in obj) { |
|
if (typeof obj[key] === 'function') { |
|
methods.push(key); |
|
} |
|
} |
|
} |
|
|
|
for (var i = 0; i < methods.length; i++) { |
|
var method = methods[i]; |
|
var original = obj[method]; |
|
|
|
obj[method] = function retryWrapper(original) { |
|
var op = exports.operation(options); |
|
var args = Array.prototype.slice.call(arguments, 1); |
|
var callback = args.pop(); |
|
|
|
args.push(function(err) { |
|
if (op.retry(err)) { |
|
return; |
|
} |
|
if (err) { |
|
arguments[0] = op.mainError(); |
|
} |
|
callback.apply(this, arguments); |
|
}); |
|
|
|
op.attempt(function() { |
|
original.apply(obj, args); |
|
}); |
|
}.bind(obj, original); |
|
obj[method].options = options; |
|
} |
|
};
|
|
|