Limites de Requisição
A API External do Efflux implementa rate limiting para garantir uso justo e estabilidade do sistema. Entender esses limites ajuda você a construir integrações confiáveis.
Limites Atuais
| Tipo de Limite | Valor | Janela |
|---|---|---|
| Requisições por minuto | 60 | Janela rolante de 1 minuto |
| Requisições por hora | 1.000 | Janela rolante de 1 hora |
| Requisições por dia | 10.000 | Janela rolante de 24 horas |
Headers de Rate Limit
Informações de rate limit são incluídas nos headers de resposta:
| Header | Descrição |
|---|---|
X-RateLimit-Limit | Máximo de requisições permitidas na janela atual |
X-RateLimit-Remaining | Requisições restantes na janela atual |
X-RateLimit-Reset | Timestamp Unix de quando a janela reseta |
Exemplo de Headers de Resposta
HTTP/1.1 200 OKX-RateLimit-Limit: 60X-RateLimit-Remaining: 45X-RateLimit-Reset: 1705764900Rate Limit Excedido
Quando você excede o rate limit, a API retorna uma resposta 429 Too Many Requests:
{ "error": "Rate limit exceeded", "code": "RATE_LIMIT_EXCEEDED"}A resposta inclui um header Retry-After indicando quantos segundos esperar:
HTTP/1.1 429 Too Many RequestsRetry-After: 30Tratando Rate Limits
1. Monitore os Headers de Rate Limit
Acompanhe seu uso lendo os headers de rate limit:
async function fetchWithRateLimitAwareness(url, options) { const response = await fetch(url, options);
const limit = response.headers.get('X-RateLimit-Limit'); const remaining = response.headers.get('X-RateLimit-Remaining'); const reset = response.headers.get('X-RateLimit-Reset');
if (remaining !== null) { console.log(`Rate limit: ${remaining}/${limit} restantes`);
if (parseInt(remaining) < 10) { console.warn('Aproximando-se do rate limit'); } }
return response;}import requests
def fetch_with_rate_limit_awareness(url, headers): response = requests.get(url, headers=headers)
limit = response.headers.get('X-RateLimit-Limit') remaining = response.headers.get('X-RateLimit-Remaining') reset = response.headers.get('X-RateLimit-Reset')
if remaining: print(f'Rate limit: {remaining}/{limit} restantes')
if int(remaining) < 10: print('Aviso: Aproximando-se do rate limit')
return response2. Implemente Retry com Backoff
Quando atingir um rate limit, use o header Retry-After:
async function fetchWithRetry(url, options, maxRetries = 3) { for (let attempt = 0; attempt < maxRetries; attempt++) { const response = await fetch(url, options);
if (response.status === 429) { const retryAfter = response.headers.get('Retry-After'); const waitSeconds = retryAfter ? parseInt(retryAfter) : Math.pow(2, attempt);
console.log(`Rate limited. Aguardando ${waitSeconds}s antes de tentar novamente...`); await sleep(waitSeconds * 1000); continue; }
return response; }
throw new Error('Máximo de tentativas excedido');}
function sleep(ms) { return new Promise(resolve => setTimeout(resolve, ms));}import timeimport requests
def fetch_with_retry(url, headers, max_retries=3): for attempt in range(max_retries): response = requests.get(url, headers=headers)
if response.status_code == 429: retry_after = response.headers.get('Retry-After') wait_seconds = int(retry_after) if retry_after else (2 ** attempt)
print(f'Rate limited. Aguardando {wait_seconds}s antes de tentar novamente...') time.sleep(wait_seconds) continue
return response
raise Exception('Máximo de tentativas excedido')3. Implemente Fila de Requisições
Para aplicações de alto volume, enfileire requisições para ficar dentro dos limites:
class RateLimitedQueue { constructor(requestsPerSecond = 1) { this.queue = []; this.processing = false; this.minInterval = 1000 / requestsPerSecond; this.lastRequest = 0; }
async add(requestFn) { return new Promise((resolve, reject) => { this.queue.push({ requestFn, resolve, reject }); this.process(); }); }
async process() { if (this.processing || this.queue.length === 0) return;
this.processing = true;
while (this.queue.length > 0) { const now = Date.now(); const timeSinceLastRequest = now - this.lastRequest;
if (timeSinceLastRequest < this.minInterval) { await sleep(this.minInterval - timeSinceLastRequest); }
const { requestFn, resolve, reject } = this.queue.shift();
try { this.lastRequest = Date.now(); const result = await requestFn(); resolve(result); } catch (error) { reject(error); } }
this.processing = false; }}
// Usoconst queue = new RateLimitedQueue(1); // 1 requisição por segundo
const results = await Promise.all([ queue.add(() => fetchContent()), queue.add(() => fetchPlayers()), queue.add(() => fetchSchedules()),]);Boas Práticas
1. Use Cache nas Respostas
Reduza chamadas à API fazendo cache das respostas:
const cache = new Map();const CACHE_TTL = 5 * 60 * 1000; // 5 minutos
async function getCachedContent() { const cached = cache.get('content');
if (cached && Date.now() - cached.timestamp < CACHE_TTL) { return cached.data; }
const data = await fetchContent(); cache.set('content', { data, timestamp: Date.now() });
return data;}2. Use Webhooks (Em Breve)
3. Agrupe Requisições Relacionadas
Se você precisa de dados de múltiplos endpoints, faça requisições concorrentes mas esteja atento ao rate limit:
// Bom: Requisições concorrentes (ainda conta contra o rate limit)const [content, players, schedules] = await Promise.all([ fetchContent(), fetchPlayers(), fetchSchedules()]);
// Melhor: Com consciência do rate limitasync function fetchAllData() { const remaining = await getRateLimitRemaining();
if (remaining < 3) { // Aguardar reset do rate limit await waitForReset(); }
return Promise.all([ fetchContent(), fetchPlayers(), fetchSchedules() ]);}4. Otimize Intervalos de Polling
Se você está fazendo polling por atualizações, use intervalos razoáveis:
| Caso de Uso | Intervalo Recomendado |
|---|---|
| Atualizações de dashboard | 30-60 segundos |
| Monitoramento de players | 1-5 minutos |
| Atualização de analytics | 5-15 minutos |
| Sincronização de conteúdo | 5-10 minutos |
// Polling com intervalo adaptativoasync function pollWithBackoff(fetchFn, baseInterval = 30000) { let interval = baseInterval;
while (true) { try { const data = await fetchFn();
// Reset para intervalo base em sucesso interval = baseInterval;
// Processar dados... } catch (error) { if (error.status === 429) { // Dobrar intervalo em rate limit (máx 5 minutos) interval = Math.min(interval * 2, 5 * 60 * 1000); } }
await sleep(interval); }}5. Trate Rate Limits Graciosamente na UI
Mostre feedback significativo aos usuários quando houver rate limit:
try { const data = await fetchContent(); displayContent(data);} catch (error) { if (error.status === 429) { showNotification( 'Estamos recebendo muitas requisições. Por favor, aguarde um momento e tente novamente.', 'warning' ); }}Monitorando Seu Uso
Acompanhe seus padrões de uso da API para ficar dentro dos limites:
- Registre todas as requisições com timestamps
- Monitore os headers de rate limit nas respostas
- Configure alertas ao se aproximar dos limites
- Revise o uso periodicamente para otimizar