Details
In @packages/api/src/extensions/channels/web/base-web-channel.ts around lines 168 - 190, The current enqueueMessageDispatch chains only channelEventBus.emitMessage, so ThreadService.resolveThreadForIncoming(req) can run concurrently for two near-simultaneous first messages on the same socket; move/gate thread resolution into the per-socket sequence by chaining the resolveThreadForIncoming call inside the existing webMessageQueue promise chain (i.e., replace or precede this.channelEventBus.emitMessage(event) with a then that first calls ThreadService.resolveThreadForIncoming(req) and awaits its result before emitting), ensuring. socketData.webMessageQueue covers thread resolution and dispatch; apply the same change to the other similar block handling socket messages (the other occurrence noted in the comment).
webMessageQueue only starts after resolveThreadForIncoming(). Two near-simultaneous first messages on the same socket can therefore race through thread resolution before either request is chained. Since ThreadService.resolveThreadForIncoming() mutates thread state (touch/close/create), that can ack different thread_ids or split one conversation across multiple threads. Please gate thread resolution with the same per-socket sequence, or add subscriber-level locking/transactionality around thread resolution. A concurrent two-message regression test on a fresh session would catch this.
Details
In
@packages/api/src/extensions/channels/web/base-web-channel.tsaround lines 168 - 190, The current enqueueMessageDispatch chains only channelEventBus.emitMessage, so ThreadService.resolveThreadForIncoming(req) can run concurrently for two near-simultaneous first messages on the same socket; move/gate thread resolution into the per-socket sequence by chaining the resolveThreadForIncoming call inside the existing webMessageQueue promise chain (i.e., replace or precede this.channelEventBus.emitMessage(event) with a then that first calls ThreadService.resolveThreadForIncoming(req) and awaits its result before emitting), ensuring. socketData.webMessageQueue covers thread resolution and dispatch; apply the same change to the other similar block handling socket messages (the other occurrence noted in the comment).webMessageQueue only starts after resolveThreadForIncoming(). Two near-simultaneous first messages on the same socket can therefore race through thread resolution before either request is chained. Since ThreadService.resolveThreadForIncoming() mutates thread state (touch/close/create), that can ack different thread_ids or split one conversation across multiple threads. Please gate thread resolution with the same per-socket sequence, or add subscriber-level locking/transactionality around thread resolution. A concurrent two-message regression test on a fresh session would catch this.