Skip to content

Commit 749542e

Browse files
committed
Faster shutdown of pgxpool.Pool background goroutines
When a pool is closed, some background goroutines may be left open, particularly for health checks as detailed in #1641. Two specific examples have been refactored here to avoid a blocking sleep and instead also select on the pool being closed to potentially return/continue sooner.
1 parent dc94db6 commit 749542e

1 file changed

Lines changed: 24 additions & 8 deletions

File tree

pgxpool/pool.go

Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,9 @@ type Pool struct {
9393
maxConnIdleTime time.Duration
9494
healthCheckPeriod time.Duration
9595

96+
healthCheckMu sync.Mutex
97+
healthCheckTimer *time.Timer
98+
9699
healthCheckChan chan struct{}
97100

98101
closeOnce sync.Once
@@ -381,15 +384,25 @@ func (p *Pool) isExpired(res *puddle.Resource[*connResource]) bool {
381384
}
382385

383386
func (p *Pool) triggerHealthCheck() {
384-
go func() {
387+
const healthCheckDelay = 500 * time.Millisecond
388+
389+
p.healthCheckMu.Lock()
390+
defer p.healthCheckMu.Unlock()
391+
392+
if p.healthCheckTimer == nil {
385393
// Destroy is asynchronous so we give it time to actually remove itself from
386394
// the pool otherwise we might try to check the pool size too soon
387-
time.Sleep(500 * time.Millisecond)
388-
select {
389-
case p.healthCheckChan <- struct{}{}:
390-
default:
391-
}
392-
}()
395+
p.healthCheckTimer = time.AfterFunc(healthCheckDelay, func() {
396+
select {
397+
case <-p.closeChan:
398+
case p.healthCheckChan <- struct{}{}:
399+
default:
400+
}
401+
})
402+
return
403+
}
404+
405+
p.healthCheckTimer.Reset(healthCheckDelay)
393406
}
394407

395408
func (p *Pool) backgroundHealthCheck() {
@@ -408,6 +421,9 @@ func (p *Pool) backgroundHealthCheck() {
408421
}
409422

410423
func (p *Pool) checkHealth() {
424+
ticker := time.NewTicker(500 * time.Millisecond)
425+
defer ticker.Stop()
426+
411427
for {
412428
// If checkMinConns failed we don't destroy any connections since we couldn't
413429
// even get to minConns
@@ -424,7 +440,7 @@ func (p *Pool) checkHealth() {
424440
select {
425441
case <-p.closeChan:
426442
return
427-
case <-time.After(500 * time.Millisecond):
443+
case <-ticker.C:
428444
}
429445
}
430446
}

0 commit comments

Comments
 (0)