fix: resolve ERR_INSUFFICIENT_RESOURCES connection exhaustion
- Add concurrency limiter (max 4 GET requests) to API layer, leaving slots for SSE and health checks. Write ops bypass the limiter. - Add AbortController to ContainerStats, project detail page, and dashboard to cancel in-flight requests on navigation/unmount. - Move global SSE connection from layout to events page (only consumer). - Add 30s heartbeat to SSE endpoint to detect zombie connections. - Serialize dashboard project fetches to avoid parallel burst. - Rebuild frontend in dev-server.sh so go:embed stays in sync.
This commit is contained in:
@@ -7,6 +7,7 @@ import (
|
||||
"log/slog"
|
||||
"net/http"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/go-chi/chi/v5"
|
||||
|
||||
@@ -158,6 +159,10 @@ func (s *Server) streamEvents(w http.ResponseWriter, r *http.Request) {
|
||||
})
|
||||
defer s.eventBus.Unsubscribe(sub)
|
||||
|
||||
// Periodic heartbeat so the browser detects dead connections.
|
||||
heartbeat := time.NewTicker(30 * time.Second)
|
||||
defer heartbeat.Stop()
|
||||
|
||||
ctx := r.Context()
|
||||
for {
|
||||
select {
|
||||
@@ -168,6 +173,10 @@ func (s *Server) streamEvents(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
writeSSE(w, flusher, evt)
|
||||
case <-heartbeat.C:
|
||||
// SSE comment line — keeps the connection alive without triggering onmessage.
|
||||
fmt.Fprintf(w, ": heartbeat\n\n")
|
||||
flusher.Flush()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user