From 73b85eb947e63a2b6868861dc386064c8a870952 Mon Sep 17 00:00:00 2001 From: Angel Beltran Date: Thu, 6 Aug 2026 20:39:45 -0600 Subject: [PATCH] amazon: fix a goroutine/connection leak on ProcessEvents shutdown listenForNotifications' notification-forwarding goroutine sent on ch unconditionally after each WaitForNotification. If ProcessEvents' main loop had already exited (ctx cancelled) at the exact moment this goroutine had a notification to forward, nobody was left reading from the unbuffered channel - the send blocked forever, the goroutine never reached its deferred pc.Release(), and the pooled connection leaked permanently. Real in production (a shutdown racing an in-flight NOTIFY), not just a test artifact. Surfaced by a go test ./... hang inside domains/amazon (a goroutine stuck in pgxpool.Pool.Close's WaitGroup.Wait) - increased cross-package NOTIFY traffic from domains/reports' Amazon-platform fixtures made the race easy to hit, but didn't cause it. Fixed with a select alongside the send so the goroutine notices ctx.Done() instead of blocking forever when nobody's listening anymore. Co-Authored-By: Claude Sonnet 5 Claude-Session: https://claude.ai/code/session_01XEDaCB7C2NEBgyvqEtZuxY --- domains/amazon/mock.go | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/domains/amazon/mock.go b/domains/amazon/mock.go index 6300efb..ae18e07 100644 --- a/domains/amazon/mock.go +++ b/domains/amazon/mock.go @@ -217,7 +217,11 @@ func (m *Mocks) listenForNotifications(ctx context.Context) (<-chan struct{}, <- return fmt.Errorf("error occurred while waiting for the next notification: %w", err) } - ch <- struct{}{} + select { + case ch <- struct{}{}: + case <-ctx.Done(): + return nil + } } }()