package transport import ( "net/http" "time" "github.com/gin-gonic/gin" "github.com/geo-platform/tenant-api/internal/bootstrap" ) type DesktopEventsHandler struct { streams *bootstrap.App } func NewDesktopEventsHandler(a *bootstrap.App) *DesktopEventsHandler { return &DesktopEventsHandler{streams: a} } func (h *DesktopEventsHandler) Stream(c *gin.Context) { client := MustDesktopClient(c.Request.Context()) events, cancel := h.streams.DesktopTaskStreams.Subscribe(client.ID.String()) defer cancel() c.Header("Content-Type", "text/event-stream") c.Header("Cache-Control", "no-cache") c.Header("Connection", "keep-alive") c.Header("X-Accel-Buffering", "no") flusher, ok := c.Writer.(http.Flusher) if !ok { return } if err := writeSSE(c, "connected", gin.H{ "client_id": client.ID.String(), "workspace_id": client.WorkspaceID, "server_time": time.Now().UTC(), }); err != nil { return } flusher.Flush() heartbeat := time.NewTicker(15 * time.Second) defer heartbeat.Stop() for { select { case <-c.Request.Context().Done(): return case <-heartbeat.C: if err := writeSSE(c, "ping", gin.H{"ts": time.Now().UTC()}); err != nil { return } flusher.Flush() case event, ok := <-events: if !ok { return } if err := writeSSE(c, event.Type, event); err != nil { return } flusher.Flush() } } }