Skip to content

Tempo Real — operação, escala e observabilidade

O que é este documento — o runbook de infraestrutura do tempo real do ionCLASS: o que precisa estar ligado em produção para o WebSocket (Reverb) aguentar o horário de saída, como escalar, e o que monitorar — com o alarme que importa em destaque. Companheiro da arquitetura de tempo real, que decide o quê vira tempo real; aqui é como manter de pé. As varreduras agendadas que também empurram eventos pela fila estão em tarefas agendadas.

Como funciona. Os três eventos de tempo real (StudentStateChanged, StudentRosterChanged, ResponsibleNotificationCreated) são transmitidos pela fila — assíncronos — e chegam ao Reverb pelo worker.


1. A fila de broadcast — o elo mais crítico

Todo evento de tempo real é enfileirado e só chega ao cliente quando o worker o processa. Sem worker acompanhando, não há tempo real — e, pior, ele degrada em silêncio (ver §4).

  • QUEUE_CONNECTION=redis em produção. O default é database, que não aguenta a rajada da saída. O Horizon já está instalado, e Horizon exige Redis — confirme que prod está em redis e que o Horizon está supervisionando a fila que recebe os broadcasts.
  • Worker sempre de pé. O processo do Horizon precisa estar sob supervisor/systemd com restart automático. Se ele cai, a fila cresce e as telas "parecem" funcionar enquanto atrasam.
  • Reverb rodando. O processo do Reverb (ou o container equivalente) também sob supervisão. É o processo que mantém os sockets vivos.

Ordem de dependência na saída: ação (portaria/hardware) → evento enfileirado → Horizon processa → Reverb entrega → app do responsável. Qualquer elo parado quebra a promessa; o mais provável de saturar é a fila.


2. Escala horizontal do Reverb

Um processo Reverb atende bem até o limite de sockets da máquina (memória + file descriptors). Ao passar de um processo/instância:

  • Ligar REVERB_SCALING_ENABLED=true (default false). Isso usa Redis pub/sub (canal REVERB_SCALING_CHANNEL, default reverb) para propagar mensagens entre os processos — sem isso, um responsável conectado ao processo A não recebe um evento publicado no processo B.
  • REVERB_APP_MAX_CONNECTIONS — dimensionar para o pico de responsáveis simultâneos na saída (milhares de sockets, cada um com ping a cada 60s — REVERB_APP_PING_INTERVAL).
  • Cada app aberto = um socket vivo. O custo é memória + file descriptors no Reverb; o gatilho de escala é o horário de saída, não a média do dia.

Enquanto houver um processo só, REVERB_SCALING_ENABLED pode ficar desligado — a variável fica documentada aqui como o interruptor de escala.


3. Origens e limites em produção

  • REVERB_ALLOWED_ORIGINS=app.ionclass.com.br,monitor.ionclass.com.br — restringe quem pode abrir socket (default *). Inclui o app do responsável e a portaria.
  • Rate limiting já existe e é configurável (REVERB_APP_RATE_LIMITING_ENABLED, ..._MAX_ATTEMPTS, ..._DECAY_SECONDS). Revisar se o pico de saída não esbarra nos limites default.
  • TLS (REVERB_SCHEME=https, porta 443) — o app monta o cliente de tempo real forçando TLS a partir das credenciais que recebe da API, então o transporte precisa estar em wss em prod.

4. Monitoramento — o alarme que importa é a fila crescendo

O design é best-effort: se o Reverb cai ou a fila atrasa, o cliente não mostra erro — ele cai para o refetch ao focar a tela. Ou seja, a degradação é invisível ao usuário até a promessa já estar quebrada. Por isso o monitoramento não é opcional.

Regra de alarme nº 1: alertar quando a profundidade da fila de broadcast cresce. É o sinal antecipado — dispara antes de qualquer responsável perceber atraso.

  • Hoje, sem instalar nada: o dashboard do Horizon (já instalado) mostra throughput, jobs pendentes, tempo de espera e falhas por fila. Cobre o alarme prioritário (fila/latência do worker). Configure um alerta sobre a métrica de pending jobs / wait time da fila de broadcast.
  • Métricas de socket (opcional, follow-up): conexões ativas, mensagens/s e latência evento→entrega não vêm do Horizon. Para elas, instalar Pulse — a configuração do Reverb já está pré-cabeada para o recorder do Pulse (basta habilitá-lo). Não instalado ainda; é uma mudança de dependência do backend, então tratar como tarefa própria (instalação + configuração + migração + gate do dashboard), fora do escopo da entrega do cliente. Telescope é só para ambiente de dev.

O que observar continuamente:

profundidade da fila de broadcast · latência/wait do worker (Horizon)
conexões ativas · mensagens/s · latência evento → entrega (Pulse, quando houver)
saúde dos processos: Horizon vivo? Reverb vivo? Redis vivo?
taxa de reconexão dos clientes

5. Checklist de rollout (antes do horário de saída)

  • [ ] QUEUE_CONNECTION=redis em prod e Horizon supervisionando a fila de broadcast (restart automático).
  • [ ] Processo Reverb sob supervisão (restart automático); Redis saudável.
  • [ ] REVERB_ALLOWED_ORIGINS com os hosts do app e da portaria; TLS em wss.
  • [ ] REVERB_APP_MAX_CONNECTIONS e rate-limit dimensionados para o pico.
  • [ ] Se >1 processo Reverb: REVERB_SCALING_ENABLED=true (Redis pub/sub).
  • [ ] Alarme de profundidade/latência da fila de broadcast ligado (Horizon).
  • [ ] (Follow-up) Pulse para métricas de socket, se quiser visibilidade de conexões/latência de entrega.

Lembrete de arquitetura. O tempo real não substitui o push FCM: WebSocket cobre o app aberto; FCM cobre o app fechado. Os dois convivem e o cliente deduplica pela versão do estado de retirada (estado nunca regride) e pelo identificador real da notificação (inbox). Se todo o tempo real cair, o produto continua correto — só volta a ser "atrasado" como antes.

Documentação do ionCLASS