Skip to content

Commit

Permalink
Add incremental wait time for subsequent request retries
Browse files Browse the repository at this point in the history
  • Loading branch information
corycaywood committed Mar 17, 2017
1 parent 9231097 commit 954f5ef
Show file tree
Hide file tree
Showing 2 changed files with 28 additions and 1 deletion.
8 changes: 7 additions & 1 deletion lib/zendesk-uploader/client-wrapper.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ const logger = require('../logger');
* Wrapper class for the `node-zendesk` api client
* Wraps all requests in the `articles`, `sections`, `categories`, and `accesspolcies` objects in Promises
* Also wraps requests with a retry functionality that will retry the request if the error response is >= 500 or contains a `retryAfter` property
* Subsequent retries without a "retry-after" header will wait twice as long as the last retry before trying the request again
*/

const MAX_RETRIES = 5;
Expand Down Expand Up @@ -57,6 +58,7 @@ module.exports = class ZendeskClientWrapper {

_createPromiseRequest() {
let retries = MAX_RETRIES;
let retryNumber = 0;
// First param is the method to call - subsequent params will be passed to the method
const args = [].slice.call(arguments);
const method = args.shift();
Expand All @@ -68,7 +70,11 @@ module.exports = class ZendeskClientWrapper {
// err.retryAfter is present on all 429 (rate limit has been exceeded) and some 503 errors
// err.retryAfter is time to wait in seconds
retries--;
let retryAfter = err.retryAfter ? err.retryAfter * 1000 : RETRY_AFTER_DEFAULT;
retryNumber++;
const retryAfter = err.retryAfter
? err.retryAfter * 1000
// Default retry should wait twice as long as the previous retry
: RETRY_AFTER_DEFAULT * Math.max(Math.pow(2, retryNumber - 1), 1);
setTimeout(() => method.apply(this, args), retryAfter);

logger.warn(`Zendesk request failed. Retrying request after ${retryAfter} milliseconds. ${retries} attempts are remaining.`);
Expand Down
21 changes: 21 additions & 0 deletions test/unit/zendesk-uploader/client-wrapper.js
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,27 @@ describe('ZendeskClientWrapper', () => {
});
});

it('should retry after twice as long as the last retry for the request when there are subsequent 500 errors', () => {
const stub = sandbox.stub(this.zendeskStub.articles, 'create');
stub.yields(null, null, {});
stub.onFirstCall().yields({statusCode: 503});
stub.onSecondCall().yields({statusCode: 503});
stub.onThirdCall().yields({statusCode: 503});

let clock = sandbox.useFakeTimers();
let createArticle = this.zendeskClient.articles.create(123, {});

expect(stub).to.have.been.calledOnce;
clock.tick(500);
expect(stub).to.have.been.calledTwice;
clock.tick(1000);
expect(stub).to.have.been.calledThrice;
clock.tick(2000);
return createArticle.then(() => {
expect(stub.callCount).to.be.equal(4);
});
});

it('should reject the promise if the request fails after 5 retries', () => {
const stub = sandbox.stub(this.zendeskStub.articles, 'create')
.yields({retryAfter: 0.01});
Expand Down

0 comments on commit 954f5ef

Please sign in to comment.