From 40c27ed90fc63dffa6ef6800e95047147d6e2a59 Mon Sep 17 00:00:00 2001 From: Jannis Braun <151788261+TheZwiss@users.noreply.github.com> Date: Tue, 5 May 2026 20:52:05 +0200 Subject: [PATCH] fix(chat): apply loadMessages dedup to force=true callers as well useWebSocket's ready handler calls loadMessages(channelId, true) from two adjacent code paths in the same handler invocation (remote-space refresh + per-origin cache clearing). Both fired in parallel because force=true bypassed dedup, producing the duplicate /messages requests visible in playwright network traces even after the parallel-mount dedup landed. Coalescing force=true with an in-flight call is safe: the requests hit the same endpoint with the same params and would return the same data, and the force caller still gets a fresh result via the shared Promise. --- packages/web/src/stores/chatStore.ts | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/packages/web/src/stores/chatStore.ts b/packages/web/src/stores/chatStore.ts index c99a9b2c..79b246c7 100644 --- a/packages/web/src/stores/chatStore.ts +++ b/packages/web/src/stores/chatStore.ts @@ -179,12 +179,16 @@ export const useChatStore = create((set, get) => ({ // The remote WS ready handler will call loadMessages once the map is populated. if (!isDm && !useSpaceStore.getState().channelOriginMap.has(channelId)) return; - // Parallel-call dedup: if a non-forced load for this channel is already in - // flight, return that Promise instead of starting a second fetch. `force` - // bypasses the dedup because callers using it (WS reconnect) explicitly - // want a fresh fetch even if one is already pending. See `inFlightLoads` - // declaration for the full rationale. - if (!force) { + // Parallel-call dedup: if a load for this channel is already in flight, + // return that Promise instead of starting a second fetch. Applies to + // force=true callers as well — `useWebSocket`'s ready handler invokes + // `loadMessages(currentChannelId, true)` from two adjacent code paths + // (one for remote-instance space refresh, one for cache clearing) on every + // WS-ready event, and there's no value in two parallel fetches for the + // same channel: they hit the same endpoint with the same params and + // return the same data. Coalescing is safe; the force caller still gets a + // fresh result via the in-flight Promise. + { const existing = inFlightLoads.get(channelId); if (existing) return existing; }