I am working on some website for League of Legends statistics, which uses the RiotGames API.
The API allows you to do a maximum amount of requests per 10 seconds, and another maximum amount of requests per 10 minutes.
I made several functions to realize a queue concept, where I pass the API requests into and which only pushs out as many requests as allowed and then waits until I can do more requests, based on the given limits.
Sidenote: The limits are applied to each API server individually (e.g. euw, na, oce, etc.)
I wonder how good my code is/where it could be improved:
var request = require("request");
var apiKey = "someAPIkey";
var constant10S = 3000;
var constant10M = 180000;
var requestQueue = {
br: {requests10S: 0, requests10M: 0, time10S: 0, time10M: 0, queueSleeping: true, requests: []},
euw: {requests10S: 0, requests10M: 0, time10S: 0, time10M: 0, queueSleeping: true, requests: []},
eune: {requests10S: 0, requests10M: 0, time10S: 0, time10M: 0, queueSleeping: true, requests: []},
na: {requests10S: 0, requests10M: 0, time10S: 0, time10M: 0, queueSleeping: true, requests: []},
tr: {requests10S: 0, requests10M: 0, time10S: 0, time10M: 0, queueSleeping: true, requests: []},
kr: {requests10S: 0, requests10M: 0, time10S: 0, time10M: 0, queueSleeping: true, requests: []},
las: {requests10S: 0, requests10M: 0, time10S: 0, time10M: 0, queueSleeping: true, requests: []},
lan: {requests10S: 0, requests10M: 0, time10S: 0, time10M: 0, queueSleeping: true, requests: []},
oce: {requests10S: 0, requests10M: 0, time10S: 0, time10M: 0, queueSleeping: true, requests: []}
};
function queuedRequest(server, urlDetail, parameter, callback) {
if (typeof parameter === "function") {
callback = parameter;
parameter = {};
}
parameter.api_key = apiKey;
var queries = "?";
for (var query in parameter) {
queries += query + "=" + parameter[query] + "&";
}
queries = queries.substring(0, queries.length - 1);
var url = "https://" + server + ".api.pvp.net/api/lol/" + server + urlDetail + queries;
var qR = {url: encodeURI(url), callback: callback, retry: 0};
requestQueue[server].requests.push(qR);
if (requestQueue[server].queueSleeping) {
triggerQueue(server);
}
}
function retryRequest(server, request) {
requestQueue[server].requests.push(request);
if (requestQueue[server].queueSleeping) {
triggerQueue(server);
}
}
function triggerQueue(server) {
console.log("starting queue Worker...");
requestQueue[server].queueSleeping = false;
var timeNow = (new Date()).getTime();
if (timeNow - requestQueue[server].time10S > 10000) {
requestQueue[server].time10S = timeNow;
requestQueue[server].requests10S = 0;
}
if (timeNow - requestQueue[server].time10M > 600000) {
requestQueue[server].time10M = timeNow;
requestQueue[server].requests10M = 0;
}
queueWorker(server);
}
function queueWorker(server) {
console.log("Current queue: " + requestQueue[server].requests.length);
var timeNow = (new Date()).getTime();
if (requestQueue[server].requests10S >= constant10S && (timeNow - requestQueue[server].time10S) < 10000) {
console.log(server + " reached 10 seconds rate limit");
setTimeout(function () {
queueWorker(server)
}, (10000 - (timeNow - requestQueue[server].time10S)));
} else if (requestQueue[server].requests10M >= constant10M && (timeNow - requestQueue[server].time10M) < 600000) {
console.log(server + " reached 10 minutes rate limit");
setTimeout(function () {
queueWorker(server)
}, (600000 - (timeNow - requestQueue[server].time10M)));
} else {
if (timeNow - requestQueue[server].time10S > 10000) {
requestQueue[server].time10S = timeNow;
requestQueue[server].requests10S = 0;
}
if (timeNow - requestQueue[server].time10M > 600000) {
requestQueue[server].time10M = timeNow;
requestQueue[server].requests10M = 0;
}
requestQueue[server].requests10M++;
requestQueue[server].requests10S++;
var r = requestQueue[server].requests[0];
console.log("working on request:" + r.url + " Retry: " + r.retry);
requestQueue[server].requests.shift();
request(r.url, function (error, response, body) {
if (response != undefined) {
if (response.statusCode === 404) {
body = "{}";
}
}
if (error || response.statusCode === 429 || response.statusCode === 500 || response.statusCode === 503) {
if (response) {
console.log(response.statusCode);
}
console.log(error);
if (r.retry <= 5) {
r.retry++;
setTimeout(function () {
retryRequest(server, r)
}, 1000);
} else {
r.callback(error, response, body);
}
} else {
r.callback(error, response, body);
}
});
if (requestQueue[server].requests.length < 1) {
requestQueue[server].queueSleeping = true;
} else {
queueWorker(server);
}
}
}