|
| 1 | +# Correção de Erros PreKeyError no WhatsApp - Com Recuperação de Mensagens |
| 2 | + |
| 3 | +## Problema Identificado |
| 4 | + |
| 5 | +O sistema estava apresentando erros intermitentes de `PreKeyError: Invalid PreKey ID` quando contatos específicos tentavam enviar mensagens. Este é um problema de criptografia end-to-end do WhatsApp onde: |
| 6 | + |
| 7 | +- A sessão de criptografia entre o WhatsApp e um contato específico fica corrompida/dessincronizada |
| 8 | +- As Pre-shared Keys (PreKeys) usadas para estabelecer sessões E2E ficam inválidas |
| 9 | +- O contato tenta enviar mensagens com chaves antigas/inválidas |
| 10 | +- **PROBLEMA CRÍTICO**: As mensagens eram filtradas e descartadas permanentemente - o usuário nunca recebia essas mensagens |
| 11 | + |
| 12 | +### Exemplo do Erro |
| 13 | +``` |
| 14 | +PreKeyError: Invalid PreKey ID |
| 15 | +Contato: 250151964803283@lid / 556699840407@s.whatsapp.net |
| 16 | +Grupo: 556699841230-1508699495@g.us |
| 17 | +Tipo de mensagem: pkmsg (PreKey Message) |
| 18 | +``` |
| 19 | + |
| 20 | +## Solução Implementada |
| 21 | + |
| 22 | +### 1. Armazenamento Temporário de Mensagens Falhas |
| 23 | +- Mensagens que falham na descriptografia são armazenadas temporariamente em memória (até 30 minutos) |
| 24 | +- Limite de 50 mensagens por contato para evitar uso excessivo de memória |
| 25 | +- Limpeza automática de mensagens antigas |
| 26 | +- **Nota**: Armazenamento em memória - mensagens são perdidas se o servidor reiniciar (mas isso é raro) |
| 27 | + |
| 28 | +### 2. Rastreamento de Erros por Contato |
| 29 | +- Adicionado `preKeyErrorTracker` na classe `BaileysStartupService` |
| 30 | +- Rastreia quantas vezes cada contato gera erros de PreKey |
| 31 | +- Mantém timestamp do último erro para limpeza automática |
| 32 | + |
| 33 | +### 3. Recuperação Automática de Sessão + Reprocessamento |
| 34 | +Novo método `attemptSessionRecovery()` que: |
| 35 | +- Detecta quando um contato tem 2+ erros de PreKey |
| 36 | +- Tenta reestabelecer a sessão usando `assertSessions()` |
| 37 | +- **NOVO**: Após recuperar a sessão, tenta reprocessar mensagens armazenadas |
| 38 | +- Limita tentativas a 3 para evitar loops infinitos |
| 39 | +- Após 3 falhas, descarta mensagens e reseta contador (permite novas tentativas imediatamente) |
| 40 | + |
| 41 | +### 4. Reprocessamento de Mensagens Perdidas |
| 42 | +Novo método `retryFailedMessages()` que: |
| 43 | +- Tenta reprocessar até 3 vezes cada mensagem armazenada |
| 44 | +- Processa mensagens na ordem em que foram recebidas |
| 45 | +- Remove mensagens que foram processadas com sucesso |
| 46 | +- Descarta mensagens após 3 tentativas falhadas |
| 47 | +- **Resultado**: Mensagens que estavam "perdidas" são recuperadas! |
| 48 | + |
| 49 | +### 5. Logs Melhorados |
| 50 | +- Logs detalhados identificando o contato problemático |
| 51 | +- Informações sobre grupo, participante e tipo de mensagem |
| 52 | +- Alertas específicos para erros de PreKey |
| 53 | +- Rastreamento de tentativas de recuperação |
| 54 | +- **NOVO**: Notificação quando mensagens são recuperadas com sucesso |
| 55 | +- **NOVO**: Alerta quando mensagens não podem ser recuperadas |
| 56 | + |
| 57 | +### 6. Limpeza Automática |
| 58 | +- Erros antigos (>1 hora) são removidos automaticamente |
| 59 | +- Sessões recuperadas com sucesso limpam o contador de erros |
| 60 | +- Mensagens antigas (>30 minutos) são descartadas automaticamente |
| 61 | +- Cache de mensagens problemáticas expira em 30 minutos |
| 62 | + |
| 63 | +## Arquivos Modificados |
| 64 | + |
| 65 | +### `src/api/integrations/channel/whatsapp/whatsapp.baileys.service.ts` |
| 66 | +1. **Linha ~231**: Adicionado `preKeyErrorTracker` e `failedMessages` para rastrear erros e armazenar mensagens |
| 67 | +2. **Linha ~5492**: Novo método `storeFailedMessage()` para armazenar mensagens que falharam |
| 68 | +3. **Linha ~5530**: Novo método `retryFailedMessages()` para reprocessar mensagens armazenadas |
| 69 | +4. **Linha ~5600**: Método `attemptSessionRecovery()` agora reprocessa mensagens após recuperar sessão |
| 70 | +5. **Linha ~5680**: Melhorado `baileysSignalRepositoryDecryptMessage()` com recuperação automática |
| 71 | +6. **Linha ~2292**: Filtro de mensagens agora armazena mensagens falhas para reprocessamento |
| 72 | + |
| 73 | +### `src/api/integrations/channel/whatsapp/baileysMessage.processor.ts` |
| 74 | +1. **Linha ~58**: Melhorado `markMessageAsProblematic()` com logs de diagnóstico adicionais |
| 75 | + |
| 76 | +## Como Funciona |
| 77 | + |
| 78 | +### Fluxo Normal (Sem Erros) |
| 79 | +``` |
| 80 | +Mensagem recebida → Descriptografia → Processamento → Sucesso |
| 81 | +``` |
| 82 | + |
| 83 | +### Fluxo com PreKeyError (Nova Implementação com Recuperação) |
| 84 | +``` |
| 85 | +Erro 1 → Armazena mensagem em memória (30min) |
| 86 | + ↓ |
| 87 | +Erro 2 → TENTA RECUPERAR SESSÃO automaticamente |
| 88 | + ↓ |
| 89 | +Sessão recuperada → Reprocessa as mensagens → MENSAGENS CHEGAM! ✅ |
| 90 | + ↓ |
| 91 | +Falhou? → Tenta novamente no próximo erro |
| 92 | + ↓ |
| 93 | +Erro 3 → Última tentativa de recuperação |
| 94 | + ↓ |
| 95 | +Falhou 3x? → Descarta mensagens antigas + ZERA contador |
| 96 | + ↓ |
| 97 | +Novas mensagens → Processo reinicia automaticamente (sem espera) |
| 98 | +``` |
| 99 | + |
| 100 | +### Detalhes do Processo |
| 101 | + |
| 102 | +1. **Armazenamento Temporário**: Mensagens com erro são guardadas em memória por 30 minutos |
| 103 | +2. **Trigger de Recuperação**: Após 2 erros do mesmo contato, inicia tentativa automática |
| 104 | +3. **Limite de Tentativas**: Máximo de 3 tentativas de recuperação |
| 105 | +4. **Reset Inteligente**: Após 3 falhas, descarta mensagens antigas e zera contador |
| 106 | +5. **Sem Bloqueio**: Novas mensagens do mesmo contato podem acionar recuperação imediatamente |
| 107 | +6. **Prevenção de Duplicatas**: Sistema verifica `msg.key.id` antes de armazenar |
| 108 | +7. **Limpeza Automática**: Mensagens expiram após 30 minutos se não recuperadas |
| 109 | + |
| 110 | +### Exemplo de Recuperação Bem-Sucedida |
| 111 | +``` |
| 112 | +1. Contato envia 2 mensagens → Ambas falham (PreKeyError) |
| 113 | +2. Sistema armazena as 2 mensagens temporariamente (sem duplicação) |
| 114 | +3. Após 2º erro, sistema reestabelece sessão automaticamente |
| 115 | +4. Sistema reprocessa as 2 mensagens armazenadas |
| 116 | +5. Resultado: Ambas as mensagens são entregues com sucesso! |
| 117 | +``` |
| 118 | + |
| 119 | +## Benefícios |
| 120 | + |
| 121 | +1. **Recuperação de Mensagens**: Mensagens que antes eram perdidas agora são recuperadas automaticamente |
| 122 | +2. **Recuperação Automática**: Sistema tenta resolver o problema sem intervenção manual |
| 123 | +3. **Logs Detalhados**: Facilita diagnóstico e identificação de contatos problemáticos |
| 124 | +4. **Proteção contra Loops**: Limites de tentativas evitam sobrecarga |
| 125 | +5. **Não Invasivo**: Mensagens continuam sendo filtradas até a recuperação |
| 126 | +6. **Limpeza Automática**: Não acumula dados de erros antigos |
| 127 | +7. **Transparente**: Usuário final não percebe o problema - mensagens chegam normalmente após recuperação |
| 128 | + |
| 129 | +## Monitoramento |
| 130 | + |
| 131 | +### Logs a Observar |
| 132 | + |
| 133 | +**Erro detectado e mensagem armazenada:** |
| 134 | +``` |
| 135 | +Erro de descriptografia (pkmsg) para 556699840407@s.whatsapp.net: PreKeyError: Invalid PreKey ID |
| 136 | +Mensagem armazenada para reprocessamento futuro. Contato: 556699840407@s.whatsapp.net, Total armazenado: 1 |
| 137 | +``` |
| 138 | + |
| 139 | +**Tentativa de recuperação:** |
| 140 | +``` |
| 141 | +Detectados 3 erros de PreKey para 556699840407@s.whatsapp.net. Tentando reestabelecer sessão... |
| 142 | +``` |
| 143 | + |
| 144 | +**Recuperação bem-sucedida:** |
| 145 | +``` |
| 146 | +Sessão reestabelecida com sucesso para 556699840407@s.whatsapp.net |
| 147 | +Tentando reprocessar 3 mensagem(ns) armazenada(s) de 556699840407@s.whatsapp.net |
| 148 | +Mensagem reprocessada com sucesso! ID: 3EB0XXXXX |
| 149 | +Mensagem reprocessada com sucesso! ID: 3EB0YYYYY |
| 150 | +Mensagem reprocessada com sucesso! ID: 3EB0ZZZZZ |
| 151 | +3 mensagem(ns) recuperada(s) com sucesso de 556699840407@s.whatsapp.net! |
| 152 | +3 mensagem(ns) perdida(s) foi(ram) recuperada(s)! |
| 153 | +``` |
| 154 | + |
| 155 | +**Limite atingido após 3 tentativas (mensagens descartadas + contador resetado):** |
| 156 | +``` |
| 157 | +ATENÇÃO: 5 mensagem(ns) de 556699840407@s.whatsapp.net não puderam ser recuperadas após 3 tentativas e serão descartadas. |
| 158 | +Contador resetado para 556699840407@s.whatsapp.net. Novas mensagens deste contato poderão acionar o processo de recuperação novamente. |
| 159 | +``` |
| 160 | + |
| 161 | +**Limite de armazenamento:** |
| 162 | +``` |
| 163 | +Limite de mensagens armazenadas atingido para 556699840407@s.whatsapp.net. Mensagem será descartada permanentemente. |
| 164 | +``` |
| 165 | + |
| 166 | +## Limitações |
| 167 | + |
| 168 | +1. **Janela de Recuperação**: Mensagens são armazenadas por até 30 minutos em memória |
| 169 | +2. **Limite por Contato**: Máximo 50 mensagens armazenadas por contato |
| 170 | +3. **Tentativas de Reprocessamento**: Máximo 3 tentativas por mensagem |
| 171 | +4. **Tentativas de Recuperação**: Máximo 3 tentativas, depois descarta e reseta contador |
| 172 | +5. **Memória**: Mensagens são armazenadas em memória RAM (perdidas se o servidor reiniciar, mas isso é raro) |
| 173 | +6. **Tempo de Recuperação**: Sistema tenta recuperar após 2 erros, geralmente em poucos segundos/minutos |
| 174 | +7. **Reset Automático**: Após 3 falhas, contador é zerado e novas mensagens podem acionar recuperação novamente |
| 175 | + |
| 176 | +## Próximos Passos (Opcional) |
| 177 | + |
| 178 | +Se o problema persistir ou para melhorar ainda mais: |
| 179 | + |
| 180 | +1. **Persistência em Banco**: Armazenar mensagens falhas no banco de dados para sobreviver a reinicializações |
| 181 | +2. **Endpoint Manual**: Criar endpoint para forçar reset de sessão de contatos específicos |
| 182 | +3. **Webhook de Alerta**: Notificar administradores quando limite de tentativas for atingido |
| 183 | +4. **Métricas**: Adicionar contadores Prometheus para monitorar frequência de erros |
| 184 | +5. **Dashboard**: Interface para visualizar mensagens pendentes de recuperação |
| 185 | +6. **Notificação ao Usuário**: Informar o remetente que a mensagem está pendente de recuperação |
| 186 | + |
| 187 | +## Testando a Solução |
| 188 | + |
| 189 | +1. Monitore os logs após deploy |
| 190 | +2. Aguarde o próximo erro de PreKey do contato problemático |
| 191 | +3. Verifique se o sistema armazena a mensagem |
| 192 | +4. Após 2 erros, verifique se o sistema tenta recuperação |
| 193 | +5. Confirme se mensagens armazenadas são reprocessadas com sucesso |
| 194 | +6. Valide que as mensagens chegam ao destinatário final |
| 195 | +7. Se falhar 3 vezes, confirme que contador é resetado e novas mensagens são aceitas |
| 196 | + |
| 197 | +## Comportamento Esperado |
| 198 | + |
| 199 | +### Cenário 1: Recuperação Bem-Sucedida (Comum) |
| 200 | +``` |
| 201 | +Erro 1 → Armazena mensagem |
| 202 | +Erro 2 → Tenta recuperar sessão → SUCESSO → Mensagens entregues ✅ |
| 203 | +``` |
| 204 | + |
| 205 | +### Cenário 2: Recuperação na 3ª Tentativa |
| 206 | +``` |
| 207 | +Erro 1 → Armazena mensagem |
| 208 | +Erro 2 → Tenta recuperar → Falha |
| 209 | +Erro 3 → Tenta recuperar → SUCESSO → Mensagens entregues ✅ |
| 210 | +``` |
| 211 | + |
| 212 | +### Cenário 3: Falha Total (Raro) |
| 213 | +``` |
| 214 | +Erro 1 → Armazena mensagem |
| 215 | +Erro 2 → Tenta recuperar → Falha |
| 216 | +Erro 3 → Tenta recuperar → Falha → Descarta mensagens antigas + Zera contador |
| 217 | +Nova mensagem → Processo reinicia (sem espera) → Nova tentativa de recuperação |
| 218 | +``` |
| 219 | + |
| 220 | +## Notas Técnicas |
| 221 | + |
| 222 | +- `assertSessions()` força o WhatsApp a reestabelecer as chaves de criptografia |
| 223 | +- PreKey errors são esperados ocasionalmente em sistemas WhatsApp de alto volume |
| 224 | +- A solução não afeta o processamento normal de mensagens |
| 225 | +- Compatível com multi-tenant (isolamento por instância) |
| 226 | +- Mensagens são armazenadas com metadados completos para reprocessamento fiel |
| 227 | +- Reprocessamento usa o mesmo fluxo de mensagens normais (webhooks, integrações, etc.) |
0 commit comments