Permalink
Browse files

retry() method

  • Loading branch information...
1 parent f43ee18 commit a1a4cb80be76643656fcfcb1ada323c91e424da5 @disfated disfated committed Jan 24, 2012
Showing with 83 additions and 10 deletions.
  1. +8 −2 README.md
  2. +25 −6 lib/restler.js
  3. +50 −2 test/restler.js
View
10 README.md
@@ -49,6 +49,7 @@ Basic method to make a request of any type. The function returns a RestRequest o
#### members
* `abort([error])` Cancels request. `abort` event is emitted. `request.aborted` is set to `true`. If non-falsy `error` is passed, then `error` will be additionaly emitted (with `error` passed as a param and `error.type` is set to `"abort"`). Otherwise only `complete` event will raise.
+* `retry([timeout])` Re-sends request after `timeout` ms. Pending request is aborted.
* `aborted` Determines if request was aborted.
@@ -121,8 +122,13 @@ Example usage
var sys = require('util'),
rest = require('./restler');
-rest.get('http://google.com').on('complete', function(data) {
- sys.puts(data);
+rest.get('http://google.com').on('complete', function(err, data) {
+ if (err) {
+ sys.puts('Error: ' + err.message);
+ this.retry(5000); // try again after 5 sec
+ } else {
+ sys.puts(data);
+ }
});
rest.get('http://twaud.io/api/v1/users/danwrong.json').on('complete', function(data) {
View
31 lib/restler.js
@@ -110,12 +110,11 @@ mixin(Request.prototype, {
_responseHandler: function(response) {
var self = this;
- if (this._isRedirect(response) && this.options.followRedirects) {
+ if (self._isRedirect(response) && self.options.followRedirects) {
try {
- var location = url.resolve(this.url, response.headers['location']);
- Request.call(this, location, this.options); // reusing request object to handle recursive redirects
+ self.url = url.parse(url.resolve(self.url.href, response.headers['location']));
+ self._retry();
// todo handle somehow infinite redirects
- this.run();
} catch(err) {
err.message = 'Failed to follow redirect: ' + err.message;
self._fireError(err, response);
@@ -212,6 +211,14 @@ mixin(Request.prototype, {
}
});
},
+ _retry: function() {
+ this.request.removeAllListeners().on('error', function() {});
+ if (this.request.finished) {
+ this.request.abort();
+ }
+ Request.call(this, this.url.href, this.options); // reusing request object to handle recursive calls and remember listeners
+ this.run();
+ },
run: function() {
var self = this;
@@ -254,6 +261,17 @@ mixin(Request.prototype, {
self.request.abort();
self.emit('abort', err);
return this;
+ },
+ retry: function(timeout) {
+ var self = this;
+ timeout = parseInt(timeout);
+ var fn = self._retry.bind(self);
+ if (!isFinite(timeout) || timeout <= 0) {
+ process.nextTick(fn, timeout);
+ } else {
+ setTimeout(fn, timeout);
+ }
+ return this;
}
});
@@ -266,8 +284,9 @@ function shortcutOptions(options, method) {
function request(url, options) {
var request = new Request(url, options);
- request.on('error', function() {});
- return request.run();
+ request.on('error', function() {});
+ process.nextTick(request.run.bind(request));
+ return request;
}
function get(url, options) {
View
52 test/restler.js
@@ -37,7 +37,7 @@ function setup(response) {
function teardown() {
return function (next) {
- this.server.close();
+ this.server._handle && this.server.close();
process.nextTick(next);
};
}
@@ -66,7 +66,9 @@ function echoResponse(request, response) {
'content-length': echo.length,
'request-method': request.method.toLowerCase()
});
- response.end(request.method == 'HEAD' ? undefined : echo);
+ setTimeout(function() {
+ response.end(request.method == 'HEAD' ? undefined : echo);
+ }, request.headers['x-delay'] | 0);
});
}
@@ -211,6 +213,52 @@ module.exports['Basic'] = {
test.ok(true);
test.done();
});
+ },
+
+ 'Should correctly retry': function(test) {
+ var counter = 0;
+ rest.get(host, { headers: { 'x-connection-abort': 'true' }}).on('complete', function() {
+ if (++counter < 3) {
+ this.retry(10);
+ } else {
+ test.ok(true);
+ test.done();
+ }
+ });
+ },
+
+ 'Should correctly retry after abort': function(test) {
+ var counter = 0;
+ rest.get(host).on('complete', function() {
+ if (++counter < 3) {
+ this.retry().abort();
+ } else {
+ test.ok(true);
+ test.done();
+ }
+ }).abort();
+ },
+
+ 'Should correctly retry while pending': function(test) {
+ var counter = 0, request;
+ function command() {
+ var args = [].slice.call(arguments);
+ var method = args.shift();
+ method && setTimeout(function() {
+ request[method]();
+ command.apply(null, args);
+ }, 50);
+ }
+
+ request = rest.get(host, { headers: { 'x-delay': '1000' } }).on('complete', function() {
+ if (++counter < 3) {
+ command('retry', 'abort');
+ } else {
+ test.ok(true);
+ test.done();
+ }
+ });
+ command('abort');
}
};

0 comments on commit a1a4cb8

Please sign in to comment.