Skip to content

Commit c60e8a2

Browse files
authored
Evict recentlyAccepted blocks based on wall-clock time (#3460)
1 parent d7c9423 commit c60e8a2

File tree

2 files changed

+25
-17
lines changed

2 files changed

+25
-17
lines changed

utils/window/window.go

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ type window[T any] struct {
3333
minSize int
3434

3535
// mutex for synchronization
36-
lock sync.RWMutex
36+
lock sync.Mutex
3737
// elements in the window
3838
elements buffer.Deque[node[T]]
3939
}
@@ -77,8 +77,9 @@ func (w *window[T]) Add(value T) {
7777

7878
// Oldest returns the oldest element in the window.
7979
func (w *window[T]) Oldest() (T, bool) {
80-
w.lock.RLock()
81-
defer w.lock.RUnlock()
80+
w.lock.Lock()
81+
defer w.lock.Unlock()
82+
w.removeStaleNodes()
8283

8384
oldest, ok := w.elements.PeekLeft()
8485
if !ok {
@@ -89,8 +90,9 @@ func (w *window[T]) Oldest() (T, bool) {
8990

9091
// Length returns the number of elements in the window.
9192
func (w *window[T]) Length() int {
92-
w.lock.RLock()
93-
defer w.lock.RUnlock()
93+
w.lock.Lock()
94+
defer w.lock.Unlock()
95+
w.removeStaleNodes()
9496

9597
return w.elements.Len()
9698
}
@@ -100,13 +102,9 @@ func (w *window[T]) removeStaleNodes() {
100102
// If we're beyond the expiry threshold, removeStaleNodes this node from our
101103
// window. Nodes are guaranteed to be strictly increasing in entry time,
102104
// so we can break this loop once we find the first non-stale one.
103-
newest, ok := w.elements.PeekRight()
104-
if !ok {
105-
return
106-
}
107105
for w.elements.Len() > w.minSize {
108106
oldest, ok := w.elements.PeekLeft()
109-
if !ok || newest.entryTime.Sub(oldest.entryTime) <= w.ttl {
107+
if !ok || w.clock.Time().Sub(oldest.entryTime) <= w.ttl {
110108
return
111109
}
112110
_, _ = w.elements.PopLeft()

utils/window/window_test.go

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,7 @@ func TestTTLAdd(t *testing.T) {
127127
require.Equal(4, oldest)
128128
}
129129

130-
// TestTTLLength tests that elements are not evicted on Length
130+
// TestTTLLength tests that elements are evicted on Length
131131
func TestTTLLength(t *testing.T) {
132132
require := require.New(t)
133133

@@ -156,10 +156,10 @@ func TestTTLLength(t *testing.T) {
156156
clock.Set(start.Add(testTTL + time.Second))
157157

158158
// No more elements should be present in the window.
159-
require.Equal(3, window.Length())
159+
require.Equal(0, window.Length())
160160
}
161161

162-
// TestTTLOldest tests that stale elements are not evicted on calling Oldest
162+
// TestTTLOldest tests that stale elements are evicted on calling Oldest
163163
func TestTTLOldest(t *testing.T) {
164164
require := require.New(t)
165165

@@ -188,15 +188,25 @@ func TestTTLOldest(t *testing.T) {
188188
require.Equal(1, oldest)
189189
require.Equal(3, window.elements.Len())
190190

191-
// Now we're one second past the ttl of 10 seconds as defined in testTTL,
191+
// Now we're one second before the ttl of 10 seconds as defined in testTTL,
192192
// so all existing elements shoud still exist.
193-
clock.Set(start.Add(testTTL + time.Second))
193+
// Add 4 to the window to make it:
194+
// [1, 2, 3, 4]
195+
clock.Set(start.Add(testTTL - time.Second))
196+
window.Add(4)
194197

195-
// Now there should be three elements in the window
196198
oldest, ok = window.Oldest()
197199
require.True(ok)
198200
require.Equal(1, oldest)
199-
require.Equal(3, window.elements.Len())
201+
require.Equal(4, window.elements.Len())
202+
203+
// Now we're one second past the ttl of the initial 3 elements
204+
// call to oldest should now evict 1,2,3 and return 4.
205+
clock.Set(start.Add(testTTL + time.Second))
206+
oldest, ok = window.Oldest()
207+
require.True(ok)
208+
require.Equal(4, oldest)
209+
require.Equal(1, window.elements.Len())
200210
}
201211

202212
// Tests that we bound the amount of elements in the window

0 commit comments

Comments
 (0)