|
|
- var RetryOperation = require('./retry_operation');
-
- exports.operation = function(options) {
- var timeouts = exports.timeouts(options);
- return new RetryOperation(timeouts, {
- forever: options && options.forever,
- 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 * opts.minTimeout * 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;
- }
- };
|