mirror of
https://github.com/J3vb/OwnCord.git
synced 2026-09-03 03:50:00 +03:00
fix(ws): don't clean voice state when a replacement connection exists
readPump teardown always ran handleVoiceLeave, trusting the joined_at guard in LeaveVoiceChannelIfMatch to protect replacement sessions. On reconnect the voice session TRANSFERS to the replacement client with the same joined_at, so the guard cannot tell the two apart: whenever teardown snapshotted voiceChID before the transfer zeroed it, the old connection deleted the replacement's voice_state row (flaked on the Windows CI runner as TestServeWS_Reconnect_PreservesVoiceState). Gate voice cleanup on !replaced — the same condition the presence-offline broadcast four lines down already uses. A genuinely final disconnect behaves exactly as before, and a stale row from a crashed replacement is still swept by the fresh-connect cleanup. Also deflake TestHub_ConcurrentRegisterUnregister: poll for quiescence with a deadline instead of a fixed 50ms sleep that loses to the -race scheduler on slow runners. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -489,7 +489,12 @@ func TestHub_ConcurrentRegisterUnregister(t *testing.T) {
|
||||
}(i)
|
||||
}
|
||||
wg.Wait()
|
||||
time.Sleep(50 * time.Millisecond)
|
||||
// The hub loop drains register/unregister asynchronously; poll instead of
|
||||
// a fixed sleep, which flakes under -race on slow runners.
|
||||
deadline := time.Now().Add(5 * time.Second)
|
||||
for hub.ClientCount() != 0 && time.Now().Before(deadline) {
|
||||
time.Sleep(10 * time.Millisecond)
|
||||
}
|
||||
if hub.ClientCount() != 0 {
|
||||
t.Errorf("expected 0 clients after concurrent churn, got %d", hub.ClientCount())
|
||||
}
|
||||
|
||||
+7
-3
@@ -411,9 +411,13 @@ func readPump(ctx context.Context, conn *websocket.Conn, hub *Hub, c *Client) {
|
||||
voiceChID := c.getVoiceChID()
|
||||
replaced := hub.unregisterNow(c)
|
||||
if c.user != nil {
|
||||
// Always clean up voice state — LeaveVoiceChannelIfMatch uses a
|
||||
// join_token guard so it won't remove a replacement client's session.
|
||||
if voiceChID != 0 {
|
||||
// Clean up voice state only when this was the user's final
|
||||
// connection. A replacement connection owns the (transferred)
|
||||
// voice session, and the join_token guard cannot tell the
|
||||
// difference — the transfer keeps the same joined_at — so
|
||||
// cleaning here would delete the replacement's DB row whenever
|
||||
// teardown snapshots voiceChID before the transfer zeroes it.
|
||||
if voiceChID != 0 && !replaced {
|
||||
hub.handleVoiceLeave(ctx, c)
|
||||
}
|
||||
c.mu.Lock()
|
||||
|
||||
Reference in New Issue
Block a user