Skip to content

Commit

Permalink
[v1.0.0] stable release, support for .abort()
Browse files Browse the repository at this point in the history
  • Loading branch information
FGRibreau committed Mar 26, 2014
1 parent b6ac75f commit f235ed9
Show file tree
Hide file tree
Showing 4 changed files with 71 additions and 21 deletions.
5 changes: 3 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ request({
maxAttempts: 5, // (default) try 5 times
retryDelay: 5000 // (default) wait for 5s before trying again
}, function(err, response, body){
// this callback will only be called when the request succeeded or after maxAttempts.
// this callback will only be called when the request succeeded or after maxAttempts or on error
});
```

Expand All @@ -37,6 +37,7 @@ Install with [npm](https://npmjs.org/package/requestretry).

## Changelog

v1.0.0: Initial commit
v1.0.0: request now yield an Request instance with a `.abort()` method.
v0.0.1: Initial commit

Copyright 2014, [Francois-Guillaume Ribreau](http://fgribreau.com) (npm@fgribreau.com)
61 changes: 43 additions & 18 deletions index.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
'use strict';

/*
* retriablerequest
* Request
*
* Copyright(c) 2014 Francois-Guillaume Ribreau <npm@fgribreau.com>
* MIT Licensed
*
*/
var request = require('request');
var _ = require('fg-lodash');
var request = require('request');
var _ = require('fg-lodash');
var Cancelable = require('cancelable');

var RETRIABLE_ERRORS = ['ECONNRESET', 'ENOTFOUND', 'ESOCKETTIMEDOUT', 'ETIMEDOUT', 'ECONNREFUSED'];

Expand All @@ -17,26 +18,50 @@ var DEFAULTS = {
retryDelay: 5000, // wait for 5s before trying again
};

function isRetriableRequest(err, response){
// Inspired from https://github.com/geoffreak/request-enhanced/blob/master/src/request-enhanced.coffee#L107
return (err && _.contains(RETRIABLE_ERRORS, err.code)) || (response && 500 <= response.statusCode && response.statusCode < 600);
function Request(options, f, maxAttempts, retryDelay){
this.maxAttempts = maxAttempts;
this.retryDelay = retryDelay;
this.options = options;
this.f = _.once(f);
this._timeout = null;
this._req = null;
}

function tryUntilFail(options, f, retryOptions){
retryOptions.maxAttempts--;
Request.request = request;

Request.prototype._tryUntilFail = function(){
this.maxAttempts--;

request(options, function(err, response, body){
if(isRetriableRequest(err, response) && retryOptions.maxAttempts >= 0){
return setTimeout(tryUntilFail.bind(null, options, f, retryOptions), retryOptions.retryDelay);
this._req = Request.request(this.options, function(err, response, body){
if(this._isRetriable(err, response) && this.maxAttempts >= 0){
this._timeout = setTimeout(this._tryUntilFail.bind(this), this.retryDelay);
return;
}

return f(err, response, body);
});
}
return this.f(err, response, body);
}.bind(this));
};

Request.prototype._isRetriable = function(err, response){
// Inspired from https://github.com/geoffreak/request-enhanced/blob/master/src/request-enhanced.coffee#L107
return (err && _.contains(RETRIABLE_ERRORS, err.code)) || (response && 500 <= response.statusCode && response.statusCode < 600);
};

function RetriableRequest(options, f){
var retryOptions = _(options || {}).defaults(DEFAULTS).pick(Object.keys(DEFAULTS)).value();
tryUntilFail(options, f, retryOptions);
Request.prototype.abort = function(){
if(this._req){
this._req.abort();
}
clearTimeout(this._timeout);
this.f(new Error('Aborted'));
};

function Factory(options, f){
var retry = _(options || {}).defaults(DEFAULTS).pick(Object.keys(DEFAULTS)).value();
var req = new Request(options, f, retry.maxAttempts, retry.retryDelay);
req._tryUntilFail();
return req;
}

module.exports = RetriableRequest;
module.exports = Factory;

Factory.Request = Request;
6 changes: 5 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
"email": "npm@fgribreau.com",
"url": "http://fgribreau.com"
},
"version": "0.0.1",
"version": "1.0.0",
"repository": {
"url": "https://github.com/FGRibreau/node-request-retry"
},
Expand All @@ -15,5 +15,9 @@
"dependencies": {
"fg-lodash": "0.0.1",
"request": "~2.34.0"
},
"devDependencies": {
"chai": "~1.9.1",
"mocha": "~1.18.2"
}
}
20 changes: 20 additions & 0 deletions test/abort.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
'use strict';

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

describe('Request-retry', function () {

it('should return a RequestRetry handler object with a abort method', function (done) {
var start = +new Date();
var o = request({
url: 'http://filltext.com/?rows=1&delay=10', // wait for 4s
json:true
}, function(err){
t.strictEqual(err.toString(), 'Error: Aborted');
done();
});

o.abort();
});
});

0 comments on commit f235ed9

Please sign in to comment.