fix: prevent ghost voice users after server restart
Replace the stale-flag-based voice re-registration in the WS ready handler with a server-authoritative check. If the server's voiceStates doesn't include us (server restarted, lost in-memory voiceRooms), cleanly tear down the LiveKit session via leaveVoice() + disconnect(). If the server still knows about us (WS blip), do nothing.
This commit is contained in:
@@ -267,20 +267,24 @@ function handleEvent(origin: string, event: ServerEvent): void {
|
|||||||
// at broadcast and hardware time.
|
// at broadcast and hardware time.
|
||||||
}
|
}
|
||||||
|
|
||||||
// Re-register in voice channel after WS reconnect — the server lost
|
// Server-authoritative voice session check: if we had a voice connection
|
||||||
// voice state on restart, so we must tell it we're still connected.
|
// but the server's voiceStates doesn't include us (server restarted and
|
||||||
// GUARD: Only re-register if LiveKit is actually connected. Background
|
// lost in-memory voiceRooms), tear down the stale LiveKit session cleanly.
|
||||||
// tabs can reconnect WS but not LiveKit — sending voice_join without
|
// If the server still knows about us (WS blip, not a restart), do nothing —
|
||||||
// an active media plane would create ghost users in the sidebar.
|
// useLiveKit's ConnectionStateChanged handler will re-register if needed.
|
||||||
{
|
{
|
||||||
const { currentVoiceChannelId, isLiveKitConnected } = useVoiceStore.getState();
|
const { currentVoiceChannelId } = useVoiceStore.getState();
|
||||||
if (currentVoiceChannelId && isLiveKitConnected) {
|
if (currentVoiceChannelId) {
|
||||||
const voiceOrigin = getChannelOrigin(currentVoiceChannelId);
|
const voiceOrigin = getChannelOrigin(currentVoiceChannelId);
|
||||||
if (voiceOrigin === origin) {
|
if (voiceOrigin === origin) {
|
||||||
const myId = event.user.id;
|
const serverKnowsUs = event.voiceStates?.[currentVoiceChannelId]?.includes(event.user.id);
|
||||||
if (myId) addVoiceUser(currentVoiceChannelId, myId);
|
if (!serverKnowsUs) {
|
||||||
wsSend({ type: 'voice_join', channelId: currentVoiceChannelId }, origin);
|
// leaveVoice() clears currentVoiceChannelId first to prevent
|
||||||
broadcastVoiceStatus(origin);
|
// AppLayout from auto-reconnecting (disconnect() fires with
|
||||||
|
// CLIENT_INITIATED which skips handleForceDisconnect).
|
||||||
|
useVoiceStore.getState().leaveVoice();
|
||||||
|
getActiveRoom()?.disconnect();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user