mirror of
https://github.com/livekit/livekit.git
synced 2026-10-15 15:30:14 +00:00
rtc: keep update cache eviction order when listing recent disconnects (#4975)
GetRecentlyDisconnectedParticipants walked the participant update cache with Get, which moves each entry to the front of the LRU. Walking from newest to oldest left the cache in reverse order, so after a reconnect the next updates evicted the most recently updated participants first. In a room where the subscriber has tracked 128 or more participants, a participant that had just disconnected was then dropped from the cache and a later reconnect did not report it as disconnected, and the out-of-order version check was lost for recently updated participants. Use Peek, which reads an entry without changing its recency.
This commit is contained in:
@@ -305,6 +305,42 @@ func TestOutOfOrderUpdates(t *testing.T) {
|
||||
require.Equal(t, "second update", sent.GetUpdate().Participants[0].Metadata)
|
||||
}
|
||||
|
||||
func TestRecentlyDisconnectedKeepsUpdateOrder(t *testing.T) {
|
||||
p := newParticipantForTest("test")
|
||||
|
||||
// fill the update cache (128 entries), the last update is a disconnect
|
||||
const cacheSize = 128
|
||||
for i := range cacheSize {
|
||||
state := livekit.ParticipantInfo_ACTIVE
|
||||
if i == cacheSize-1 {
|
||||
state = livekit.ParticipantInfo_DISCONNECTED
|
||||
}
|
||||
require.NoError(t, p.SendParticipantUpdate([]*livekit.ParticipantInfo{{
|
||||
Sid: fmt.Sprintf("PA_%d", i),
|
||||
Identity: fmt.Sprintf("p%d", i),
|
||||
Version: 1,
|
||||
State: state,
|
||||
}}))
|
||||
}
|
||||
|
||||
disconnected := p.GetRecentlyDisconnectedParticipants()
|
||||
require.Len(t, disconnected, 1)
|
||||
require.Equal(t, "PA_127", disconnected[0].Sid)
|
||||
|
||||
// an update for a new participant evicts the least recently updated entry,
|
||||
// not the disconnect that was just reported
|
||||
require.NoError(t, p.SendParticipantUpdate([]*livekit.ParticipantInfo{{
|
||||
Sid: "PA_new",
|
||||
Identity: "new",
|
||||
Version: 1,
|
||||
State: livekit.ParticipantInfo_ACTIVE,
|
||||
}}))
|
||||
|
||||
disconnected = p.GetRecentlyDisconnectedParticipants()
|
||||
require.Len(t, disconnected, 1)
|
||||
require.Equal(t, "PA_127", disconnected[0].Sid)
|
||||
}
|
||||
|
||||
// after disconnection, things should continue to function and not panic
|
||||
func TestDisconnectTiming(t *testing.T) {
|
||||
t.Run("Negotiate doesn't panic after channel closed", func(t *testing.T) {
|
||||
|
||||
@@ -268,7 +268,8 @@ func (p *ParticipantImpl) GetRecentlyDisconnectedParticipants() []*livekit.Parti
|
||||
p.updateLock.Lock()
|
||||
keys := p.updateCache.Keys()
|
||||
for i := len(keys) - 1; i >= 0; i-- {
|
||||
if info, ok := p.updateCache.Get(keys[i]); ok {
|
||||
// Peek, as Get would move each entry to the front and reverse the eviction order
|
||||
if info, ok := p.updateCache.Peek(keys[i]); ok {
|
||||
if info.updatedAt.Before(lastSignalAt) {
|
||||
continue
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user