diff --git a/server/selection.go b/server/selection.go index c827034db..985f2d254 100644 --- a/server/selection.go +++ b/server/selection.go @@ -135,12 +135,15 @@ func (s *MinLSSelector) Select(ctx context.Context) *BroadcastSession { return s.selectUnknownSession(ctx) } - minSess := sess.(*BroadcastSession) - if minSess.LatencyScore > s.minLS && len(s.unknownSessions) > 0 { - return s.selectUnknownSession(ctx) + lowestLatencyScoreKnownSession := heap.Pop(s.knownSessions).(*BroadcastSession) + if lowestLatencyScoreKnownSession.LatencyScore <= s.minLS { + // known session has good enough latency score, use it + return lowestLatencyScoreKnownSession } - return heap.Pop(s.knownSessions).(*BroadcastSession) + // known session does not have good enough latency score, clear the heap and use unknown session + s.knownSessions = &sessHeap{} + return s.selectUnknownSession(ctx) } // Size returns the number of sessions stored by the selector diff --git a/server/selection_test.go b/server/selection_test.go index aa936ddb0..9699bb7af 100644 --- a/server/selection_test.go +++ b/server/selection_test.go @@ -183,48 +183,39 @@ func TestMinLSSelector(t *testing.T) { assert.Equal(sel.Size(), 2) assert.Equal(len(sel.unknownSessions), 2) - // Set sess1.LatencyScore to not be good enough - sess1.LatencyScore = 1.1 + // Set sess1.LatencyScore to good enough + sess1.LatencyScore = 0.9 sel.Complete(sess1) assert.Equal(sel.Size(), 3) assert.Equal(len(sel.unknownSessions), 2) assert.Equal(sel.knownSessions.Len(), 1) - // Select from unknownSessions - sess2 := sel.Select(context.TODO()) + // Select sess1 because it's a known session with good enough latency score + sess := sel.Select(context.TODO()) assert.Equal(sel.Size(), 2) - assert.Equal(len(sel.unknownSessions), 1) - assert.Equal(sel.knownSessions.Len(), 1) + assert.Equal(len(sel.unknownSessions), 2) + assert.Equal(sel.knownSessions.Len(), 0) - // Set sess2.LatencyScore to be good enough - sess2.LatencyScore = .9 - sel.Complete(sess2) + // Set sess.LatencyScore to not be good enough + sess.LatencyScore = 1.1 + sel.Complete(sess) assert.Equal(sel.Size(), 3) - assert.Equal(len(sel.unknownSessions), 1) - assert.Equal(sel.knownSessions.Len(), 2) + assert.Equal(len(sel.unknownSessions), 2) + assert.Equal(sel.knownSessions.Len(), 1) - // Select from knownSessions - knownSess := sel.Select(context.TODO()) + // Select from unknownSessions, because sess2 does not have a good enough latency score + sess = sel.Select(context.TODO()) + sess.LatencyScore = 1.1 + sel.Complete(sess) assert.Equal(sel.Size(), 2) assert.Equal(len(sel.unknownSessions), 1) assert.Equal(sel.knownSessions.Len(), 1) - assert.Equal(knownSess, sess2) - // Set knownSess.LatencyScore to not be good enough - knownSess.LatencyScore = 1.1 - sel.Complete(knownSess) - // Clear unknownSessions - sess := sel.Select(context.TODO()) - sess.LatencyScore = 2.1 - sel.Complete(sess) - assert.Equal(len(sel.unknownSessions), 0) - assert.Equal(sel.knownSessions.Len(), 3) - - // Select from knownSessions - knownSess = sel.Select(context.TODO()) - assert.Equal(sel.Size(), 2) + // Select the last unknown session + sess = sel.Select(context.TODO()) + assert.Equal(sel.Size(), 0) assert.Equal(len(sel.unknownSessions), 0) - assert.Equal(sel.knownSessions.Len(), 2) + assert.Equal(sel.knownSessions.Len(), 0) sel.Clear() assert.Zero(sel.Size())