fix(chatwoot-adapter): stop a migrated @lid contact's inbound from splitting its conversation#31
Merged
Merged
Conversation
…litting its conversation A contact whose Chatwoot conversation was mapped under <phone>@c.us and has since migrated to @lid arrives with chatId=@lid, misses the @c.us mapping in resolveConversation, and gets a duplicate conversation (thread split). The inbound mirror of the outbound fix in 0.4.0 (#615). - resolveConversation dual-looks-up: getByChat(raw) then getByChat(canonical) (via ctx.engine.canonicalChatId, best-effort), reusing the existing @c.us conversation instead of creating a duplicate. - The per-chat lock stays keyed on the RAW chatId, not the canonical one: canonicalChatId is non-deterministic (warm=@c.us / cold=@lid / needs a live engine), so a canonical lock key wouldn't reliably serialize two inbound and could double-create. The raw id is deterministic and already converges a migrated contact's inbound; canonicalization is used only for the lookup, and its call is raw-fallback-wrapped so it never throws and drops a message. - refreshContactName patches under the key the mapping lives under, so reusing a @c.us mapping via @lid records the name (no repeated updateContact). Best-effort: resolves after any reply to the contact, or on every inbound with OpenWA RESOLVE_LID_TO_PHONE=true (documented). chatwoot-adapter 0.5.1; no core change.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Stops a contact who has migrated to WhatsApp's
@lidaddressing from splitting into a duplicate Chatwoot conversation on the inbound path. This is the inbound mirror of the outbound fix shipped in 0.4.0 (#615).Problem
resolveConversationlooked up the mapping by the rawmsg.chatIdand created a new conversation on a miss. A contact whose conversation was mapped under<phone>@c.us(pre-migration) and has since migrated arrives withchatId = <lid>@lid, misses the@c.usmapping, and gets a second, duplicate conversation — the thread splits.Fix
Reuse the host
ctx.engine.canonicalChatIdresolver (@lid → <phone>@c.us, best-effort) for a dual lookup:getByChat(raw)thengetByChat(canonical). A migrated contact's inbound then lands in its existing@c.usconversation instead of a duplicate; a genuinely new chat still creates once.Deliberate design points (arrived at via review):
chatId, not the canonical id.canonicalChatIdis best-effort and non-deterministic (it returns@c.uswhen the lid→phone cache is warm,@lidwhen cold, and needs a live engine), so keying the lock on it would let two inbound for the same chat lock different keys and double-create. The raw id is deterministic and already converges a migrated contact's inbound. Canonicalization is used only for the lookup.canonicalChatIdcall is wrapped with a raw fallback, so it can never throw and drop a message before it is de-duplicated/queued (the retry drain re-relays messages whose WA session may be offline).refreshContactNamenow patches under the key the mapping actually lives under, so reusing a@c.usmapping via@lidrecords the synced name (no repeatedupdateContacton every later inbound).Cold-store residual
canonicalChatIdresolves only when the lid→phone mapping is known — after any outbound reply to the contact, or on every inbound when OpenWA'sRESOLVE_LID_TO_PHONE=trueis set (documented; it also helps the outbound path). A receive-only migrated contact on a default deployment can still create an@lidconversation until the store warms — same behavior as before the fix, now closable with that flag.Compatibility
Version
0.5.1(patch, bugfix). No core change (minOpenWAVersionstays 0.8.7). Non-@lidtraffic (@c.us, groups) is byte-for-byte unchanged.