diff --git a/server.js b/server.js index 2a8262d..1de6151 100644 --- a/server.js +++ b/server.js @@ -258,7 +258,7 @@ app.get('/api/calendar', async (req, res) => { // Polling rotatif : on poll un joueur à la fois en rotation continue. // Avec N joueurs et un intervalle cible de 2 min : délai entre chaque = 2min / N. const ROOTME_TARGET_INTERVAL_MS = 2 * 60 * 1000; // refresh cible par joueur -const ROOTME_MIN_DELAY_MS = 10_000; // plancher anti-429 +const ROOTME_MIN_DELAY_MS = 10_000; // plancher entre deux requêtes let rootmeCache = null; let rootmePrevScores = {}; // login → last known score @@ -304,15 +304,25 @@ function startRootmePoller() { rootmeCache = []; let idx = 0; + let backoffUntil = 0; // timestamp jusqu'auquel on suspend le polling async function pollNext() { const id = ids[idx]; idx = (idx + 1) % ids.length; + const waitMs = Math.max(delayMs, backoffUntil - Date.now()); + if (waitMs > delayMs) { + console.log(`[rootme] backoff actif, reprise dans ${Math.round(waitMs / 1000)}s`); + return setTimeout(pollNext, waitMs); + } + try { const resp = await fetch(`https://api.www.root-me.org/auteurs/${id}`, { headers, timeout: 10000 }); if (resp.status === 429) { - console.warn(`[rootme] 429 pour id "${id}", prochain tour dans ${delayMs / 1000}s`); + const retryAfter = parseInt(resp.headers.get('retry-after') || '0', 10); + const pauseMs = (retryAfter > 0 ? retryAfter * 1000 : 5 * 60 * 1000); + backoffUntil = Date.now() + pauseMs; + console.warn(`[rootme] 429 — pause ${Math.round(pauseMs / 1000)}s`); } else { const entry = parseRootmeUser(await resp.json(), id); if (entry) {