2
\$\begingroup\$

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);
        }
    }
}
\$\endgroup\$

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Browse other questions tagged or ask your own question.