From 9ff4dea166a2e75e2114bde9a373a59cd665828f Mon Sep 17 00:00:00 2001 From: Harshit Gangal Date: Tue, 18 Feb 2025 15:55:46 +0530 Subject: [PATCH] pool: reopen connection closed by idle timeout Signed-off-by: Harshit Gangal --- go/pools/smartconnpool/pool.go | 14 ++++++++++++-- go/pools/smartconnpool/pool_test.go | 11 +++++++++-- 2 files changed, 21 insertions(+), 4 deletions(-) diff --git a/go/pools/smartconnpool/pool.go b/go/pools/smartconnpool/pool.go index 87a288bec3d..ca45e1329e8 100644 --- a/go/pools/smartconnpool/pool.go +++ b/go/pools/smartconnpool/pool.go @@ -503,8 +503,16 @@ func (pool *ConnPool[C]) connReopen(ctx context.Context, dbconn *Pooled[C], now return err } - dbconn.timeUsed.set(now) + if dbconn.Conn.Setting() != nil { + err = dbconn.Conn.ApplySetting(ctx, dbconn.Conn.Setting()) + if err != nil { + dbconn.Close() + return err + } + } + dbconn.timeCreated.set(now) + dbconn.timeUsed.set(now) return nil } @@ -764,7 +772,9 @@ func (pool *ConnPool[C]) closeIdleResources(now time.Time) { if conn.timeUsed.expired(mono, timeout) { pool.Metrics.idleClosed.Add(1) conn.Close() - pool.closedConn() + if err := pool.connReopen(context.Background(), conn, monotonicNow()); err != nil { + pool.closedConn() + } } } } diff --git a/go/pools/smartconnpool/pool_test.go b/go/pools/smartconnpool/pool_test.go index 202261e6f3b..893d247ee60 100644 --- a/go/pools/smartconnpool/pool_test.go +++ b/go/pools/smartconnpool/pool_test.go @@ -608,6 +608,7 @@ func TestIdleTimeout(t *testing.T) { conns = append(conns, r) } + assert.GreaterOrEqual(t, state.open.Load(), int64(5)) // wait a long while; ensure that none of the conns have been closed time.Sleep(1 * time.Second) @@ -628,9 +629,15 @@ func TestIdleTimeout(t *testing.T) { t.Fatalf("Connections remain open after 1 second") } } + // At least 5 connections should have been closed by now. + assert.GreaterOrEqual(t, p.Metrics.IdleClosed(), int64(5), "At least 5 connections should have been closed by now.") - // no need to assert anything: all the connections in the pool should are idle-closed - // now and if they're not the test will timeout and fail + // At any point, at least 4 connections should be open, with 1 either in the process of opening or already opened. + // The idle connection closer shuts down one connection at a time. + assert.GreaterOrEqual(t, state.open.Load(), int64(4)) + + // The number of available connections in the pool should remain at 5. + assert.EqualValues(t, 5, p.Available()) } t.Run("WithoutSettings", func(t *testing.T) { testTimeout(t, nil) })