Skip to content

Commit

Permalink
GitHub auth: use token with the most remaining requests
Browse files Browse the repository at this point in the history
Part of #529.
  • Loading branch information
espadrine committed Jun 27, 2016
1 parent bfc6e7d commit de41847
Showing 1 changed file with 32 additions and 9 deletions.
41 changes: 32 additions & 9 deletions lib/github-auth.js
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@ function sendTokenToAllServers(token) {

// Track rate limit requests remaining.

// Ideally, we would want priority queues here.
var reqRemaining = new Map(); // From token to requests remaining.
var reqReset = new Map(); // From token to timestamp.

Expand All @@ -146,22 +147,44 @@ function utcEpochSeconds() {

var userTokenRateLimit = 12500;

// Return false if the token cannot reasonably be expected to perform
// a GitHub request.
function isTokenUsable(token, now) {
var reqs = reqRemaining.get(token);
var reset = reqReset.get(token);
// We don't want to empty more than 3/4 of a user's rate limit.
var hasRemainingReqs = reqs > (userTokenRateLimit / 4);
var isBeyondRateLimitReset = reset < now;
return hasRemainingReqs || isBeyondRateLimitReset;
}

// Return a list of tokens (as strings) which can be used for a GitHub request,
// with a reasonable chance that the request will succeed.
function usableTokens() {
var now = utcEpochSeconds();
return githubUserTokens.data.filter(function(token) {
return isTokenUsable(token, now);
});
}

// Retrieve a user token if there is one for which we believe there are requests
// remaining. Return undefined if we could not find one.
function getReqRemainingToken() {
// Go through the user tokens.
// Keep the first one which is usable or has reset.
var now = utcEpochSeconds();
for (var token of reqReset.keys()) {
// Among usable ones, use the one with the highest number of remaining
// requests.
var tokens = usableTokens();
var highestReq = -1;
var highestToken;
for (var i = 0; i < tokens.length; i++) {
var token = tokens[i];
var reqs = reqRemaining.get(token);
var reset = reqReset.get(token);
// We don't want to empty more than 3/4 of a user's rate limit.
var hasRemainingReqs = reqs > (userTokenRateLimit / 4);
var isBeyondRateLimitReset = reset < now;
if (hasRemainingReqs || isBeyondRateLimitReset) {
return token;
if (reqs > highestReq) {
highestReq = reqs;
highestToken = token;
}
}
return highestToken;
}

function addGithubToken(token) {
Expand Down

0 comments on commit de41847

Please sign in to comment.