Worker: PostgreSQL pooling e conexões
Visão geral
Cada processo do worker (container/replica) usa um único Prisma Client com um connection pool para o Postgres. O número de sessões TCP no servidor é aproximadamente:
réplicas do worker + réplicas da API + jobs adicionais × conexões por pool
Use PgBouncer (modo transaction) ou o pooler do provedor se precisar de muitas instâncias de aplicação com um teto baixo de conexões reais no Postgres.
DATABASE_URL (Prisma)
Parâmetros úteis na query string (PostgreSQL):
| Parâmetro | Efeito |
|---------------------|--------|
| connection_limit | Máximo de conexões no pool por processo (ex.: 12). |
| pool_timeout | Segundos à espera de uma conexão livre do pool. |
Exemplo (acrescentar ao URL existente, respeitando ? vs &):
postgresql://user:pass@host:5432/db?schema=public&connection_limit=12&pool_timeout=20
A API (apps/fullstack ou equivalente) e o worker somam conexões se apontarem ao mesmo Postgres sem pooler. Ajuste connection_limit em cada serviço para o tráfego esperado (ex.: API com mais, worker com teto coerente com a concorrência BullMQ documentada abaixo).
Concorrência BullMQ no worker
Variáveis opcionais (ver apps/worker/src/worker-bull-concurrency.ts):
WORKER_BULL_CONCURRENCY_FREE_PLAN_RENEWAL(default 5)WORKER_BULL_CONCURRENCY_STRIPE_SUB_BOUNDARY(default 3)WORKER_BULL_CONCURRENCY_PIX_SUBSCRIPTIONS(default 5)WORKER_BULL_CONCURRENCY_DATA_RETENTION(default 1)WORKER_BULL_CONCURRENCY_PILOT_INSTANCE_HEALTHCHECK(default 1)WORKER_BULL_CONCURRENCY_WHATSAPP_INSTANCE_VALIDATE(default 2)WORKER_BULL_CONCURRENCY_RECOVERY_SWEEP(default 1)WORKER_BULL_CONCURRENCY_LABELS(default 5)
Filas por instância WhatsApp usam concurrency: 1 por fila. Reduza as variáveis acima se o pool estiver a esgotar (pool_timeout / filas de espera no Prisma).
Pilot instance healthcheck (restarts sequenciais)
O job processAllInstancesHealthcheck avalia instâncias OPEN uma a uma; quando várias precisam de restart (Evolution V2 / GO), os restarts executam em sequência dentro da mesma execução do job (não em paralelo). O job pode demorar mais se houver muitas instâncias a reiniciar; WORKER_BULL_CONCURRENCY_PILOT_INSTANCE_HEALTHCHECK continua a limitar quantos jobs deste tipo correm em paralelo entre si por processo.
Message reconcilers (locks Redis e batches)
Os reconcilers de fila QUEUED / SENT / entrega / READ usam locks NX no Redis (ver message-reconcile-lock.ts e message-reconciler-schedule.ts).
| Variável | Efeito |
|----------|--------|
| MESSAGE_RECONCILER_PER_TYPE_LOCKS | 1 ou true: lock por tipo (ps:reconciler:lock:queued, :sent, :delivered, :retries) e reconcilers podem correr em paralelo. Omitido: cadeia num único lock (ps:reconciler:lock:chain) — queued → sent → delivered no timer horário; na arranque inclui também retries. |
| MESSAGE_RECONCILER_LOCK_TTL_MS | TTL do lock em ms (mín. 10s, máx. 600s). Default 180000 (3 min) para acomodar a cadeia. |
| MESSAGE_RECONCILER_LOG_LOCK_MISSES | 1 / true: debug quando SET NX falha (outro processo detém o lock). |
| MESSAGE_RECONCILER_BATCH_SIZE | Linhas por batch (default 200, máx. 5000). |
| MESSAGE_RECONCILER_MAX_BATCHES | Batches por execução (default 5, máx. 100). |
Intervalos existentes: MESSAGE_RECONCILER_INTERVAL_MS, SENT_DELIVERY_RETRY_INTERVAL_MS (ver bootstrap/start.ts).
Cache da lista de instâncias (menos leituras)
WORKER_INSTANCE_NAMES_LIST_CACHE_TTL_MS— TTL do cache Redis da lista de nomes de instância (default45000). Use0para desativar e consultar sempre o banco.- O cache é invalidado no canal Redis
whatsapp:instance:open(verlist-desired-instance-names.ts).
Observabilidade
pg_stat_activityno Postgres para contar sessões por aplicação.- Logs Prisma
queryemdevelopmentno pacote@pilot-status/database(packages/database/src/index.ts).
Sessões zumbi e “too many clients already”
Quando max_connections está esgotado, novas sessões (incluindo psql ou o script abaixo) recebem FATAL: sorry, too many clients already. Libere slots antes de administrar o banco: por exemplo, pausar temporariamente o worker ou o frontend na Ilumin, ou reiniciar um serviço que segure pool grande.
Script no repositório
Com DATABASE_URL apontando para o banco alvo:
cd packages/database
npx tsx scripts/postgres-zombie-cleanup.ts
- Por defeito só inspeciona (
pg_stat_activity, contagens porstate,max_connections). --terminate— executapg_terminate_backendem sessõesidle in transaction/idle in transaction (aborted)comstate_changemais antigo que 10 minutos (ajustável com--idle-minutes=N).--apply-role-timeouts— tentaALTER ROLE <current_user> SET idle_in_transaction_session_timeout = '5min'(requer permissão no papel atual).
Exemplo:
DATABASE_URL="postgresql://user:pass@host:5432/pilot_status?schema=public" npx tsx scripts/postgres-zombie-cleanup.ts --terminate --idle-minutes=10
Não use --terminate em massa sobre estado idle sem rever application_name: pools Prisma mantêm conexões idle saudáveis.
Postgres (SQL manual)
Os mesmos passos descritos no plano interno: SELECT em pg_stat_activity, depois SELECT pg_terminate_backend(pid) FROM pg_stat_activity WHERE ... com critérios conservadores. Cliente psql não aceita o parâmetro de query schema=public do Prisma — use URL sem esse parâmetro e SET search_path TO public, ou use o script com URL Prisma completa.
Ilumin e segredos
ilumin.yml e apps/worker/ilumin.yml usam DATABASE_URL: ${DATABASE_URL} / - DATABASE_URL=${DATABASE_URL}. Configure o valor completo (com connection_limit e pool_timeout adequados ao serviço) no painel Ilumin, não no Git.