Skip to content

Commit a7cbe74

Browse files
fix pgxpool maxconnlifetime zero unlimited
1 parent 7293fb1 commit a7cbe74

2 files changed

Lines changed: 49 additions & 0 deletions

File tree

pgxpool/pool.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -461,6 +461,9 @@ func (p *Pool) Close() {
461461
}
462462

463463
func (p *Pool) isExpired(res *puddle.Resource[*connResource]) bool {
464+
if p.maxConnLifetime <= 0 {
465+
return false
466+
}
464467
return time.Now().After(res.Value().maxAgeTime)
465468
}
466469

pgxpool/pool_test.go

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1324,6 +1324,52 @@ func TestPoolAcquireDestroysExpiredIdleConn(t *testing.T) {
13241324
require.EqualValues(t, 1, stats.TotalConns())
13251325
}
13261326

1327+
func TestPoolAcquireUnlimitedLifetimeDoesNotExpire(t *testing.T) {
1328+
t.Parallel()
1329+
1330+
ctx, cancel := context.WithTimeout(context.Background(), 120*time.Second)
1331+
defer cancel()
1332+
1333+
config, err := pgxpool.ParseConfig(os.Getenv("PGX_TEST_DATABASE"))
1334+
require.NoError(t, err)
1335+
1336+
// A MaxConnLifetime of zero means connections never expire due to age. The
1337+
// acquire-time expiry check must not treat such connections as expired,
1338+
// otherwise Acquire destroys and recreates them in a loop and ultimately fails.
1339+
config.MaxConnLifetime = 0
1340+
config.HealthCheckPeriod = 100 * time.Millisecond
1341+
1342+
pool, err := pgxpool.NewWithConfig(ctx, config)
1343+
require.NoError(t, err)
1344+
defer pool.Close()
1345+
1346+
// Establish a single connection and remember its identity.
1347+
c, err := pool.Acquire(ctx)
1348+
require.NoError(t, err)
1349+
firstConn := c.Conn()
1350+
c.Release()
1351+
waitForReleaseToComplete()
1352+
1353+
require.EqualValues(t, 1, pool.Stat().TotalConns())
1354+
1355+
// Give the background health check several chances to (wrongly) reap the conn.
1356+
time.Sleep(500 * time.Millisecond)
1357+
1358+
// Re-acquiring must succeed and hand back the very same connection: it was
1359+
// neither expired at acquire time nor destroyed by the health check.
1360+
for range 5 {
1361+
c, err = pool.Acquire(ctx)
1362+
require.NoError(t, err)
1363+
require.Same(t, firstConn, c.Conn())
1364+
c.Release()
1365+
waitForReleaseToComplete()
1366+
}
1367+
1368+
stats := pool.Stat()
1369+
require.EqualValues(t, 0, stats.MaxLifetimeDestroyCount())
1370+
require.EqualValues(t, 1, stats.TotalConns())
1371+
}
1372+
13271373
func TestPoolAcquirePingTimeout(t *testing.T) {
13281374
t.Parallel()
13291375

0 commit comments

Comments
 (0)