Documentação / Análise Detalhada: Fluxo de Envio de Mensagens - Pilot Status

Análise Detalhada: Fluxo de Envio de Mensagens - Pilot Status

Entrar

Análise Detalhada: Fluxo de Envio de Mensagens - Pilot Status

Este documento apresenta uma análise profunda do ciclo de vida de uma mensagem no sistema Pilot Status, desde a requisição na API até a entrega no WhatsApp do destinatário. O objetivo é mapear as regras, os mecanismos de resiliência, os pontos de falha e propor melhorias para alcançar a máxima garantia de entrega.


1. O Fluxo de Envio (Caminho Feliz)

O fluxo de uma mensagem passa por quatro grandes estágios:

  1. Entrada e Validação (API REST): O cliente faz um POST /v1/messages/send.
  2. Persistência e Enfileiramento: A mensagem é salva no banco de dados com status QUEUED e despachada para o BullMQ (apoiado por Redis).
  3. Processamento (Worker): Um worker consome a fila, aplica variáveis de template, simula o comportamento humano ("digitando...") e faz a chamada HTTP para a Evolution API.
  4. Confirmação Assíncrona (Webhooks): A Evolution API dispara webhooks de volta para o Pilot Status informando SERVER_ACK (recebido pelo servidor do WhatsApp) e DELIVERY_ACK (entregue ao celular do cliente).

2. Regras e Validações Aplicadas

Antes de uma mensagem ser sequer enfileirada, ela passa por um funil estrito de validações no endpoint da API:

  • Autenticação e Ambiente:
    • TEST: Permite envios apenas para o número cadastrado no perfil do desenvolvedor.
    • LIVE: Exige que o projeto tenha a flag productionApproved verdadeira.
  • Regras de Instância: Mensagens de Marketing exigem o uso de uma instância própria conectada pelo cliente. O sistema decide dinamicamente se usa a instância padrão (Pilot Status) ou a do cliente.
  • Opt-in Transacional: Validado pelo WhatsAppTransactionalOptInService. A única exceção é o envio de OTP (One Time Password) através do número oficial do Pilot Status.
  • Rate Limiting: Previne abusos na API, bloqueando picos anômalos de requisições.
  • Time-to-Live (TTL / deliverUntil): Se o cliente não definir, o sistema impõe limites baseados na categoria da mensagem:
    • OTP: Expira em 2 minutos.
    • UTILITY: Expira em 1 hora.
    • MARKETING: Expira em 4 horas.

3. Sistemas Atuais para Garantir o Envio

O sistema já possui uma arquitetura moderna focada em resiliência:

  • Desacoplamento com Filas (BullMQ): A API não aguarda o envio para o WhatsApp. Ela apenas enfileira, garantindo respostas rápidas (baixa latência) e tolerância a picos.
  • Política de Retentativas (Retries): O worker está configurado para tentar enviar a mensagem até 10 vezes, com um intervalo fixo de 30 segundos entre as falhas.
  • Preservação de Tentativas (Smart Wait): Se o worker detecta que a instância do WhatsApp está desconectada (connecting ou closed), ele não queima as retentativas. A mensagem volta para QUEUED silenciosamente.
  • Message Reconciler (Cron/Worker): Um processo de varredura roda em background procurando mensagens presas no estado QUEUED. Ele é responsável por reenfileirar mensagens que por algum motivo foram "esquecidas" ou marcá-las como FAILED se o tempo de deliverUntil foi ultrapassado.
  • Distributed Locks: O uso de travas no Redis evita que dois workers processem a mesma mensagem simultaneamente (evitando envios duplicados).

4. Condições de Falha (Quando a mensagem realmente não chega)

Uma mensagem só é marcada como FAILED (desistência total) nas seguintes situações:

  1. Falha Crítica (Erro 404): A Evolution API retorna que a instância solicitada não existe ou foi excluída. O sistema desiste imediatamente.
  2. Estouro de TTL (Timeout): O tempo limite definido no deliverUntil é atingido (ex: WhatsApp do cliente ficou offline por mais de 2 minutos para um OTP). O Reconciler a marca como falha.
  3. Exaustão de Retentativas: A Evolution API retorna erros temporários (ex: 500 Internal Server Error, indisponibilidade de rede) 10 vezes consecutivas (durante os 5 minutos de janela dos retries).
  4. Rejeição Síncrona (API): Falha no Opt-in, Rate Limit excedido ou ambiente de Teste tentando enviar para números não autorizados (neste caso, nem entra na fila).

5. Gargalos e Pontos de Falha Identificados (Vulnerabilidades)

Apesar de resiliente, a arquitetura atual possui pontos sensíveis que podem causar perda ou atraso de mensagens:

  • Dependência Estrita do Redis (Single Point of Failure): Se o Redis cair, o BullMQ para. Pior: a API POST /messages/send falhará ao tentar enfileirar a mensagem, retornando erro 500 para o cliente.
  • Intervalo de Retry Fixo (Thundering Herd): O intervalo de 30 segundos fixo para retries pode ser perigoso. Se a Evolution API cair e voltar, todas as mensagens represadas tentarão ser enviadas quase ao mesmo tempo a cada 30 segundos, podendo derrubar a Evolution API novamente.
  • Perda de Webhooks: O status de "Entregue" depende exclusivamente dos webhooks da Evolution API. Se a API do Pilot Status estiver reiniciando (deploy) no exato momento em que o webhook chegar, a mensagem ficará com status "fantasmas" (QUEUED ou SENT) para sempre, mesmo tendo chegado ao celular.
  • Gargalo de Fila Única: Se um cliente disparar 100.000 mensagens de Marketing, elas podem entupir o BullMQ, atrasando o envio de mensagens críticas de OTP de outros clientes. Atualmente existe a prioridade urgent, mas filas compartilhadas ainda geram contenção.

6. Sugestões de Melhoria (Rumo à Resiliência Máxima)

Para garantir que o sistema tente entregar a mensagem ao máximo, independente de falhas de infraestrutura, recomendo as seguintes evoluções:

A. Padrão Transactional Outbox (Fim da dependência crítica do Redis)

Em vez de a API salvar no banco e tentar escrever no BullMQ na mesma requisição, a API deve apenas salvar no banco de dados (Postgres) em uma transação. Um processo separado (relé) lê as mensagens novas do Postgres e as empurra para o Redis.

  • Vantagem: Se o Redis cair, a API continua aceitando mensagens (elas ficam salvas no Postgres). Quando o Redis voltar, a fila é preenchida automaticamente. Nenhuma requisição de cliente é perdida.

B. Exponential Backoff com Jitter

Alterar a política de retentativas de (10 tentativas fixas de 30s) para um recuo exponencial (ex: 5s, 15s, 45s, 2m, 5m...) adicionando um Jitter (aleatoriedade de alguns segundos).

  • Vantagem: Evita ataques de DDoS acidentais na própria Evolution API quando ela se recupera de uma instabilidade.

C. Fallback de Instâncias (Roteamento Inteligente)

Se um cliente possui múltiplas instâncias conectadas (ex: suporte1, suporte2) e a instância primária desconectar, o sistema poderia tentar re-rotear a mensagem por uma instância de fallback ativa, ao invés de apenas aguardar o deliverUntil expirar.

D. Sincronização Ativa de Status (Anti-Perda de Webhooks)

O Message Reconciler deve ser aprimorado para identificar mensagens que estão no estado SENT (Enviadas para a Evolution) há mais de X minutos sem receber o webhook de DELIVERY_ACK. Nessas situações, o Reconciler faria um polling (GET ativo) na Evolution API para checar o status real e atualizar o banco.

E. Circuit Breaker na Integração com Evolution API

Implementar um Circuit Breaker no Worker. Se a Evolution API começar a retornar muitos erros 5xx seguidos, o circuito "abre" e o Worker pausa o processamento da fila BullMQ por alguns minutos.

  • Vantagem: Evita gastar tentativas de retry das mensagens atoa enquanto a Evolution API está sabidamente fora do ar.

F. Dead Letter Queue (DLQ)

Mensagens que esgotam as tentativas ou falham por erro 404 devem ser movidas para uma tabela/fila de DLQ (Dead Letter Queue). Isso permite que a equipe de operações ou o próprio cliente (via Dashboard) revise o motivo da falha e clique em um botão "Forçar Reenvio" se o problema subjacente (como número de destino incorreto) tiver sido corrigido.

G. Separação Física de Filas (Lane Isolation)

Criar filas BullMQ separadas por categoria: queue:otp, queue:utility, queue:marketing. Workers independentes (ou com pesos diferentes) garantem que picos de envio de marketing nunca afetem a latência de mensagens OTP críticas.