Skip to content

Commit e72edee

Browse files
authored
Merge pull request #94 from OleksiiSliusarenko/master
Possibility to overwrite `options` in retry strategy
2 parents 52e45de + 731c712 commit e72edee

4 files changed

Lines changed: 86 additions & 11 deletions

File tree

README.md

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,13 +113,30 @@ A retry strategy let you specify when request-retry should retry a request
113113
* @param {Null | Object} err
114114
* @param {Object} response
115115
* @param {Object} body
116+
* @param {Object} options copy
116117
* @return {Boolean} true if the request should be retried
117118
*/
118-
function myRetryStrategy(err, response, body){
119+
function myRetryStrategy(err, response, body, options){
119120
// retry the request if we had an error or if the response was a 'Bad Gateway'
120121
return err || response.statusCode === 502;
121122
}
122123

124+
/**
125+
* @param {Null | Object} err
126+
* @param {Object} response
127+
* @param {Object} body
128+
* @param {Object} options copy
129+
* @return {Object} mustRetry: {Boolean} true if the request should be retried
130+
* options: {Object} new options for request
131+
*/
132+
function myRetryStrategy(err, response, body, options){
133+
options.url = 'new url'; //you can overwrite some attributes or create new object
134+
return {
135+
mustRetry: err || response.statusCode === 502,
136+
options: options, //then it should be passed back, it will be used for new requests
137+
}
138+
}
139+
123140
request({
124141
url: 'https://api.domain.com/v1/a/b'
125142
json:true,

index.js

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ function Request(url, options, f, retryConfig) {
8080

8181
/**
8282
* Return true if the request should be retried
83-
* @type {Function} (err, response) -> Boolean
83+
* @type {Function} (err, response, body, options) -> [Boolean, Object (optional)]
8484
*/
8585
this.retryStrategy = _.isFunction(options.retryStrategy) ? options.retryStrategy : RetryStrategies.HTTPOrNetworkError;
8686

@@ -130,7 +130,15 @@ Request.prototype._tryUntilFail = function () {
130130
err.attempts = this.attempts;
131131
}
132132

133-
if (this.retryStrategy(err, response, body) && this.maxAttempts > 0) {
133+
var mustRetry = this.retryStrategy(err, response, body, _.cloneDeep(this.options));
134+
if (_.isObject(mustRetry)) {
135+
if (_.isObject(mustRetry.options)) {
136+
this.options = mustRetry.options; //if retryStrategy supposes different request options for retry
137+
}
138+
mustRetry = mustRetry.mustRetry;
139+
}
140+
141+
if (mustRetry && this.maxAttempts > 0) {
134142
this._timeout = setTimeout(this._tryUntilFail.bind(this), this.delayStrategy.call(this, err, response, body));
135143
return;
136144
}

test/attempts.test.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ describe('Request attempts', function () {
3838
});
3939

4040
it('should call delay strategy 2 times after some retries', function (done) {
41+
this.timeout(3000);
4142
var mockDelayStrategy = sinon.stub().returns(500);
4243
var startTime = process.hrtime();
4344
request({

test/strategies.test.js

Lines changed: 57 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,66 @@ var request = require('../');
44
var t = require('chai').assert;
55

66
describe('RetryStrategies', function () {
7-
it('should have a strategy `HTTPError` to only retry on HTTP errors', function () {
8-
checkHTTPErrors(request.RetryStrategies.HTTPError);
9-
});
107

11-
it('should have a strategy `NetworkError` to only retry on nodejs network errors', function () {
12-
checkNetworkErrors(request.RetryStrategies.NetworkError, request.RetryStrategies.NetworkError.RETRIABLE_ERRORS);
8+
describe('Default strategies', function () {
9+
it('should have a strategy `HTTPError` to only retry on HTTP errors', function () {
10+
checkHTTPErrors(request.RetryStrategies.HTTPError);
11+
});
12+
13+
it('should have a strategy `NetworkError` to only retry on nodejs network errors', function () {
14+
checkNetworkErrors(request.RetryStrategies.NetworkError, request.RetryStrategies.NetworkError.RETRIABLE_ERRORS);
15+
});
16+
17+
it('should have a strategy `HTTPOrNetworkError` to only retry on nodejs network and HTTP errors', function () {
18+
checkHTTPErrors(request.RetryStrategies.HTTPOrNetworkError);
19+
checkNetworkErrors(request.RetryStrategies.HTTPOrNetworkError, request.RetryStrategies.NetworkError.RETRIABLE_ERRORS);
20+
});
1321
});
1422

15-
it('should have a strategy `HTTPOrNetworkError` to only retry on nodejs network and HTTP errors', function () {
16-
checkHTTPErrors(request.RetryStrategies.HTTPOrNetworkError);
17-
checkNetworkErrors(request.RetryStrategies.HTTPOrNetworkError, request.RetryStrategies.NetworkError.RETRIABLE_ERRORS);
23+
describe('Custom strategies', function () {
24+
it('should overwrite `options` object if strategy returned it', function (done) {
25+
var strategy = function (err, response, body, options) {
26+
options.url = 'http://www.filltext.com/?rows=1&err=200'; //overwrite url to return 200
27+
return {
28+
mustRetry: true,
29+
options: options,
30+
};
31+
};
32+
33+
request({
34+
url: 'http://www.filltext.com/?rows=1&err=500', // returns a 500 status
35+
maxAttempts: 3,
36+
retryDelay: 100,
37+
retryStrategy: strategy
38+
}, function(err, response, body) {
39+
if(err) done(err);
40+
41+
t.strictEqual(200, response.statusCode);
42+
done();
43+
});
44+
});
45+
46+
it('should not overwrite `options` object if strategy did not returned it', function (done) {
47+
var strategy = function (err, response, body, options) {
48+
options.url = 'http://www.filltext.com/?rows=1&err=200'; //overwrite url to return 200
49+
//do not return `options`
50+
return {
51+
mustRetry: true,
52+
};
53+
};
54+
55+
request({
56+
url: 'http://www.filltext.com/?rows=1&err=500', // returns a 500 status
57+
maxAttempts: 3,
58+
retryDelay: 100,
59+
retryStrategy: strategy
60+
}, function(err, response, body) {
61+
if(err) done(err);
62+
63+
t.strictEqual(500, response.statusCode);
64+
done();
65+
});
66+
})
1867
});
1968
});
2069

0 commit comments

Comments
 (0)