-
Notifications
You must be signed in to change notification settings - Fork 886
fix(p2p): reclaim connTracker lastConnect entries once their window elapses #3918
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -83,3 +83,32 @@ func TestConnTracker(t *testing.T) { | |
| }) | ||
|
|
||
| } | ||
|
|
||
| // A connection that dies inside the window keeps its lastConnect entry, because | ||
| // the window has not elapsed and a reconnect still has to be refused. Nothing | ||
| // revisited those entries afterwards, so on a public listener every address whose | ||
| // connection was short-lived stayed in the map for the life of the process. | ||
| func TestConnTrackerShortLivedConnsDoNotAccumulate(t *testing.T) { | ||
| const conns = 100_000 | ||
|
|
||
| ct := newConnTracker(10, time.Millisecond) | ||
| for range conns { | ||
| ip := randLocalAddr() | ||
| require.NoError(t, ct.AddConn(ip)) | ||
| ct.RemoveConn(ip) | ||
| } | ||
|
|
||
| // Bounded by the addresses seen within one window rather than by every address | ||
| // seen. The margin is wide because the sweep is driven by elapsed time. | ||
| require.Less(t, len(ct.lastConnect), conns/10) | ||
| } | ||
|
|
||
| // Reclaiming entries must not let an address reconnect inside its window. | ||
| func TestConnTrackerSweepPreservesWindow(t *testing.T) { | ||
| ct := newConnTracker(10, time.Hour) | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [suggestion] With The case that exercises it needs an entry created after the last sweep but still inside its window when the next sweep fires — e.g. with a short window, prime |
||
| ip := randLocalAddr() | ||
|
|
||
| require.NoError(t, ct.AddConn(ip)) | ||
| ct.RemoveConn(ip) | ||
| require.Error(t, ct.AddConn(ip)) | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[suggestion] This bound is a function of loop throughput rather than of the sweep: the surviving entries are those added since the last sweep, i.e. roughly
window / per-iteration cost. At an estimated ~0.5–1µs per iteration that lands around 1–3k, comfortably under 10k, and-racein CI only widens the margin — but the relationship is inverted from what you want (a faster machine retains more), so the headroom shrinks precisely where the test is cheapest to run.You can make it deterministic and much stronger at the same time by forcing the final sweep instead of sampling mid-stream: after the loop,
time.Sleep(2 * time.Millisecond)thenAddConn/RemoveConnone fresh address. That call sweeps (nextSweephas certainly elapsed) and every loop entry is now older than the window, sorequire.Len(t, ct.lastConnect, 1)holds exactly, and it still fails without the sweep.