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