diff --git a/src/Socket/chats.ts b/src/Socket/chats.ts index cd1a0ac5..45336f5e 100644 --- a/src/Socket/chats.ts +++ b/src/Socket/chats.ts @@ -41,7 +41,7 @@ import { newLTHashState, processSyncAction } from '../Utils' -import { makeMutex } from '../Utils/make-mutex' +import { makeMutex, makeKeyedMutex } from '../Utils/make-mutex' import processMessage from '../Utils/process-message' import { buildTcTokenFromJid } from '../Utils/tc-token-utils' import { @@ -74,8 +74,8 @@ export const makeChatsSocket = (config: SocketConfig) => { let syncState: SyncState = SyncState.Connecting - /** this mutex ensures that messages are processed in order */ - const messageMutex = makeMutex() + /** this mutex ensures that messages from the same chat are processed in order, while allowing parallel processing of messages from different chats */ + const messageMutex = makeKeyedMutex() /** this mutex ensures that receipts are processed in order */ const receiptMutex = makeMutex() diff --git a/src/Socket/messages-recv.ts b/src/Socket/messages-recv.ts index f7038bbd..4e798d12 100644 --- a/src/Socket/messages-recv.ts +++ b/src/Socket/messages-recv.ts @@ -1266,7 +1266,14 @@ export const makeMessagesRecvSocket = (config: SocketConfig) => { } try { - await messageMutex.mutex(async () => { + // Use KeyedMutex with remoteJid to allow parallel processing of messages from different chats + // while maintaining order for messages within the same chat + // Fallback: msg.key.id (unique per message) > 'unknown' (serializes all unknown messages) + const mutexKey = msg.key.remoteJid || (() => { + logger.warn({ msgId: msg.key.id, fromMe: msg.key.fromMe }, 'Missing remoteJid in message key, using msg.key.id as fallback') + return msg.key.id || 'unknown' + })() + await messageMutex.mutex(mutexKey, async () => { await decrypt() // message failed to decrypt if (msg.messageStubType === proto.WebMessageInfo.StubType.CIPHERTEXT && msg.category !== 'peer') { diff --git a/src/Socket/messages-send.ts b/src/Socket/messages-send.ts index 58339125..a767ec3c 100644 --- a/src/Socket/messages-send.ts +++ b/src/Socket/messages-send.ts @@ -1639,7 +1639,11 @@ export const makeMessagesSocket = (config: SocketConfig) => { // Emit own event for album root if configured if (config.emitOwnEvents) { process.nextTick(async () => { - await messageMutex.mutex(() => upsertMessage(albumRootMsg, 'append')) + const mutexKey = albumRootMsg.key.remoteJid || (() => { + logger.warn({ msgId: albumRootMsg.key.id }, 'Missing remoteJid in albumRootMsg, using msg.key.id as fallback') + return albumRootMsg.key.id || 'unknown' + })() + await messageMutex.mutex(mutexKey, () => upsertMessage(albumRootMsg, 'append')) }) } @@ -1732,7 +1736,11 @@ export const makeMessagesSocket = (config: SocketConfig) => { // Emit own event if configured if (config.emitOwnEvents) { process.nextTick(async () => { - await messageMutex.mutex(() => upsertMessage(mediaMsg, 'append')) + const mutexKey = mediaMsg.key.remoteJid || (() => { + logger.warn({ msgId: mediaMsg.key.id }, 'Missing remoteJid in mediaMsg, using msg.key.id as fallback') + return mediaMsg.key.id || 'unknown' + })() + await messageMutex.mutex(mutexKey, () => upsertMessage(mediaMsg, 'append')) }) } @@ -1931,7 +1939,11 @@ export const makeMessagesSocket = (config: SocketConfig) => { }) if (config.emitOwnEvents) { process.nextTick(async () => { - await messageMutex.mutex(() => upsertMessage(fullMsg, 'append')) + const mutexKey = fullMsg.key.remoteJid || (() => { + logger.warn({ msgId: fullMsg.key.id }, 'Missing remoteJid in fullMsg, using msg.key.id as fallback') + return fullMsg.key.id || 'unknown' + })() + await messageMutex.mutex(mutexKey, () => upsertMessage(fullMsg, 'append')) }) }