Ensure older participant session update does not go out after a newer (#1372)

* Ensure older participant session update does not go out after a newer
session has joined.

* fix tests

* change comment

* do not send older version
This commit is contained in:
Raja Subramanian
2023-02-03 00:30:11 +05:30
committed by GitHub
parent 8c513a1fc5
commit 037ae572d9
2 changed files with 39 additions and 11 deletions
+22 -10
View File
@@ -900,6 +900,10 @@ func (r *Room) broadcastParticipantState(p types.LocalParticipant, opts broadcas
}
func (r *Room) sendParticipantUpdates(updates []*livekit.ParticipantInfo) {
if len(updates) == 0 {
return
}
for _, op := range r.GetParticipants() {
err := op.SendParticipantUpdate(updates)
if err != nil {
@@ -960,16 +964,24 @@ func (r *Room) pushAndDequeueUpdates(pi *livekit.ParticipantInfo, isImmediate bo
shouldSend := isImmediate || pi.IsPublisher
if existing != nil {
if pi.Sid != existing.Sid {
// session change, need to send immediately
isImmediate = true
existing.State = livekit.ParticipantInfo_DISCONNECTED
updates = append(updates, existing)
} else if pi.Version < existing.Version {
// out of order update
return nil
} else if shouldSend {
updates = append(updates, existing)
if pi.Sid == existing.Sid {
// same participant session
if pi.Version < existing.Version {
// out of order update
return nil
}
} else {
// different participant sessions
if existing.JoinedAt < pi.JoinedAt {
// existing is older, synthesize a DISCONNECT for older and
// send immediately along with newer session to signal switch
shouldSend = true
existing.State = livekit.ParticipantInfo_DISCONNECTED
updates = append(updates, existing)
} else {
// older session update, newer session has already become active, so nothing to do
return nil
}
}
}
+17 -1
View File
@@ -211,28 +211,33 @@ func TestPushAndDequeueUpdates(t *testing.T) {
Sid: "1",
IsPublisher: true,
Version: 1,
JoinedAt: 0,
}
publisher1v2 := &livekit.ParticipantInfo{
Identity: identity,
Sid: "1",
IsPublisher: true,
Version: 2,
JoinedAt: 1,
}
publisher2 := &livekit.ParticipantInfo{
Identity: identity,
Sid: "2",
IsPublisher: true,
Version: 1,
JoinedAt: 2,
}
subscriber1v1 := &livekit.ParticipantInfo{
Identity: identity,
Sid: "1",
Version: 1,
JoinedAt: 0,
}
subscriber1v2 := &livekit.ParticipantInfo{
Identity: identity,
Sid: "1",
Version: 2,
JoinedAt: 1,
}
requirePIEquals := func(t *testing.T, a, b *livekit.ParticipantInfo) {
@@ -267,6 +272,17 @@ func TestPushAndDequeueUpdates(t *testing.T) {
requirePIEquals(t, subscriber1v2, queued)
},
},
{
name: "both versions updates when immediate",
pi: subscriber1v2,
existing: subscriber1v1,
immediate: true,
expected: []*livekit.ParticipantInfo{subscriber1v2},
validate: func(t *testing.T, rm *Room, _ []*livekit.ParticipantInfo) {
queued := rm.batchedUpdates[livekit.ParticipantIdentity(identity)]
require.Nil(t, queued)
},
},
{
name: "out of order updates are rejected",
pi: subscriber1v1,
@@ -294,7 +310,7 @@ func TestPushAndDequeueUpdates(t *testing.T) {
name: "when switching to publisher, queue is cleared",
pi: publisher1v2,
existing: subscriber1v1,
expected: []*livekit.ParticipantInfo{subscriber1v1, publisher1v2},
expected: []*livekit.ParticipantInfo{publisher1v2},
validate: func(t *testing.T, rm *Room, updates []*livekit.ParticipantInfo) {
require.Empty(t, rm.batchedUpdates)
},