package plugin import ( "context" "log/slog" "sync" "realtime-gateway/internal/model" ) type Handler interface { Name() string Handle(context.Context, model.Envelope) error } type Bus struct { logger *slog.Logger mu sync.RWMutex handlers []Handler } func NewBus(logger *slog.Logger) *Bus { return &Bus{ logger: logger, } } func (b *Bus) Register(handler Handler) { b.mu.Lock() b.handlers = append(b.handlers, handler) b.mu.Unlock() } func (b *Bus) Publish(envelope model.Envelope) { b.mu.RLock() handlers := append([]Handler(nil), b.handlers...) b.mu.RUnlock() for _, handler := range handlers { handler := handler go func() { if err := handler.Handle(context.Background(), envelope); err != nil { b.logger.Warn("plugin handler failed", "handler", handler.Name(), "error", err) } }() } } func (b *Bus) HandlerCount() int { b.mu.RLock() defer b.mu.RUnlock() return len(b.handlers) }