fix(inbound): avoid HOL blocking on malformed-JID fallback bucket

Addresses Copilot review on PR #392.

The previous fallback `normalizedChatId || 'unknown'` funneled every
message with a missing or malformed chat id into a single global queue
on `postUpsertMutex`, head-of-line blocking unrelated malformed inputs
behind a shared bucket.

Prefer `msg.key?.id` over the constant: it is unique per message so
unrelated malformed inputs no longer serialize together, while valid
messages continue to hit the normalized chat-id path — preserving the
per-chat ordering guarantee where it actually matters. The CodeRabbit
concern about `msg.key.id` fragmenting the queue applied to the primary
key derivation (where ordering matters); here it is purely a fallback
for a corruption edge case where there is no chat to order by anyway.
This commit is contained in:
Renato Alcara
2026-04-26 16:03:07 -03:00
parent 942f4ae2c9
commit dc24e60e5b
+8 -6
View File
@@ -1486,14 +1486,16 @@ export const makeChatsSocket = (config: SocketConfig) => {
// Use getChatId + jidNormalizedUser so the mutex key matches the chat-id
// scheme processMessage uses for chat updates (broadcasts target the
// participant). Falling back to a constant bucket avoids fragmenting the
// queue when the key is malformed.
// Compute the normalized value first then apply the fallback: a malformed
// but truthy rawChatId (e.g. missing `@`) makes jidNormalizedUser return
// '', which would otherwise pass through as an empty mutex key.
// participant). When getChatId/jidNormalizedUser yields nothing usable
// (missing or malformed JID), prefer a message-derived fallback over a
// single global 'unknown' bucket — that bucket would head-of-line block
// every malformed message behind a shared queue. msg.key.id is unique
// per message so unrelated malformed inputs no longer serialize together;
// for valid messages we still hit the normalized chat-id path, so the
// per-chat ordering guarantee is unchanged where it matters.
const rawChatId = getChatId(msg.key)
const normalizedChatId = rawChatId ? jidNormalizedUser(rawChatId) : ''
const postUpsertChatId = normalizedChatId || 'unknown'
const postUpsertChatId = normalizedChatId || msg.key?.id || 'unknown'
// Wrap in `postUpsertMutex(chatId)` (a SEPARATE keyed mutex from the outer
// `messageMutex` held by the inbound caller) so per-chat ordering of