@@ -14,6 +14,9 @@ type RequestTracker struct {
1414 wg sync.WaitGroup
1515 shutdownCh chan struct {}
1616 isShutdown atomic.Bool
17+ // notifyCh is used to notify when a request completes during shutdown
18+ notifyCh chan struct {}
19+ notifyMu sync.Mutex
1720}
1821
1922// NewRequestTracker creates a new request tracker
@@ -36,8 +39,23 @@ func (t *RequestTracker) Add() bool {
3639
3740// Done decrements the active request count
3841func (t * RequestTracker ) Done () {
39- atomic .AddInt64 (& t .activeCount , - 1 )
42+ remaining := atomic .AddInt64 (& t .activeCount , - 1 )
4043 t .wg .Done ()
44+
45+ // Notify shutdown goroutine if shutting down
46+ if t .isShutdown .Load () {
47+ t .notifyMu .Lock ()
48+ ch := t .notifyCh
49+ t .notifyMu .Unlock ()
50+ if ch != nil {
51+ select {
52+ case ch <- struct {}{}:
53+ default :
54+ // Non-blocking send, channel might be full or closed
55+ }
56+ }
57+ log .Printf ("[RequestTracker] Request completed, %d remaining" , remaining )
58+ }
4159}
4260
4361// ActiveCount returns the current number of active requests
@@ -97,8 +115,12 @@ func (t *RequestTracker) ShutdownCh() <-chan struct{} {
97115
98116// GracefulShutdown initiates graceful shutdown and waits for requests to complete
99117// maxWait: maximum time to wait for requests to complete
100- // checkInterval: how often to log remaining requests
101- func (t * RequestTracker ) GracefulShutdown (maxWait time.Duration , checkInterval time.Duration ) bool {
118+ func (t * RequestTracker ) GracefulShutdown (maxWait time.Duration ) bool {
119+ // Setup notify channel before marking shutdown
120+ t .notifyMu .Lock ()
121+ t .notifyCh = make (chan struct {}, 100 ) // Buffered to avoid blocking Done()
122+ t .notifyMu .Unlock ()
123+
102124 t .isShutdown .Store (true )
103125 close (t .shutdownCh )
104126
@@ -116,19 +138,21 @@ func (t *RequestTracker) GracefulShutdown(maxWait time.Duration, checkInterval t
116138 close (done )
117139 }()
118140
119- ticker := time .NewTicker (checkInterval )
120- defer ticker .Stop ()
121-
122141 deadline := time .After (maxWait )
123142
124143 for {
125144 select {
126145 case <- done :
127146 log .Printf ("[RequestTracker] All requests completed, shutdown clean" )
128147 return true
129- case <- ticker .C :
130- remaining := t .ActiveCount ()
131- log .Printf ("[RequestTracker] Waiting for %d active requests to complete..." , remaining )
148+ case <- t .notifyCh :
149+ // Request completed notification received, log is printed in Done()
150+ // Check if all done
151+ if t .ActiveCount () == 0 {
152+ <- done // Wait for wg.Wait() to complete
153+ log .Printf ("[RequestTracker] All requests completed, shutdown clean" )
154+ return true
155+ }
132156 case <- deadline :
133157 remaining := t .ActiveCount ()
134158 log .Printf ("[RequestTracker] Timeout reached, %d requests still active, forcing shutdown" , remaining )
0 commit comments