stream-score/backend/sse_stream.go
2025-02-25 16:26:52 +01:00

87 lines
1.5 KiB
Go

package main
import (
"fmt"
"log"
"net/http"
"sync"
"time"
"github.com/gin-gonic/gin"
)
type Message struct {
Data interface{} `json:"data"`
Id string `json:"id"`
}
type Client struct {
Channel chan Message `json:"clients"`
}
var (
clients = make(map[*Client]bool)
clientsMutex sync.Mutex
broadcast = make(chan Message)
)
func SSEHandler(c *gin.Context) {
client := &Client{
Channel: make(chan Message),
}
log.Printf("events: %+v", client)
AddClient(client)
defer unregisterClient(client)
log.Printf("Client %s connected", client)
c.Writer.Header().Set("Content-Type", "text/event-stream")
c.Writer.Header().Set("Cache-Control", "no-cache")
c.Writer.Header().Set("Connection", "keep-alive")
c.Writer.Header().Set("Transfer-Encoding", "chunked")
for {
select {
case msg := <-client.Channel:
fmt.Fprintf(c.Writer, "data: %s\n\n", msg.Data)
c.Writer.Flush()
case <-c.Writer.CloseNotify():
return
}
}
}
func AddClient(client *Client) {
clientsMutex.Lock()
clients[client] = true
clientsMutex.Unlock()
}
func unregisterClient(client *Client) {
clientsMutex.Lock()
delete(clients, client)
close(client.Channel)
clientsMutex.Unlock()
}
func SendMsg(c *gin.Context) {
var msg Message
c.ShouldBind(&msg)
msg.Id = time.Now().Format(time.RFC3339)
broadcast <- msg
c.JSON(http.StatusOK, gin.H{"status": "sent"})
}
func handleMessages() {
for {
msg := <-broadcast
clientsMutex.Lock()
for client := range clients {
client.Channel <- msg
}
clientsMutex.Unlock()
}
}