Design de Filas
Topologia
Tipos de Job
// Fila: runs
interface RunJob {
type: 'run';
tenantId: string;
integrationKey: string;
handlerKey: string;
direction: 'inbound' | 'outbound';
trigger: 'schedule' | 'manual';
runId: string;
}
// Fila: items
interface ItemJob {
type: 'item';
tenantId: string;
integrationKey: string;
handlerKey: string;
direction: 'inbound' | 'outbound';
runId: string;
itemId: string;
externalId: string;
payload: unknown;
}
Priorização de Jobs
Jobs recebem prioridade baseada no trigger (BullMQ: menor valor = maior prioridade):
| Trigger | Priority | Justificativa |
|---|---|---|
webhook | 1 | Tempo real, resposta esperada pelo cliente externo |
manual | 2 | Ação deliberada do usuário |
queue | 3 | Consumo de fila externa |
schedule | 5 | Agendamento periódico, tolera latência |
Definido em packages/core/src/types/index.ts como constante JOB_PRIORITY, aplicado em todos os produtores (scheduler, webhook, run-worker fan-out).
Resiliência
| Mecanismo | Configuração |
|---|---|
| Retry | 3 tentativas, backoff exponencial (5s base) |
| DLQ | Após falha final, execution_items.dlq_at é preenchido |
| Fan-out | FlowProducer parent/child — parent completa quando todos filhos terminam |
| Concurrency | Configurável por handler via configs.concurrency |
| Rate Limiting por handler | Configurável via configs.rate_limit_per_minute |
| Rate Limiting por tenant | Sliding window 1.000 items/min, delay (não falha) ao exceder |
| Circuit Breaker | Por integration_key: 5 falhas → open 30s → half-open → closed |
| Priorização | Webhooks passam na frente de schedules na fila items |
| Pausa | Por handler, sem afetar outros |
| Cache | Redis TTL 60s para types (reduz consultas ao PostgreSQL) |
| Batch Processing | Contrato /process-batch para reduzir overhead HTTP |
Circuit Breaker
Circuit Breaker Redis-backed por integration_key com 3 estados:
closed ──(5 falhas)──→ open ──(30s)──→ half-open ──(2 sucessos)──→ closed
Quando o circuito está open, o item-worker faz fast-fail (throw imediato), e o job vai para retry. Isso evita que o Runner continue batendo em APIs externas que estão fora do ar.
Implementado em packages/core/src/resilience/circuit-breaker.ts.
Rate Limiter por Tenant
Sliding window Redis-backed que previne starvation de filas — um tenant com carga massiva (ex: 100k leads) não bloqueia itens de outros tenants.
- Limite: 1.000 items/minuto por tenant (configurável)
- Ao exceder: job é adiado em 5s (não falha, não perde)
- Storage: Redis sorted set com auto-cleanup
Implementado em packages/core/src/resilience/rate-limiter.ts.
Cache Redis
Cache para reduzir consultas ao PostgreSQL em hot paths:
| Namespace | Chave | TTL | Usado em |
|---|---|---|---|
types | integration_key | 60s | run-worker, item-worker |
Implementado em packages/core/src/cache/redis-cache.ts com pattern getOrFetch.