shutdown gracefully shuts down the ConnManager
()
| 173 | |
| 174 | // shutdown gracefully shuts down the ConnManager |
| 175 | func (cm *ConnManager) shutdown() error { |
| 176 | var err error |
| 177 | |
| 178 | cm.shutdownOnce.Do(func() { |
| 179 | shared.LogInfo("ConnManager: Beginning graceful shutdown") |
| 180 | |
| 181 | // Signal shutdown to prevent new goroutines |
| 182 | close(cm.shutdownCh) |
| 183 | |
| 184 | // Clean up all sessions |
| 185 | cm.mu.Lock() |
| 186 | sessions := make([]*Session, len(cm.sessions)) |
| 187 | copy(sessions, cm.sessions) |
| 188 | cm.sessions = nil |
| 189 | cm.mu.Unlock() |
| 190 | |
| 191 | // Clean up each session |
| 192 | for _, session := range sessions { |
| 193 | if cleanupErr := cm.cleanupSession(session); cleanupErr != nil { |
| 194 | shared.LogErrorf("Error cleaning up session %s: %v", session.ID, cleanupErr) |
| 195 | if err == nil { |
| 196 | err = cleanupErr |
| 197 | } |
| 198 | } |
| 199 | } |
| 200 | |
| 201 | // Wait for all goroutines to finish with timeout |
| 202 | done := make(chan struct{}) |
| 203 | go func() { |
| 204 | cm.activeGoroutines.Wait() |
| 205 | close(done) |
| 206 | }() |
| 207 | |
| 208 | select { |
| 209 | case <-done: |
| 210 | shared.LogInfo("ConnManager: All goroutines finished cleanly") |
| 211 | case <-time.After(5 * time.Second): |
| 212 | shared.LogError("ConnManager: Timeout waiting for goroutines to finish", fmt.Errorf("shutdown timeout")) |
| 213 | } |
| 214 | |
| 215 | shared.LogInfo("ConnManager: Shutdown complete") |
| 216 | }) |
| 217 | |
| 218 | return err |
| 219 | } |
| 220 | |
| 221 | // monitor watches sessions and handles rotation |
| 222 | func (cm *ConnManager) monitor(ctx context.Context) { |
no test coverage detected