From 90c8d2a0f708f21d7a69222460aa0f37aca7c5d0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Leszko?= Date: Wed, 26 Jun 2024 10:42:42 +0200 Subject: [PATCH] selection: Clear known sessions if none of them has good enough latency score Problem: We never cleaned the known sessions, even if all of them had too low latency score to use; example of what sometimes happens: 1) Broadcaster accumulated 8 known sessions, but all had too low latency score 2) Session refresh was not triggered because we had a lot of knows session in the pool 3) At the same time, we didn't have sessions in unknown session pool 4) Selection checked that it cannot use the known session and tried to select from unknown sessions (but the pool was empty or there were no sessions fulfilling the condition of max price or perf score) --- server/selection.go | 11 ++++++---- server/selection_test.go | 47 ++++++++++++++++------------------------ 2 files changed, 26 insertions(+), 32 deletions(-) diff --git a/server/selection.go b/server/selection.go index c827034db6..985f2d2546 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 aa936ddb04..9699bb7af5 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())