Give proper grace period when recorder is still in the room (#1547)

When a recorder is in the room, we would skip grace period due
to a bug with how LastLeftAt was set. This would cause RoomComposite
templates to exit immediately if the last participant in the room reconnects.
This commit is contained in:
David Zhao
2023-03-23 23:57:11 -07:00
committed by GitHub
parent d7750a60ec
commit d8356e012e
2 changed files with 22 additions and 16 deletions
+17 -13
View File
@@ -27,14 +27,18 @@ import (
const (
DefaultEmptyTimeout = 5 * 60 // 5m
DefaultRoomDepartureGrace = 20
AudioLevelQuantization = 8 // ideally power of 2 to minimize float decimal
AudioLevelQuantization = 8 // ideally power of 2 to minimize float decimal
invAudioLevelQuantization = 1.0 / AudioLevelQuantization
subscriberUpdateInterval = 3 * time.Second
dataForwardLoadBalanceThreshold = 20
)
var (
// var to allow unit test override
RoomDepartureGrace uint32 = 20
)
type broadcastOptions struct {
skipSource bool
immediate bool
@@ -464,6 +468,11 @@ func (r *Room) RemoveParticipant(identity livekit.ParticipantIdentity, pID livek
// send broadcast only if it's not already closed
sendUpdates := !p.IsDisconnected()
// remove all published tracks
for _, t := range p.GetPublishedTracks() {
r.trackManager.RemoveTrack(t)
}
p.OnTrackUpdated(nil)
p.OnTrackPublished(nil)
p.OnTrackUnpublished(nil)
@@ -476,11 +485,7 @@ func (r *Room) RemoveParticipant(identity livekit.ParticipantIdentity, pID livek
r.Logger.Debugw("closing participant for removal", "pID", p.ID(), "participant", p.Identity())
_ = p.Close(true, reason)
r.lock.RLock()
if len(r.participants) == 0 {
r.leftAt.Store(time.Now().Unix())
}
r.lock.RUnlock()
r.leftAt.Store(time.Now().Unix())
if sendUpdates {
if r.onParticipantChanged != nil {
@@ -597,16 +602,15 @@ func (r *Room) CloseIfEmpty() {
}
}
timeout := r.protoRoom.EmptyTimeout
var timeout uint32
var elapsed int64
if r.FirstJoinedAt() > 0 {
// exit 20s after
if r.FirstJoinedAt() > 0 && r.LastLeftAt() > 0 {
elapsed = time.Now().Unix() - r.LastLeftAt()
if timeout > DefaultRoomDepartureGrace {
timeout = DefaultRoomDepartureGrace
}
// need to give time in case participant is reconnecting
timeout = RoomDepartureGrace
} else {
elapsed = time.Now().Unix() - r.protoRoom.CreationTime
timeout = r.protoRoom.EmptyTimeout
}
r.lock.Unlock()
+5 -3
View File
@@ -33,6 +33,8 @@ func init() {
serverlogger.InitFromConfig(config.LoggingConfig{
Config: logger.Config{Level: "debug"},
})
// allow immediate closure in testing
RoomDepartureGrace = 1
}
var iceServersForRoom = []*livekit.ICEServer{{Urls: []string{"stun:stun.l.google.com:19302"}}}
@@ -59,11 +61,11 @@ func TestJoinedState(t *testing.T) {
require.LessOrEqual(t, s, rm.LastLeftAt())
})
t.Run("LastLeftAt should not be set when there are still participants in the room", func(t *testing.T) {
t.Run("LastLeftAt should be set when there are still participants in the room", func(t *testing.T) {
rm := newRoomWithParticipants(t, testRoomOpts{num: 2})
p0 := rm.GetParticipants()[0]
rm.RemoveParticipant(p0.Identity(), p0.ID(), types.ParticipantCloseReasonClientRequestLeave)
require.EqualValues(t, 0, rm.LastLeftAt())
require.Greater(t, rm.LastLeftAt(), int64(0))
})
}
@@ -349,7 +351,7 @@ func TestRoomClosure(t *testing.T) {
rm.protoRoom.EmptyTimeout = 0
rm.RemoveParticipant(p.Identity(), p.ID(), types.ParticipantCloseReasonClientRequestLeave)
time.Sleep(defaultDelay)
time.Sleep(time.Duration(RoomDepartureGrace)*time.Second + defaultDelay)
rm.CloseIfEmpty()
require.Len(t, rm.GetParticipants(), 0)