-
Notifications
You must be signed in to change notification settings - Fork 14
Backport 18967 to v21 branch connection pool bugfix #201
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
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 | ||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -1280,3 +1280,88 @@ | |||||||||||||
| require.EqualValues(t, 0, state.open.Load()) | ||||||||||||||
| } | ||||||||||||||
| } | ||||||||||||||
|
|
||||||||||||||
| // TestIdleTimeoutConnectionLeak checks for leaked connections after idle timeout | ||||||||||||||
| func TestIdleTimeoutConnectionLeak(t *testing.T) { | ||||||||||||||
| var state TestState | ||||||||||||||
|
|
||||||||||||||
| // Slow connection creation to ensure idle timeout happens during reopening | ||||||||||||||
| state.chaos.delayConnect = 300 * time.Millisecond | ||||||||||||||
|
|
||||||||||||||
| p := NewPool(&Config[*TestConn]{ | ||||||||||||||
| Capacity: 2, | ||||||||||||||
| IdleTimeout: 50 * time.Millisecond, | ||||||||||||||
| LogWait: state.LogWait, | ||||||||||||||
| }).Open(newConnector(&state), nil) | ||||||||||||||
|
|
||||||||||||||
| getCtx, cancel := context.WithTimeout(t.Context(), 500*time.Millisecond) | ||||||||||||||
|
Check failure on line 1297 in go/pools/smartconnpool/pool_test.go
|
||||||||||||||
| defer cancel() | ||||||||||||||
|
|
||||||||||||||
| // Get and return two connections | ||||||||||||||
| conn1, err := p.Get(getCtx, nil) | ||||||||||||||
| require.NoError(t, err) | ||||||||||||||
|
|
||||||||||||||
| conn2, err := p.Get(getCtx, nil) | ||||||||||||||
| require.NoError(t, err) | ||||||||||||||
|
|
||||||||||||||
| p.put(conn1) | ||||||||||||||
| p.put(conn2) | ||||||||||||||
|
|
||||||||||||||
| // At this point: Active=2, InUse=0, Available=2 | ||||||||||||||
| require.EqualValues(t, 2, p.Active()) | ||||||||||||||
| require.EqualValues(t, 0, p.InUse()) | ||||||||||||||
| require.EqualValues(t, 2, p.Available()) | ||||||||||||||
|
|
||||||||||||||
| // Wait for idle timeout to kick in and start expiring connections | ||||||||||||||
| require.EventuallyWithT(t, func(c *assert.CollectT) { | ||||||||||||||
| // Check the actual number of currently open connections | ||||||||||||||
| assert.Equal(c, int64(2), state.open.Load()) | ||||||||||||||
| // Check the total number of closed connections | ||||||||||||||
| assert.Equal(c, int64(1), state.close.Load()) | ||||||||||||||
| }, 100*time.Millisecond, 10*time.Millisecond) | ||||||||||||||
|
|
||||||||||||||
| // At this point, the idle timeout worker has expired the connections | ||||||||||||||
| // and is trying to reopen them (which takes 300ms due to delayConnect) | ||||||||||||||
|
|
||||||||||||||
| // Try to get connections while they're being reopened | ||||||||||||||
| // This should trigger the bug where connections get discarded | ||||||||||||||
| for i := 0; i < 2; i++ { | ||||||||||||||
| getCtx, cancel := context.WithTimeout(t.Context(), 50*time.Millisecond) | ||||||||||||||
|
Check failure on line 1329 in go/pools/smartconnpool/pool_test.go
|
||||||||||||||
|
||||||||||||||
| defer cancel() | ||||||||||||||
|
|
||||||||||||||
| conn, err := p.Get(getCtx, nil) | ||||||||||||||
| require.NoError(t, err) | ||||||||||||||
|
|
||||||||||||||
| p.put(conn) | ||||||||||||||
| } | ||||||||||||||
|
|
||||||||||||||
| // Wait a moment for all reopening to complete | ||||||||||||||
| require.EventuallyWithT(t, func(c *assert.CollectT) { | ||||||||||||||
| // Check the actual number of currently open connections | ||||||||||||||
| require.Equal(c, int64(2), state.open.Load()) | ||||||||||||||
| // Check the total number of closed connections | ||||||||||||||
| require.Equal(c, int64(2), state.close.Load()) | ||||||||||||||
|
Comment on lines
+1341
to
+1343
|
||||||||||||||
| require.Equal(c, int64(2), state.open.Load()) | |
| // Check the total number of closed connections | |
| require.Equal(c, int64(2), state.close.Load()) | |
| assert.Equal(c, int64(2), state.open.Load()) | |
| // Check the total number of closed connections | |
| assert.Equal(c, int64(2), state.close.Load()) |
Check failure on line 1353 in go/pools/smartconnpool/pool_test.go
GitHub Actions / Static Code Checks Etc
t.Context undefined (type *testing.T has no field or method Context, but does have unexported field context) (typecheck)
Check failure on line 1353 in go/pools/smartconnpool/pool_test.go
GitHub Actions / Static Code Checks Etc
t.Context undefined (type *testing.T has no field or method Context, but does have unexported field context) (typecheck)
Check failure on line 1353 in go/pools/smartconnpool/pool_test.go
GitHub Actions / Unit Test (mysql57)
t.Context undefined (type *testing.T has no field or method Context, but does have unexported field context)
Check failure on line 1353 in go/pools/smartconnpool/pool_test.go
GitHub Actions / Unit Test (mysql80)
t.Context undefined (type *testing.T has no field or method Context, but does have unexported field context)
Check failure on line 1353 in go/pools/smartconnpool/pool_test.go
GitHub Actions / Unit Test (mysql84)
t.Context undefined (type *testing.T has no field or method Context, but does have unexported field context)
Check failure on line 1353 in go/pools/smartconnpool/pool_test.go
GitHub Actions / Unit Test (mysql80)
t.Context undefined (type *testing.T has no field or method Context, but does have unexported field context)
Check failure on line 1353 in go/pools/smartconnpool/pool_test.go
GitHub Actions / Unit Test (mysql84)
t.Context undefined (type *testing.T has no field or method Context, but does have unexported field context)
Check failure on line 1353 in go/pools/smartconnpool/pool_test.go
GitHub Actions / Unit Test (mysql57)
t.Context undefined (type *testing.T has no field or method Context, but does have unexported field context)
Check failure on line 1353 in go/pools/smartconnpool/pool_test.go
GitHub Actions / Unit Test (Race)
t.Context undefined (type *testing.T has no field or method Context, but does have unexported field context)
Copilot
AI
Dec 8, 2025
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.
The method t.Context() was introduced in Go 1.24, but this project uses Go 1.23.10 (as specified in go.mod). This will cause a compilation error. Use context.Background() instead, which is the pattern used consistently throughout this test file.
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.
The method
t.Context()was introduced in Go 1.24, but this project uses Go 1.23.10 (as specified in go.mod). This will cause a compilation error. Usecontext.Background()instead, which is the pattern used consistently throughout this test file.