--- name: sse_keepalive kind: function lang: go domain: infra version: "1.0.0" purity: impure signature: "func SSEKeepalive(w http.ResponseWriter, interval time.Duration, done <-chan struct{})" description: "Envia comentarios SSE periodicos (`: keepalive\\n\\n`) al writer hasta que done se cierre. Sirve para evitar que proxies o load balancers cierren conexiones inactivas. Bloqueante: lanzar como goroutine. Si w implementa http.Flusher hace flush tras cada keepalive." tags: [sse, keepalive, server-sent-events, http, server, infra, realtime, pendiente-usar] uses_functions: [] uses_types: [] returns: [] returns_optional: false error_type: "error_go_core" imports: [net/http, time] params: - name: w desc: "http.ResponseWriter destino del stream SSE. Si implementa http.Flusher se hace flush tras cada keepalive." - name: interval desc: "intervalo entre keepalives (recomendado 15-30s). Si <= 0 se usa 30s por defecto." - name: done desc: "canal de cierre. Cuando se cierre, la goroutine retorna inmediatamente." output: "ningun retorno; la funcion retorna cuando done se cierra o cuando una escritura falla (cliente desconectado)" tested: true tests: ["escribe comentario keepalive periodicamente", "termina cuando done se cierra", "termina cuando la escritura falla"] test_file_path: "functions/infra/sse_test.go" file_path: "functions/infra/sse_keepalive.go" --- ## Ejemplo ```go http.HandleFunc("/events", func(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "text/event-stream") w.Header().Set("Cache-Control", "no-cache") w.Header().Set("Connection", "keep-alive") done := make(chan struct{}) defer close(done) go SSEKeepalive(w, 15*time.Second, done) // Bucle principal de envio de eventos... }) ``` ## Notas Comentario SSE: la spec dice que cualquier linea que empiece con `:` es un comentario y el cliente la ignora. Mantienen viva la conexion sin generar eventos espurios. Recomendado intervalo entre 15-30s para infraestructuras tipicas (nginx default = 60s timeout idle). Si la escritura falla (conexion cerrada) la funcion retorna sin error, asumiendo que el handler principal ya detectara la desconexion via `r.Context().Done()`.