Fix two goroutine leaks: stats handlers on timeout, streamer tickers on reconnect (closes #12)
The stats handlers ran the database query in a goroutine that sent on an unbuffered channel. When the 4s request timeout won, nothing received and the goroutine blocked forever; the status page polls every 2s, so once the query exceeds the timeout every poll leaked one goroutine. Give both channels capacity 1 so the send always completes. The streamer started two ticker goroutines per connection that exited only with the streamer's lifetime context, leaking two on every reconnect. Scope them to a per-connection context cancelled when the stream call returns. Tests force the stats timeout repeatedly and drive many reconnects, then assert the goroutine count settles back to its starting value. The streamer gains an internal endpoint field so a test can point it at a local server. Model: opus-4-8
This commit is contained in:
@@ -179,9 +179,11 @@ func (s *Server) handleStatusJSON() http.HandlerFunc {
|
||||
|
||||
metrics := s.streamer.GetMetrics()
|
||||
|
||||
// Get database stats with timeout
|
||||
statsChan := make(chan database.Stats)
|
||||
errChan := make(chan error)
|
||||
// Get database stats with timeout. The channels are buffered so the
|
||||
// goroutine's send never blocks if the timeout wins and nothing here
|
||||
// receives; otherwise it would block forever and leak.
|
||||
statsChan := make(chan database.Stats, 1)
|
||||
errChan := make(chan error, 1)
|
||||
|
||||
go func() {
|
||||
dbStats, err := s.db.GetStatsContext(ctx)
|
||||
@@ -398,9 +400,11 @@ func (s *Server) handleStats() http.HandlerFunc {
|
||||
|
||||
metrics := s.streamer.GetMetrics()
|
||||
|
||||
// Get database stats with timeout
|
||||
statsChan := make(chan database.Stats)
|
||||
errChan := make(chan error)
|
||||
// Get database stats with timeout. The channels are buffered so the
|
||||
// goroutine's send never blocks if the timeout wins and nothing here
|
||||
// receives; otherwise it would block forever and leak.
|
||||
statsChan := make(chan database.Stats, 1)
|
||||
errChan := make(chan error, 1)
|
||||
|
||||
go func() {
|
||||
dbStats, err := s.db.GetStatsContext(ctx)
|
||||
|
||||
Reference in New Issue
Block a user