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.
		
		
		
		
		
			
		
			
				
					101 lines
				
				2.3 KiB
			
		
		
			
		
	
	
					101 lines
				
				2.3 KiB
			| 
								 
											2 years ago
										 
									 | 
							
								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;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								};
							 |