fix: Chats doesn't sync for multi client users
This commit is contained in:
@@ -121,6 +121,8 @@ Each signaling URL gets its own `SignalingManager` (one WebSocket each). `Signal
|
||||
|
||||
**Identify-before-join invariant.** The server drops any `join_server` / `view_server` that arrives on a connection that has not yet `identify`-ed, so a join that races ahead of identify is silently lost and the user never appears in the presence roster. On every (re)connect, `SignalingManager.reIdentifyAndRejoin` therefore re-`identify`s and only then re-joins. For this to work the manager's credential lookup (`SignalingTransportHandler.getIdentifyCredentialsForSignalUrl`) must resolve a credential as soon as one exists for that signal URL — it falls back to the credential store when the per-URL identify cache has not been populated yet. Do not narrow that lookup to only the in-memory cache; doing so lets a fresh socket emit a join before any identify and reintroduces the dropped-presence bug.
|
||||
|
||||
The server side enforces this ordering too: `handleWebSocketMessage` serializes messages per connection (a promise chain keyed by connection id in `server/src/websocket/handler.ts`). `identify` awaits a session-token DB lookup, and `identify` + `join_server` sent back-to-back often arrive in the same TCP segment; without serialization the join was evaluated mid-identify, rejected with `auth_required`, and the room membership was silently lost — the client then never received `user_joined` / `chat_message` broadcasts for that room even though same-account `account_sync` kept working, which is exactly the "chats don't sync for multi-client users" failure mode. Do not process websocket messages for one connection concurrently.
|
||||
|
||||
Room affinity is authoritative at this layer as well. The renderer repairs each room's saved `sourceId` / `sourceUrl` from server-directory responses and routes `join_server`, `view_server`, and room-scoped signaling traffic to that room's signaling URL first. If that route fails, alternate endpoints can be tried temporarily, but server-scoped raw messages are no longer broadcast to every connected signaling manager when the route is unknown.
|
||||
|
||||
Server-relayed fallbacks are intentionally narrow. Room chat (`chat_message`), direct-message events (`direct-message`, `direct-message-status`, `direct-message-mutation`), and voice presence (`voice_state`) may flow over signaling so users can still see written chat and voice roster state while P2P data channels are down. Media, attachments, message inventory sync, screen/camera state, and plugin data-channel traffic remain peer-plane responsibilities.
|
||||
@@ -170,7 +172,7 @@ Browsers do not reliably fire WebSocket close events during page refresh or navi
|
||||
|
||||
Multi-device sessions keep **multiple** open connections for the same `oderId` (different `clientInstanceId` values per tab/device). Server broadcasts exclude only the sending **connection id**, not the whole identity, so chat/typing/voice-state updates reach every logged-in device. Presence `user_joined` / `user_left` broadcasts still exclude the whole identity so other users never see duplicate join/leave events.
|
||||
|
||||
Account-owned state (saved servers, friends, profile avatar/card text, custom emoji library, server icons, message edits/reactions) syncs through **`account_sync`** WebSocket messages. The client wraps relayable P2P broadcast events and the server forwards them to other connections for the same identity via `notifyOtherConnectionsForOderId`. When a new device identifies, existing connections receive `account_sync_peer_online` and push a full snapshot.
|
||||
Account-owned state (saved servers, friends, profile avatar/card text, custom emoji library, server icons, message edits/reactions, **chat message creates/revisions**) syncs through **`account_sync`** WebSocket messages. The client wraps relayable P2P broadcast events and the server forwards them to other connections for the same identity via `notifyOtherConnectionsForOderId`. When a new device identifies, existing connections receive `account_sync_peer_online` and push a full snapshot including chunked `chat-sync-batch` history for every saved room.
|
||||
|
||||
RTC offers/answers/ICE are routed to the connection marked `voiceActive` for the target user (fallback: any open connection). Voice ownership is tracked per connection from `voice_state` payloads that include `clientInstanceId`.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user