package broker import ( "encoding/json" "sync" ) // Event is a JSON-serialisable message pushed to WebSocket clients. type Event struct { Type string `json:"type"` AgentID string `json:"agent_id,omitempty"` Payload any `json:"payload"` } type subscriber chan []byte // Broker fan-outs events to all registered WebSocket subscribers. type Broker struct { mu sync.RWMutex subs map[subscriber]struct{} } func New() *Broker { return &Broker{subs: make(map[subscriber]struct{})} } func (b *Broker) Subscribe() subscriber { ch := make(subscriber, 32) b.mu.Lock() b.subs[ch] = struct{}{} b.mu.Unlock() return ch } func (b *Broker) Unsubscribe(ch subscriber) { b.mu.Lock() delete(b.subs, ch) b.mu.Unlock() close(ch) } func (b *Broker) Publish(evt Event) { data, err := json.Marshal(evt) if err != nil { return } b.mu.RLock() defer b.mu.RUnlock() for ch := range b.subs { select { case ch <- data: default: // drop if subscriber is slow } } }