Skip to content

Commit

Permalink
Add delay strategy
Browse files Browse the repository at this point in the history
  • Loading branch information
Osbert Orr authored and oztheozoz committed Sep 6, 2016
1 parent 85b63ad commit ce99e46
Show file tree
Hide file tree
Showing 4 changed files with 49 additions and 1 deletion.
22 changes: 22 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,28 @@ request({
});
```

## How to define your own delay strategy

```
/**
* @param {Null | Object} err
* @param {Object} response
* @return {Number} number of milliseconds to delay
*/
function myDelayStrategy(err, response, body){
// set delay of retry to a random number between 500 and 3500 ms
return Math.floor(Math.random() * (3500 - 500 + 1) + 500);
}
request({
url: 'https://api.domain.com/v1/a/b'
json:true,
delayStrategy: myDelayStrategy // delayStrategy is called 1 less times than the maxAttempts set
}, function(err, response, body){
// this callback will only be called when the request succeeded or after maxAttempts or on error
});
```

## Modifying `request` options

You can use the `defaults` method to provide default options like so:
Expand Down
3 changes: 2 additions & 1 deletion index.js
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ function Request(options, f, retryConfig) {
* @type {Function} (err, response) -> Boolean
*/
this.retryStrategy = _.isFunction(options.retryStrategy) ? options.retryStrategy : RetryStrategies.HTTPOrNetworkError;
this.delayStrategy = _.isFunction(options.delayStrategy) ? options.delayStrategy : function() { return this.retryDelay; };

this._timeout = null;
this._req = null;
Expand Down Expand Up @@ -99,7 +100,7 @@ Request.prototype._tryUntilFail = function () {
response.attempts = this.attempts;
}
if (this.retryStrategy(err, response, body) && this.maxAttempts > 0) {
this._timeout = setTimeout(this._tryUntilFail.bind(this), this.retryDelay);
this._timeout = setTimeout(this._tryUntilFail.bind(this), this.delayStrategy.call(this, err, response, body));
return;
}

Expand Down
5 changes: 5 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@
{
"name": "juliendangers",
"email": "[email protected]"
},
{
"name": "Osbert Orr",
"email": "[email protected]"
}
],
"repository": {
Expand Down Expand Up @@ -41,6 +45,7 @@
"nock": "^8.0.0",
"q": "~1.4.1",
"rsvp": "^3.2.1",
"sinon": "1.17.5",
"updtr": "^0.2.1"
}
}
20 changes: 20 additions & 0 deletions test/attempts.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

var request = require('../');
var t = require('chai').assert;
var sinon = require('sinon');

describe('Request attempts', function () {
it('should show 1 attempt after a successful call', function (done) {
Expand All @@ -23,4 +24,23 @@ describe('Request attempts', function () {
done();
});
});

it('should call delay strategy 2 times after some retries', function (done) {
var mockDelayStrategy = sinon.stub().returns(500);
var startTime = process.hrtime();
request({
url: 'http://www.filltext.com/?rows=1&err=500', // return a 500 status
maxAttempts: 3,
retryDelay: 1000000, // Set to large delay to prove it will not be used
delayStrategy: mockDelayStrategy
}, function (err, response, body) {
var endTime = process.hrtime(startTime); // process.hrtime returns an array [seconds, nanoseconds]
var timeDiff = endTime[0] * 1000 + endTime[1]/1000000;

t.isAtLeast(timeDiff, 1000, 'delayStrategy\'s return value was not used or was used incorrectly');
t.isTrue(mockDelayStrategy.calledTwice, 'mockDelayStrategy was called an incorrect amount of times'); // reason it's called 2 and not 3 times is because there is no delay for the first call
done();
});
});
});

0 comments on commit ce99e46

Please sign in to comment.