Ctrl K
ComunidadGuías…

static/poll-fetch.js

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
// fetch() for endpoints a page polls on a timer: stop hammering one that
// keeps refusing.
//
// A page left open on a machine that is not in the settings whitelist
// polls forever and is refused every time — one display client produced
// 9,182 consecutive 403s in a week, about a fifth of the whole access
// log, and every one of them displaced a real request inside the log's
// row cap. The same shape appears with 404 when the two paired machines
// are on different versions: the newer one polls an endpoint the older
// one does not have yet, for as long as the version gap lasts.
//
// So after a few consecutive 403/404s the endpoint is left alone for a
// while. The caller's timer keeps ticking — it just returns a rejected
// promise without touching the network, so no page has to restructure
// its polling loop. A single success clears the state, and the pause
// expires on its own, so whitelisting the machine or finishing the
// update recovers without anyone reloading the page.
window.pollFetch = (function () {
    var LIMIT = 3;              // consecutive refusals before pausing
    var PAUSE_MS = 10 * 60000;  // how long to leave the endpoint alone
    var state = {};             // path -> {denials, pausedUntil}

    // Clear a pause. A button the operator just pressed is not polling —
    // it must try the server again however the timer behind it is doing.
    function reset(url) {
        delete state[String(url).split('?')[0]];
    }

    var poll = function (url, options) {
        var key = String(url).split('?')[0];
        var entry = state[key] || (state[key] = { denials: 0, pausedUntil: 0 });
        var now = Date.now();
        if (entry.pausedUntil > now) {
            var err = new Error('polling paused for ' + key);
            err.pollingPaused = true;
            return Promise.reject(err);
        }
        return fetch(url, options).then(function (response) {
            if (response.status === 403 || response.status === 404) {
                entry.denials += 1;
                if (entry.denials >= LIMIT) {
                    entry.pausedUntil = Date.now() + PAUSE_MS;
                    console.warn('pollFetch: ' + key + ' returned ' +
                        response.status + ' ' + entry.denials +
                        ' times — pausing polling for ' +
                        (PAUSE_MS / 60000) + ' minutes');
                }
            } else {
                entry.denials = 0;
                entry.pausedUntil = 0;
            }
            return response;
        });
        // A rejected fetch (server restarting, network blip) is deliberately
        // not counted: that is the case where polling SHOULD keep trying.
    };
    poll.reset = reset;
    return poll;
})();