Comparing version 0.0.1-3 to 0.0.1-4
82
main.js
@@ -1,22 +0,7 @@ | ||
var re = Re(options); | ||
re.try(function(retryCount, fail, callback){ | ||
request.get(options, function(err, response, xml){ | ||
// TODO: check if we got a 503 response before trying to parse | ||
parser.parseString(xml, function(err, result){ | ||
if(err){ | ||
return fail(err); | ||
} else { | ||
return callback(err, result, depth); | ||
} | ||
}); | ||
}); | ||
}, callback); | ||
exports.RETRY_STRATEGY = RETRY_STRATEGY = {CONSTANT: 0, EXPONENTIAL: 1, LINEAR: 2}; | ||
var RETRIES_DEFAULT = 4, | ||
EXP_STRAT_DEFAULT = {"type": RETRY_STRATEGY.EXPONENTIAL, "multiplier":300, "base":3}; | ||
CONST_STRAT_DEFAULT = {"type": RETRY_STRATEGY.CONSTANT, "constant":400}; | ||
LINEAR_STRAT_DEFAULT = {"type": RETRY_STRATEGY.LINEAR, "multiplier": 200}; | ||
var RETRIES_DEFAULT = 10, | ||
EXP_STRAT_DEFAULT = {"type": RETRY_STRATEGY.EXPONENTIAL, "initial":100, "base":2}; | ||
CONST_STRAT_DEFAULT = {"type": RETRY_STRATEGY.CONSTANT, "initial":400}; | ||
LINEAR_STRAT_DEFAULT = {"type": RETRY_STRATEGY.LINEAR, "initial": 100}; | ||
@@ -42,13 +27,13 @@ exports.Re = function Re(options){ | ||
case RETRY_STRATEGY.CONSTANT: | ||
if(typeof retryStrategy.constant === "undefined") retryStrategy.constant = CONSTANT_DEFAULT; | ||
this.retryInterval = createLinearRetry(retryStrategy.constant); | ||
if(typeof retryStrategy.initial === "undefined") retryStrategy.initial = CONST_STRAT_DEFAULT.initial; | ||
this.retryInterval = createLinearRetry(retryStrategy); | ||
break; | ||
case RETRY_STRATEGY.EXPONENTIAL: | ||
if(typeof retryStrategy.multiplier === "undefined") retryStrategy.multiplier = EXP_MULT_DEFAULT; | ||
if(typeof retryStrategy.base === "undefined") retryStrategy.base = EXP_BASE_DEFAULT; | ||
this.retryInterval = createExponentialRetry(retryStrategy.multiplier, retryStrategy.base); | ||
if(typeof retryStrategy.initial === "undefined") retryStrategy.initial = EXP_STRAT_DEFAULT.initial; | ||
if(typeof retryStrategy.base === "undefined") retryStrategy.base = EXP_STRAT_DEFAULT.base; | ||
this.retryInterval = createExponentialRetry(retryStrategy); | ||
break; | ||
case RETRY_STRATEGY.LINEAR: | ||
if(typeof retryStrategy.multiplier === "undefined") retryStrategy.multiplier = LINEAR_DEFAULT; | ||
this.retryInterval = createLinearRetry(retryStrategy.multiplier); | ||
if(typeof retryStrategy.initial === "undefined") retryStrategy.initial = LINEAR_STRAT_DEFAULT.initial; | ||
this.retryInterval = createLinearRetry(retryStrategy); | ||
break; | ||
@@ -67,5 +52,3 @@ default: | ||
try{ | ||
operation(self.retry, | ||
fail, | ||
callback); | ||
operation(self.retry, fail, callback); | ||
} catch(err) { | ||
@@ -76,12 +59,20 @@ fail(err); | ||
function Re.prototype.do(operation, callback){ | ||
var fail = createFailCallback(operation, callback); | ||
callback = callback || function () {}; | ||
operation(self.retry, fail, callback); | ||
} | ||
var createFailCallback = function(operation, callback){ | ||
return function(err){ | ||
var self = this, | ||
self.retry++; | ||
fail = createFailCallback(operation, callback); | ||
self.retry++; | ||
if(this.retry < this.maxRetries){ | ||
setTimeout(function(){ | ||
operation(self.retry, | ||
createFailCallback(operation, callback), | ||
callback); | ||
operation(self.retry, fail, callback); | ||
}, | ||
@@ -95,18 +86,31 @@ self.retryInterval(self.retry)); | ||
createExponentialRetry = function(multiplier, base){ | ||
createExponentialRetry = function(spec){ | ||
return function(retries){ | ||
return multiplier * Math.pow(base, retries); | ||
var spread = spec.rand ? Math.random() + 1 : 1, | ||
initial = spec.initial, | ||
base = spec.base, | ||
max = spec.max, | ||
full = spread * initial * Math.pow(base, retries); | ||
return max ? Math.min(full, max) : full; | ||
}; | ||
}; | ||
createLinearRetry = function(multiplier){ | ||
createLinearRetry = function(spec){ | ||
return function(retries){ | ||
return multiplier*(retries+1); | ||
var spread = spec.rand ? Math.random() + 1 : 1, | ||
initial = spec.initial, | ||
max = spec.max, | ||
full = spread*initial*(retries+1); | ||
return max ? Math.min(full, max) : full; | ||
}; | ||
}; | ||
createConstantRetry = function(interval){ | ||
createConstantRetry = function(spec){ | ||
return function(){ | ||
return interval; | ||
var spread = spec.rand ? Math.random() + 1 : 1, | ||
initial = spec.initial; | ||
return spread*initial; | ||
}; | ||
}; |
{ | ||
"name": "re", | ||
"version": "0.0.1-3", | ||
"version": "0.0.1-4", | ||
"description": "Do it again, after a bit.", | ||
"tags": ["utility", "data", "util", "utility"], | ||
"tags": ["utility", "retry", "exponential backoff", "linear backoff"], | ||
"author": "Waylon Flinn <waylonflinn@gmail.com>", | ||
@@ -7,0 +7,0 @@ "engines":{ |
@@ -5,4 +5,4 @@ # Re | ||
retry strategies, including: constant, exponential backoff and linear backoff. | ||
Functions are styled after the async library. | ||
Functions are styled after the `async` library. | ||
@@ -54,2 +54,5 @@ ## Install | ||
The `re.do` function is like `re.try` expect it doesn't wrap your operation in | ||
a `try...catch`. | ||
## Options | ||
@@ -60,4 +63,4 @@ | ||
var options = { | ||
retries : 4, | ||
retryStrategy : {"type": RETRY_STRATEGY.EXPONENTIAL, "multiplier":300, "base":3}, | ||
retries : 10, | ||
retryStrategy : {"type": retry.RETRY_STRATEGY.EXPONENTIAL, "initial":100, "base":2}, | ||
} | ||
@@ -69,3 +72,4 @@ | ||
This gives you 4 retries and an exponential backoff strategy with the following progression (in milliseconds): 300, 900, 2700, 8100. | ||
This gives you 10 retries and an exponential backoff strategy with the following progression (in milliseconds): 100, 200, | ||
400, 800, 1600, 3200, 6400, 12800, 25600, 51200 | ||
@@ -76,8 +80,12 @@ ### Retry Strategy Examples | ||
{"type": RETRY_STRATEGY.CONSTANT, "constant": 400} | ||
{"type": retry.RETRY_STRATEGY.CONSTANT, "initial": 400} | ||
The following will give a linear backoff strategy that has the following progress (when paired with `retries: 4`) : 200, 400, 600, 800 | ||
The following will give a linear backoff strategy that has the following progress (when paired with `retries: 10`) : 200, 400, 600, 800, 1000, 1200, 1400, 1600, 1800, 1800 | ||
{"type": RETRY_STRATEGY.LINEAR, "multiplier": 200} | ||
{"type": retry.RETRY_STRATEGY.LINEAR, "initial": 200, "max":1800} | ||
Both progressive strategies take the `max` option. All strategies also take a `rand` option. This is a `Boolean` that adds a random multiplier between 1 and 2. This makes them act like the tradition backoff function described here: | ||
[Exponential Backoff in Distributed Systems](http://dthain.blogspot.com/2009/02/exponential-backoff-in-distributed.html). | ||
This parameter is set to `false` by default. | ||
6594
87