-
Notifications
You must be signed in to change notification settings - Fork 4.7k
fix: Erro ao enviar mensagem para grupos (remoteJid failed constraint) #2162
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: develop
Are you sure you want to change the base?
fix: Erro ao enviar mensagem para grupos (remoteJid failed constraint) #2162
Conversation
…B writes Refactors the cache-saving logic to prevent `Unique constraint failed` errors. This issue occurs when an item's `remoteJid` is not yet included in the `jidOptions` of the existing record. The database query now uses an `OR` condition to find a matching record by either `jidOptions` (using `contains`) or by the `remoteJid` itself in a single query. Additionally, this commit introduces several performance optimizations: 1. **Skip Unnecessary Updates**: The function now performs a deep comparison between the new payload and the `existingRecord`. An `update` operation is only executed if the data has actually changed, reducing unnecessary database writes. 2. **Parallel Processing**: The sequential `for...of` loop has been replaced with `Promise.allSettled`. This allows all items in the `data` array to be processed concurrently, significantly speeding up execution for batch inputs. 3. **Data Consistency**: The JIDs in `jidOptions` are now sorted alphabetically before being joined into a string. This ensures that the change-detection logic is accurate, regardless of the order in which JIDs were discovered. 4. **Refactor**: Simplified JID unification logic using a `Set` and introduced a `normalizeJid` helper function for cleaner code. TODO: Investigate the root cause of why `remoteJid` is sometimes not present in `jidOptions` upon initial discovery.
Reviewer's GuideRefactors the saveOnWhatsappCache function to prevent unique constraint errors by querying both jidOptions and remoteJid, optimize database writes through change detection, process items concurrently for performance, and improve JID normalization and error resilience. Sequence diagram for the updated saveOnWhatsappCache processsequenceDiagram
participant Caller
participant "saveOnWhatsappCache()"
participant "prismaRepository.isOnWhatsapp"
participant Logger
Caller->>"saveOnWhatsappCache()": Call with data array
"saveOnWhatsappCache()"->>Logger: Log start and config check
alt Parallel processing
loop For each item (concurrent)
"saveOnWhatsappCache()"->>Logger: Log normalization/skipped item
"saveOnWhatsappCache()"->>"prismaRepository.isOnWhatsapp": findFirst({ OR: [jidOptions contains jid, remoteJid] })
"saveOnWhatsappCache()"->>Logger: Log result of findFirst
alt Record exists
"saveOnWhatsappCache()"->>Logger: Log change detection
alt Data unchanged
"saveOnWhatsappCache()"->>Logger: Log skip update
else Data changed
"saveOnWhatsappCache()"->>Logger: Log update
"saveOnWhatsappCache()"->>"prismaRepository.isOnWhatsapp": update({ id, data })
end
else No record
"saveOnWhatsappCache()"->>Logger: Log create
"saveOnWhatsappCache()"->>"prismaRepository.isOnWhatsapp": create({ data })
end
"saveOnWhatsappCache()"->>Logger: Log errors if any
end
end
"saveOnWhatsappCache()"->>Caller: Return after all settled
Entity relationship diagram for IsOnWhatsapp table changeserDiagram
IsOnWhatsapp {
string id
string remoteJid
string jidOptions
string lid
datetime createdAt
datetime updatedAt
}
%% Note: The query now checks both remoteJid and jidOptions for existence
%% No new tables, but logic for querying IsOnWhatsapp is updated
Class diagram for updated saveOnWhatsappCache logicclassDiagram
class ISaveOnWhatsappCacheParams {
string remoteJid
string remoteJidAlt
string lid
}
class saveOnWhatsappCache {
+async saveOnWhatsappCache(data: ISaveOnWhatsappCacheParams[])
}
class normalizeJid {
+normalizeJid(jid: string | null | undefined): string | null
}
class prismaRepository_isOnWhatsapp {
+findFirst(where)
+update(where, data)
+create(data)
}
class Logger {
+verbose(...)
+warn(...)
+error(...)
}
ISaveOnWhatsappCacheParams <.. saveOnWhatsappCache : uses
saveOnWhatsappCache o-- normalizeJid : uses
saveOnWhatsappCache o-- prismaRepository_isOnWhatsapp : uses
saveOnWhatsappCache o-- Logger : uses
File-Level Changes
Possibly linked issues
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
There was a problem hiding this 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 - here's some feedback:
- Consider limiting the concurrency in Promise.allSettled (e.g. via a p-limit or batching) for large data arrays to prevent overwhelming your database connections.
- Using Prisma’s contains on the comma-separated jidOptions string may produce false positives; for more reliable lookups consider storing jidOptions as an array field or using an exact-match filter.
Prompt for AI Agents
Please address the comments from this code review:
## Overall Comments
- Consider limiting the concurrency in Promise.allSettled (e.g. via a p-limit or batching) for large data arrays to prevent overwhelming your database connections.
- Using Prisma’s contains on the comma-separated jidOptions string may produce false positives; for more reliable lookups consider storing jidOptions as an array field or using an exact-match filter.
## Individual Comments
### Comment 1
<location> `src/utils/onWhatsappCache.ts:99-108` </location>
<code_context>
+ // 2. Unifica todos os JIDs usando um Set para garantir valores únicos
+ const finalJidOptions = new Set(expandedJids);
- if (existingRecord?.jidOptions) {
- const existingJids = existingRecord.jidOptions.split(',');
- // TODO: Adicionar JIDs existentes que não estão na lista atual
- existingJids.forEach((jid) => {
- if (!finalJidOptions.includes(jid)) {
- finalJidOptions.push(jid);
- }
- });
+ if (lidAltJid) {
+ finalJidOptions.add(lidAltJid);
}
-
- // TODO: Se tiver remoteJidAlt com @lid novo, adicionar
- if (altJid && !finalJidOptions.includes(altJid)) {
- finalJidOptions.push(altJid);
+
+ if (existingRecord?.jidOptions) {
+ existingRecord.jidOptions.split(',').forEach(jid => finalJidOptions.add(jid));
}
</code_context>
<issue_to_address>
**suggestion (bug_risk):** Merging existing JIDs may introduce legacy or malformed entries.
Validate each JID's format before adding to finalJidOptions to prevent legacy or malformed entries from being included.
Suggested implementation:
```typescript
// 2. Unifica todos os JIDs usando um Set para garantir valores únicos e válidos
function isValidJid(jid: string | null | undefined): boolean {
// Exemplo de validação: JID deve conter '@' e não ser vazio
return typeof jid === 'string' && jid.includes('@') && jid.trim().length > 0;
}
const finalJidOptions = new Set(
expandedJids.filter(jid => isValidJid(jid))
);
```
```typescript
if (lidAltJid && isValidJid(lidAltJid)) {
finalJidOptions.add(lidAltJid);
}
```
```typescript
if (existingRecord?.jidOptions) {
existingRecord.jidOptions
.split(',')
.filter(jid => isValidJid(jid))
.forEach(jid => finalJidOptions.add(jid));
}
```
</issue_to_address>Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
📋 Description
O objetivo principal destas modificações é corrigir o problema das mensagens não serem enviadas para alguns grupos, principalmente os que tem o número do criador no jid (ex.: '[email protected]').
A interrupção no fluxo do request é causada por um erro ao tentar criar um novo registro na base de dados com um remoteJid já existente, isto acontece pois os registros são buscados utilizando apenas o jidOptions, que às vezes não tem o atual remoteJid na lista.
O erro em questão:
Os dados diretamente na base de dados, mostrando que o remoteJid não estava no jidOptions:
A lógica de busca foi alterada para prevenir erros de 'Unique constraint failed'.
Para corrigir isso, a busca no banco agora usa
ORpara verificar tanto pelojidOptionsquanto peloremoteJidem uma única query.Além dessa correção, outras otimizações foram implementadas:
updatesó é executado se houver de fato uma mudança, reduzindo escritas desnecessárias no banco.for...of) foi substituída porPromise.allSettled, permitindo que todos os itens do arraydatasejam processados em paralelo.jidOptionsagora são ordenados antes de serem salvos ou comparados. Isso garante que a verificação de "mudança" seja precisa, independentemente da ordem de inserção.Sete um helpernormalizeJidfoi criado para limpar o código. O código foi envolto em um try-catch para evitar interrupção do fluxo de envio de mensagens, visto que o cache não é crítico.🧪 Type of Change
🧪 Testing
✅ Checklist
📝 Additional Notes
TODO: Investigar a causa raiz de o remoteJid às vezes não estar no jidOptions no momento da busca inicial. Também notei na base de dados que alguns números estão vindo com o "@g.us" duplicado.
Summary by Sourcery
Fix cache save errors for WhatsApp group messages and optimize saveOnWhatsappCache
Bug Fixes:
Enhancements:
Chores: