Skip to content

Commit b1b07b7

Browse files
Merge pull request #2321 from Vitordotpy/fix/remotejid-normalization-and-cache-race
fix: normalize remoteJid in message updates and handle race condition in contact cache
2 parents c7b7a99 + bb831d5 commit b1b07b7

File tree

2 files changed

+70
-13
lines changed

2 files changed

+70
-13
lines changed

src/api/integrations/channel/whatsapp/whatsapp.baileys.service.ts

Lines changed: 47 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1565,8 +1565,15 @@ export class BaileysStartupService extends ChannelStartupService {
15651565

15661566
for await (const { key, update } of args) {
15671567
const keyAny = key as any;
1568-
const normalizedRemoteJid = keyAny.remoteJid?.replace(/:.*$/, '');
1569-
const normalizedParticipant = keyAny.participant?.replace(/:.*$/, '');
1568+
if (keyAny.remoteJid) {
1569+
keyAny.remoteJid = keyAny.remoteJid.replace(/:.*$/, '');
1570+
}
1571+
if (keyAny.participant) {
1572+
keyAny.participant = keyAny.participant.replace(/:.*$/, '');
1573+
}
1574+
1575+
const normalizedRemoteJid = keyAny.remoteJid;
1576+
const normalizedParticipant = keyAny.participant;
15701577

15711578
if (settings?.groupsIgnore && normalizedRemoteJid?.includes('@g.us')) {
15721579
continue;
@@ -1644,18 +1651,48 @@ export class BaileysStartupService extends ChannelStartupService {
16441651

16451652
const searchId = originalMessageId || key.id;
16461653

1647-
const messages = (await this.prismaRepository.$queryRaw`
1648-
SELECT * FROM "Message"
1649-
WHERE "instanceId" = ${this.instanceId}
1650-
AND "key"->>'id' = ${searchId}
1651-
LIMIT 1
1652-
`) as any[];
1653-
findMessage = messages[0] || null;
1654+
let retries = 0;
1655+
const maxRetries = 3;
1656+
const retryDelay = 500; // 500ms delay to avoid blocking for too long
1657+
1658+
while (retries < maxRetries) {
1659+
const messages = (await this.prismaRepository.$queryRaw`
1660+
SELECT * FROM "Message"
1661+
WHERE "instanceId" = ${this.instanceId}
1662+
AND "key"->>'id' = ${searchId}
1663+
LIMIT 1
1664+
`) as any[];
1665+
findMessage = messages[0] || null;
1666+
1667+
if (findMessage?.id) {
1668+
break;
1669+
}
1670+
1671+
retries++;
1672+
if (retries < maxRetries) {
1673+
await delay(retryDelay);
1674+
}
1675+
}
16541676

16551677
if (!findMessage?.id) {
1656-
this.logger.warn(`Original message not found for update. Skipping. Key: ${JSON.stringify(key)}`);
1678+
this.logger.verbose(
1679+
`Original message not found for update after ${maxRetries} retries. Skipping. This is expected for protocol messages or ephemeral events not saved to the database. Key: ${JSON.stringify(key)}`,
1680+
);
16571681
continue;
16581682
}
1683+
1684+
// Sync the incoming key.remoteJid with the stored one.
1685+
// This mutation is safe and necessary because Baileys events might use LIDs while we store Phone JIDs (or vice versa).
1686+
// Normalizing ensuring downstream logic uses the identifier that exists in our database.
1687+
if (findMessage?.key?.remoteJid && key.remoteJid !== findMessage.key.remoteJid) {
1688+
key.remoteJid = findMessage.key.remoteJid;
1689+
}
1690+
if (findMessage?.key?.remoteJid && findMessage.key.remoteJid !== key.remoteJid) {
1691+
this.logger.verbose(
1692+
`Updating key.remoteJid from ${key.remoteJid} to ${findMessage.key.remoteJid} based on stored message`,
1693+
);
1694+
key.remoteJid = findMessage.key.remoteJid;
1695+
}
16591696
message.messageId = findMessage.id;
16601697
}
16611698

src/utils/onWhatsappCache.ts

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { prismaRepository } from '@api/server.module';
22
import { configService, Database } from '@config/env.config';
33
import { Logger } from '@config/logger.config';
4+
import { Prisma } from '@prisma/client';
45
import dayjs from 'dayjs';
56

67
const logger = new Logger('OnWhatsappCache');
@@ -164,9 +165,28 @@ export async function saveOnWhatsappCache(data: ISaveOnWhatsappCacheParams[]) {
164165
logger.verbose(
165166
`[saveOnWhatsappCache] Register does not exist, creating: remoteJid=${remoteJid}, jidOptions=${dataPayload.jidOptions}, lid=${dataPayload.lid}`,
166167
);
167-
await prismaRepository.isOnWhatsapp.create({
168-
data: dataPayload,
169-
});
168+
try {
169+
await prismaRepository.isOnWhatsapp.create({
170+
data: dataPayload,
171+
});
172+
} catch (error: any) {
173+
// Check for unique constraint violation (Prisma error code P2002)
174+
if (
175+
error instanceof Prisma.PrismaClientKnownRequestError &&
176+
error.code === 'P2002' &&
177+
(error.meta?.target as string[])?.includes('remoteJid')
178+
) {
179+
logger.verbose(
180+
`[saveOnWhatsappCache] Race condition detected for ${remoteJid}, updating existing record instead.`,
181+
);
182+
await prismaRepository.isOnWhatsapp.update({
183+
where: { remoteJid: remoteJid },
184+
data: dataPayload,
185+
});
186+
} else {
187+
throw error;
188+
}
189+
}
170190
}
171191
} catch (e) {
172192
// Loga o erro mas não para a execução dos outros promises

0 commit comments

Comments
 (0)