Skip to content

Conversation

@ricaelchiquetti
Copy link
Contributor

@ricaelchiquetti ricaelchiquetti commented Aug 15, 2025

Correção e implementação da lógica de resolução de contatos @lid

Descrição

Este PR implementa e corrige a lógica de resolução automática de contatos criados com JID @lid tanto no banco de dados quanto no cache Redis.
Agora, contatos órfãos com @lid são periodicamente verificados e, quando possível, atualizados para o JID real.

A lógica cobre os seguintes cenários:

  • Banco de dados: Busca todos os contatos com @lid, tenta resolver o JID real via Baileys e atualiza ou remove o contato conforme necessário.
  • Cache Redis: Busca todas as chaves de contato com @lid, tenta resolver o JID real e atualiza o cache, removendo a chave antiga.
  • Local Auth State: Atualiza o estado de autenticação local para refletir o JID real.

Motivo

  • Resolve problemas de entrega de mensagens para contatos criados com @lid, especialmente em dispositivos iPhone.
  • Mantém o banco e o cache limpos, evitando contatos órfãos e inconsistências.
  • Melhora a confiabilidade do sistema e reduz erros de sincronização.

Como funciona

  • O método cleanupOrphanedLidContacts executa periodicamente a limpeza e resolução dos contatos.
  • O método updateContactFromLid faz a atualização do contato e das mensagens associadas ao JID real.
  • Logs detalhados foram adicionados para facilitar o monitoramento e troubleshooting.

Testes

  • Testado em ambiente com banco de dados e Redis habilitados.
  • Verificado que contatos @lid são resolvidos e atualizados corretamente.
  • Confirmado que contatos não resolvidos são removidos.

Summary by Sourcery

Implement automatic resolution and cleanup of orphaned @lid contacts by remapping them to real JIDs at runtime and scheduling periodic cleanup, while making message persistence conditional on configuration flags and enhancing observability through detailed logs

New Features:

  • Introduce updateContactFromLid to resolve and update placeholder @lid contacts across database, Redis cache, and local auth state
  • Add cleanupOrphanedLidContacts with periodic scheduler to detect, resolve, or remove orphaned @lid contacts

Bug Fixes:

  • Fix missing resolution of @lid JIDs to real JIDs to prevent orphaned contacts and undelivered messages

Enhancements:

  • Respect SAVE_DATA config flags to conditionally fetch and persist messages and message updates based on HISTORIC, NEW_MESSAGE, and MESSAGE_UPDATE settings
  • Add verbose logging throughout message processing and @lid contact resolution flows

@sourcery-ai
Copy link
Contributor

sourcery-ai bot commented Aug 15, 2025

Reviewer's Guide

This PR introduces a full lifecycle for resolving and cleaning up WhatsApp contacts created with a @lid suffix by adding a scheduled task, on-the-fly contact resolution in the message pipeline, a dedicated resolver method that updates contacts across DB, Redis and local auth state, and conditionally toggles message persistence behaviors based on configuration flags.

Sequence diagram for periodic @lid contact cleanup and resolution

sequenceDiagram
    participant Scheduler
    participant BaileysStartupService
    participant Database
    participant RedisCache
    participant WhatsAppClient
    participant LocalAuthState

    Scheduler->>BaileysStartupService: Trigger cleanupOrphanedLidContacts()
    BaileysStartupService->>Database: Find contacts with @lid
    Database-->>BaileysStartupService: Return @lid contacts
    loop For each @lid contact
        BaileysStartupService->>WhatsAppClient: Resolve real JID via onWhatsApp()
        WhatsAppClient-->>BaileysStartupService: Return real JID or not found
        alt Real JID found
            BaileysStartupService->>Database: Update contact to real JID
            BaileysStartupService->>RedisCache: Update cache key to real JID
            BaileysStartupService->>LocalAuthState: Update local contact to real JID
        else Not found
            BaileysStartupService->>Database: Remove orphaned contact
            BaileysStartupService->>RedisCache: Remove orphaned cache key
            BaileysStartupService->>LocalAuthState: Remove orphaned local contact
        end
    end
Loading

Class diagram for BaileysStartupService contact and message update logic

classDiagram
    class BaileysStartupService {
      +startLidCleanupScheduler()
      +cleanupOrphanedLidContacts()
      +updateContactFromLid(lidJid, realJid)
      +eventHandler()
      +formatUpdateMessage(data)
    }
    class PrismaRepository {
      +contact
      +message
      +messageUpdate
    }
    class Cache {
      +hGet()
      +hSet()
      +hDelete()
      +keys()
    }
    class WhatsAppClient {
      +onWhatsApp(jid)
      +sendMessage(jid, options)
    }
    BaileysStartupService --> PrismaRepository : uses
    BaileysStartupService --> Cache : uses
    BaileysStartupService --> WhatsAppClient : uses
Loading

File-Level Changes

Change Details Files
Periodic scheduler and cleanup of orphaned '@lid' contacts
  • Invoke startLidCleanupScheduler on startup to kick off periodic cleanup
  • Implement cleanupOrphanedLidContacts to scan, resolve or delete '@lid' contacts in DB and Redis
src/api/integrations/channel/whatsapp/whatsapp.baileys.service.ts
New updateContactFromLid method for migrating '@lid' contacts
  • Resolve real JID via WhatsApp client and update contact records
  • Migrate associated messages in database
  • Update Redis cache entries and local auth state store
src/api/integrations/channel/whatsapp/whatsapp.baileys.service.ts
Inline '@lid' resolution in incoming messages
  • Detect messages with remoteJid containing '@lid' and log mapping
  • Store previousRemoteJid, set real remoteJid to senderPn
  • Call updateContactFromLid immediately after adjusting remoteJid
src/api/integrations/channel/whatsapp/whatsapp.baileys.service.ts
Config-driven message persistence and update behavior
  • Guard assignment of messageId and creation of messageUpdate entries behind SAVE_DATA flags
  • Skip formatUpdateMessage early if NEW_MESSAGE is disabled
  • Conditionally apply validation logic and update tracking based on HISTORIC, NEW_MESSAGE and MESSAGE_UPDATE settings
src/api/integrations/channel/whatsapp/whatsapp.baileys.service.ts

Possibly linked issues

  • #0: The PR updates the remoteJid field using senderPn when @lid is present, and cleans up orphaned @lid contacts, directly resolving the issue.
  • #0: The PR fixes message delivery issues for @lid contacts by implementing automatic JID resolution and updates across database, cache, and local state.
  • #0: The PR fixes the issue by implementing automatic resolution and updating of @lid contacts, enabling message delivery.

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

Copy link
Contributor

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey there - I've reviewed your changes and they look great!

Prompt for AI Agents
Please address the comments from this code review:
## Individual Comments

### Comment 1
<location> `src/api/integrations/channel/whatsapp/whatsapp.baileys.service.ts:673` </location>
<code_context>

     this.eventHandler();

+    this.startLidCleanupScheduler();
+
     this.client.ws.on('CB:call', (packet) => {
</code_context>

<issue_to_address>
Consider making the lid cleanup scheduler opt-in or configurable.

Some deployments may require tighter control over resource usage or side effects, so providing a configuration option to enable or disable the scheduler would improve flexibility.

Suggested implementation:

```typescript
    this.eventHandler();

    if (this.config?.enableLidCleanupScheduler) {
      this.startLidCleanupScheduler();
    }

    this.client.ws.on('CB:call', (packet) => {

```

1. Ensure that the class has access to a `config` object or property. If not, you will need to add it to the constructor or initialization logic.
2. Document the new configuration option (`enableLidCleanupScheduler`) in your configuration schema or documentation.
3. Update any relevant tests to cover both enabled and disabled scenarios.
</issue_to_address>

### Comment 2
<location> `src/api/integrations/channel/whatsapp/whatsapp.baileys.service.ts:4125` </location>
<code_context>
+              for (const key of keys) {
</code_context>

<issue_to_address>
Nested loop over keys may be redundant and impact performance.

The inner loop over 'keys' may cause unnecessary repeated work. Consider refactoring to avoid double iteration.
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.


this.eventHandler();

this.startLidCleanupScheduler();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion: Consider making the lid cleanup scheduler opt-in or configurable.

Some deployments may require tighter control over resource usage or side effects, so providing a configuration option to enable or disable the scheduler would improve flexibility.

Suggested implementation:

    this.eventHandler();

    if (this.config?.enableLidCleanupScheduler) {
      this.startLidCleanupScheduler();
    }

    this.client.ws.on('CB:call', (packet) => {
  1. Ensure that the class has access to a config object or property. If not, you will need to add it to the constructor or initialization logic.
  2. Document the new configuration option (enableLidCleanupScheduler) in your configuration schema or documentation.
  3. Update any relevant tests to cover both enabled and disabled scenarios.

const previousRemoteJid = received.key.remoteJid;
received.key.remoteJid = received.key.senderPn;
await this.updateContactFromLid(previousRemoteJid, received.key.remoteJid);
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue (performance): Nested loop over keys may be redundant and impact performance.

The inner loop over 'keys' may cause unnecessary repeated work. Consider refactoring to avoid double iteration.

@ricaelchiquetti ricaelchiquetti closed this by deleting the head repository Sep 8, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants