1. Objetivo da Atualização
Esta atualização implementa um conjunto de ajustes no backend que utiliza Baileys, com foco em:
- Evitar contatos duplicados criados por LID (
@lid) e PN (@s.whatsapp.net). - Corrigir relacionamentos de Tickets/Messages com contatos duplicados.
- Recalcular campos de resumo de ticket (
lastMessage,lastMessageAt) de forma idempotente. - Introduzir um cache LID/PN (Redis ou memória) para reduzir consultas e inconsistências.
- Manter o suporte multi-empresa (
companyId) em todos os scripts de saneamento.
2. Pré-Requisitos Técnicos
2.1. Ferramentas e dependências
- Node.js LTS instalado no servidor.
- Projeto com TypeScript e
ts-node/ts-node-devconfigurados. sequelizeesequelize-clifuncionando (já presentes no projeto).- Banco configurado e acessível (Postgres ou MySQL). O script de backup padrão é focado em Postgres.
2.2. Recomendações
- Executar todas as operações em ambiente de homologação antes de aplicar em produção.
- Garantir que não há migrations pendentes (
npm run db:migrateesteja ok). - Ter acesso ao servidor para rodar comandos via terminal (SSH).
fix:contacts-lid-pn, fix:chats, fix:backfill-messages).
3. Atualização de Código
Aplicar no repositório backend os seguintes itens:
- Migrations:
add-lid-pn-fields-to-contacts.ts(camposlid,pnJid,lidJid,remoteJidAlt+ índices não-únicos).unique-companyid-number-contacts.ts(opcional, índice UNIQUE em(companyId, number)após saneamento).
- Serviços:
CreateOrUpdateContactService.tsajustado para:- Buscar contato por múltiplas chaves (number, lid, pnJid, lidJid, remoteJid, remoteJidAlt).
- Mesclar contatos duplicados PN vs LID de forma conservadora.
- Alimentar o cache LID/PN após consolidar o contato.
- Listener Baileys:
wbotMessageListener.tscom:- Helpers LID/PN para normalizar JIDs.
verifyContactconsumindo/atualizando o cache LID/PN.
- Cache LID/PN:
src/utils/lidpn/env.tssrc/libs/lidPnCache/index.tssrc/libs/lidPnCache/memory.tssrc/libs/lidPnCache/redis.ts
- Scripts:
src/scripts/backupDb.tssrc/scripts/fixContactsLidPn.tssrc/scripts/fixChats.tssrc/scripts/fixBackfillMessages.ts(versão comcompanyId).
-
Atualização do
package.jsoncom os scripts:"backup:db": "node -r ts-node/register/transpile-only src/scripts/backupDb.ts", "fix:contacts-lid-pn": "node -r ts-node/register/transpile-only src/scripts/fixContactsLidPn.ts", "fix:chats": "node -r ts-node/register/transpile-only src/scripts/fixChats.ts", "fix:backfill-messages": "node -r ts-node/register/transpile-only src/scripts/fixBackfillMessages.ts"
4. Rodar Migrations
Após atualizar os arquivos no repositório e publicar no servidor, execute:
npm run db:migrate
Isso irá:
- Adicionar colunas
lid,pnJid,lidJid,remoteJidAltna tabelaContacts. - Criar índices não-únicos para melhorar buscas por
companyId+ essas colunas. - (Opcional) Criar índice UNIQUE em
(companyId, number), se a migration opcional tiver sido incluída.
(companyId, number), a migration UNIQUE pode falhar.
Recomenda-se rodar primeiro os scripts de saneamento antes de aplicar UNIQUE.
5. Ajuste de Variáveis de Ambiente
Adicione/ajuste as seguintes entradas no arquivo .env do backend:
5.1. Configuração do Cache LID/PN
LIDPN_CACHE_DRIVER=redis # ou "memory"
LIDPN_CACHE_TTL_MS=300000 # 5 minutos
LIDPN_CACHE_DRIVER=redis: usa Redis já configurado pelo projeto (vialibs/cache.ts).LIDPN_CACHE_DRIVER=memory: utiliza umMapem memória (sem dependência de Redis).LIDPN_CACHE_TTL_MS: tempo de vida dos mapeamentos PN <-> LID em milissegundos.
5.2. Configuração de Dialeto do Banco (para backup)
DB_DIALECT=postgres
O script backupDb.ts atual implementa backup via pg_dump para Postgres.
Caso esteja usando MySQL, o backup deverá ser adaptado ou feito manualmente (mysqldump).
5.3. Filtro opcional por Empresa
Alguns scripts permitem rodar por empresa via variável:
COMPANY_ID=10
Se COMPANY_ID não for informado, os scripts operam sobre todas as empresas; se for informado,
restringem a execução àquela companyId, quando implementado.
6. Subir o Backend e Validar
- Reiniciar o backend:
ou o comando equivalente usado no ambiente.pm2 restart NOME_DA_APP -
Verificar logs para garantir que não há erros de:
- Conexão com banco.
- Carregamento de models (Contact, Ticket, Message).
- Erro em
lidPnCacheou Redis.
-
Validar, via aplicação, que:
- Novos contatos continuam sendo criados normalmente.
- Não há erros ao receber mensagens.
7. Execução dos Scripts de Correção
7.1. Backup do Banco
Antes de qualquer alteração em massa, executar:
npm run backup:db
Isso gera um arquivo do tipo:
backups/backup-before-chat-fix-YYYYMMDDHHmmss.sql
7.2. Correção de Contatos LID/PN
Script: fix:contacts-lid-pn.
7.2.1. Execução de teste (DRY RUN)
Para rodar apenas o diagnóstico (sem gravar nada):
DRY_RUN=true npm run fix:contacts-lid-pn
Exemplo por empresa (se tiver adaptado o script para usar COMPANY_ID):
COMPANY_ID=10 DRY_RUN=true npm run fix:contacts-lid-pn
7.2.2. Execução efetiva
npm run fix:contacts-lid-pn
O script irá:
- Identificar contatos LID cuja
pnJidaponta para um número já existente em outro contato. - Escolher o contato com PN como vencedor e o LID como perdedor.
- Migrar tickets e mensagens do perdedor para o vencedor (por
companyId). - Marcar o contato perdedor como inativo (e, se
MERGE_DELETE_LOSER=true, deletar). - Registrar logs em
backups/fixContactsLidPn.log.
7.3. Consolidação de Tickets Duplicados
Script: fix:chats.
7.3.1. DRY RUN
DRY_RUN=true npm run fix:chats
Exemplo por empresa:
COMPANY_ID=10 DRY_RUN=true npm run fix:chats
7.3.2. Execução efetiva
npm run fix:chats
O script irá:
- Agrupar tickets por
companyId,whatsappIdecontactId. - Escolher o ticket mais antigo como principal (winner).
- Mover mensagens dos tickets duplicados (losers) para o ticket vencedor.
- Fechar os tickets duplicados (
status = "closed").
7.4. Backfill de lastMessage / lastMessageAt
Script: fix:backfill-messages.
7.4.1. DRY RUN
DRY_RUN=true npm run fix:backfill-messages
Exemplo por empresa:
COMPANY_ID=10 DRY_RUN=true npm run fix:backfill-messages
7.4.2. Execução efetiva
npm run fix:backfill-messages
O script irá, para cada ticket:
- Buscar todas as mensagens daquele ticket para o
companyIdcorrespondente. - Identificar a última mensagem (pela data
createdAt). - Preencher
lastMessagecom o texto ou com[mediaType]se for mídia. - Preencher
lastMessageAtcom ocreatedAtda última mensagem. - Opcionalmente atualizar
updatedAt(viaBACKFILL_TOUCH_UPDATED_AT).
8. Verificações Pós-Atualização
- Confirmar que contatos antes duplicados (por nome + número) agora aparecem unificados.
- Conferir se tickets não aparecem mais duplicados para o mesmo contato em uma mesma empresa.
- Verificar em algumas conversas se o resumo (
lastMessage) corresponde à última mensagem real. - Acompanhar logs do backend por um período (ex.: 24h) para garantir ausência de erros recorrentes relacionados a:
- Cache LID/PN.
- Baileys (
signalRepository.lidMapping). - Acesso às novas colunas em
Contacts.
9. Estratégia de Rollback (em caso de problemas graves)
- Parar o backend (ex.:
pm2 stopou equivalente). - Restaurar o banco a partir do arquivo gerado por
backup:db:- Postgres:
psqlou ferramenta de administração (ex.: pgAdmin). - MySQL: utilizar
mysql/mysqldumpequivalente (se implementado).
- Postgres:
- Reverter migrations se necessário:
npx sequelize db:migrate:undo:all - Retornar para a versão anterior do código (tag, commit ou branch estável).
- Subir novamente o backend e validar.