Skip to content

Commit

Permalink
Faster shutdown of pgxpool.Pool background goroutines
Browse files Browse the repository at this point in the history
When a pool is closed, some background goroutines may be left open,
particularly for health checks as detailed in jackc#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.
  • Loading branch information
bgentry committed Jul 3, 2023
1 parent dc94db6 commit 749542e
Showing 1 changed file with 24 additions and 8 deletions.
32 changes: 24 additions & 8 deletions pgxpool/pool.go
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,9 @@ type Pool struct {
maxConnIdleTime time.Duration
healthCheckPeriod time.Duration

healthCheckMu sync.Mutex
healthCheckTimer *time.Timer

healthCheckChan chan struct{}

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

func (p *Pool) triggerHealthCheck() {
go func() {
const healthCheckDelay = 500 * time.Millisecond

p.healthCheckMu.Lock()
defer p.healthCheckMu.Unlock()

if p.healthCheckTimer == nil {
// Destroy is asynchronous so we give it time to actually remove itself from
// the pool otherwise we might try to check the pool size too soon
time.Sleep(500 * time.Millisecond)
select {
case p.healthCheckChan <- struct{}{}:
default:
}
}()
p.healthCheckTimer = time.AfterFunc(healthCheckDelay, func() {
select {
case <-p.closeChan:
case p.healthCheckChan <- struct{}{}:
default:
}
})
return
}

p.healthCheckTimer.Reset(healthCheckDelay)
}

func (p *Pool) backgroundHealthCheck() {
Expand All @@ -408,6 +421,9 @@ func (p *Pool) backgroundHealthCheck() {
}

func (p *Pool) checkHealth() {
ticker := time.NewTicker(500 * time.Millisecond)
defer ticker.Stop()

for {
// If checkMinConns failed we don't destroy any connections since we couldn't
// even get to minConns
Expand All @@ -424,7 +440,7 @@ func (p *Pool) checkHealth() {
select {
case <-p.closeChan:
return
case <-time.After(500 * time.Millisecond):
case <-ticker.C:
}
}
}
Expand Down

0 comments on commit 749542e

Please sign in to comment.