GitHub auth: use token with the most remaining requests

Part of #529.
This commit is contained in:
Thaddee Tyl 2016-06-27 20:04:57 +02:00
parent bfc6e7d863
commit a7cfac6e93

View File

@ -124,6 +124,7 @@ function sendTokenToAllServers(token) {
// Track rate limit requests remaining. // Track rate limit requests remaining.
// Ideally, we would want priority queues here.
var reqRemaining = new Map(); // From token to requests remaining. var reqRemaining = new Map(); // From token to requests remaining.
var reqReset = new Map(); // From token to timestamp. var reqReset = new Map(); // From token to timestamp.
@ -146,26 +147,49 @@ function utcEpochSeconds() {
var userTokenRateLimit = 12500; var userTokenRateLimit = 12500;
// Retrieve a user token if there is one for which we believe there are requests // Return false if the token cannot reasonably be expected to perform
// remaining. Return undefined if we could not find one. // a GitHub request.
function getReqRemainingToken() { function isTokenUsable(token, now) {
// Go through the user tokens.
// Keep the first one which is usable or has reset.
var now = utcEpochSeconds();
for (var token of reqReset.keys()) {
var reqs = reqRemaining.get(token); var reqs = reqRemaining.get(token);
var reset = reqReset.get(token); var reset = reqReset.get(token);
// We don't want to empty more than 3/4 of a user's rate limit. // We don't want to empty more than 3/4 of a user's rate limit.
var hasRemainingReqs = reqs > (userTokenRateLimit / 4); var hasRemainingReqs = reqs > (userTokenRateLimit / 4);
var isBeyondRateLimitReset = reset < now; var isBeyondRateLimitReset = reset < now;
if (hasRemainingReqs || isBeyondRateLimitReset) { return hasRemainingReqs || isBeyondRateLimitReset;
return token; }
// 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.
// 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);
if (reqs > highestReq) {
highestReq = reqs;
highestToken = token;
} }
} }
return highestToken;
} }
function addGithubToken(token) { function addGithubToken(token) {
setReqRemaining(token, 0, 0); // A reset date of 0 has to be in the past. // A reset date of 0 has to be in the past.
setReqRemaining(token, userTokenRateLimit, 0);
// Insert it only if it is not registered yet. // Insert it only if it is not registered yet.
if (githubUserTokens.data.indexOf(token) === -1) { if (githubUserTokens.data.indexOf(token) === -1) {
githubUserTokens.data.push(token); githubUserTokens.data.push(token);