Files
yuan-lab-llm--clawmanager/backend/cmd/server
hippoley cfd9c46ca8 fix: add graceful shutdown, fix WebSocket Hub race, plug goroutine leaks
Address three HIGH-severity issues from the memory-leak and bloat
analysis (issue #56).

1. Graceful shutdown (main.go)
   - Replace gin's r.Run() with an explicit http.Server so the process
     can intercept SIGINT / SIGTERM.
   - On signal: drain active HTTP requests (10 s timeout), then stop
     SyncService, WebSocket Hub, and InstanceAccessService cleanup
     goroutine in order.
   - Ensures database connections, K8s watchers, and background loops
     are released cleanly on deploy or restart.

2. WebSocket Hub init race (websocket_service.go)
   - GetHub() used a bare nil-check with no synchronisation; two
     goroutines could each create a Hub and start a Run() loop.
   - Replaced with sync.Once to guarantee exactly one Hub instance.
   - Added a stop channel to Hub.Run() so the hub can be shut down
     gracefully, closing all connected clients.

3. InstanceAccessService goroutine leak (instance_access_service.go)
   - cleanupExpiredTokens() looped on ticker.C with no exit path,
     leaking the goroutine for the lifetime of the process.
   - Added a stopChan; cleanupExpiredTokens now selects on both the
     ticker and the stop signal.
   - Exposed Stop() on the service; InstanceHandler.Shutdown() calls
     it during graceful shutdown.

Tests:
- TestGetHubReturnsSameInstance: singleton guarantee
- TestGetHubConcurrentAccess: 50-goroutine race test
- TestHubStopClosesClients: verifies client cleanup on Stop()
- TestInstanceAccessServiceStopTerminatesCleanup: Stop() is safe and
  the service remains functional for token ops afterward

All existing tests continue to pass; full project build and regression
verified.

Ref: #56
2026-04-24 20:07:13 +08:00
..