package main import ( "encoding/json" "sync" ) // Broker is a simple in-memory pub/sub for SSE events. type Broker struct { mu sync.Mutex clients map[chan []byte]struct{} } func newBroker() *Broker { return &Broker{clients: make(map[chan []byte]struct{})} } func (b *Broker) subscribe() chan []byte { ch := make(chan []byte, 8) b.mu.Lock() b.clients[ch] = struct{}{} b.mu.Unlock() return ch } func (b *Broker) unsubscribe(ch chan []byte) { b.mu.Lock() delete(b.clients, ch) b.mu.Unlock() close(ch) } func (b *Broker) publish(event string, data any) { payload, _ := json.Marshal(map[string]any{"event": event, "data": data}) b.mu.Lock() defer b.mu.Unlock() for ch := range b.clients { select { case ch <- payload: default: } } }