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