package events import ( "context" "encoding/json" "fmt" "github.com/redis/go-redis/v9" ) const channel = "agent-mgr:events" type Bus struct { rdb *redis.Client } type Event struct { Type string `json:"type"` // "session.started", "session.completed", "session.failed", "session.stopped", "app.status" SessionID string `json:"session_id,omitempty"` AppID string `json:"app_id,omitempty"` Status string `json:"status,omitempty"` Message string `json:"message,omitempty"` } func NewBus(addr, password string) *Bus { return &Bus{ rdb: redis.NewClient(&redis.Options{ Addr: addr, Password: password, }), } } func (b *Bus) Publish(ctx context.Context, evt Event) error { data, err := json.Marshal(evt) if err != nil { return fmt.Errorf("marshal event: %w", err) } return b.rdb.Publish(ctx, channel, data).Err() } func (b *Bus) Subscribe(ctx context.Context) (<-chan Event, error) { sub := b.rdb.Subscribe(ctx, channel) ch := make(chan Event, 64) go func() { defer close(ch) defer sub.Close() for { msg, err := sub.ReceiveMessage(ctx) if err != nil { return } var evt Event if err := json.Unmarshal([]byte(msg.Payload), &evt); err != nil { continue } select { case ch <- evt: case <-ctx.Done(): return } } }() return ch, nil } func (b *Bus) Close() error { return b.rdb.Close() }