Skip to content

Commit

Permalink
retry() method
Browse files Browse the repository at this point in the history
  • Loading branch information
disfated committed Jan 24, 2012
1 parent f43ee18 commit a1a4cb8
Show file tree
Hide file tree
Showing 3 changed files with 83 additions and 10 deletions.
10 changes: 8 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.


Expand Down Expand Up @@ -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) {
Expand Down
31 changes: 25 additions & 6 deletions lib/restler.js
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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;

Expand Down Expand Up @@ -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;
}
});

Expand All @@ -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) {
Expand Down
52 changes: 50 additions & 2 deletions test/restler.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ function setup(response) {

function teardown() {
return function (next) {
this.server.close();
this.server._handle && this.server.close();
process.nextTick(next);
};
}
Expand Down Expand Up @@ -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);
});
}

Expand Down Expand Up @@ -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');
}

};
Expand Down

0 comments on commit a1a4cb8

Please sign in to comment.