diff --git a/internal/channels/manager.go b/internal/channels/manager.go index 7fed75e6..fa5ea520 100644 --- a/internal/channels/manager.go +++ b/internal/channels/manager.go @@ -45,10 +45,17 @@ func NewManager(msgBus *bus.MessageBus) *Manager { } // StartAll starts all registered channels and the outbound dispatch loop. +// The dispatcher is always started even when no channels exist yet, +// because channels may be loaded dynamically later via Reload(). func (m *Manager) StartAll(ctx context.Context) error { m.mu.Lock() defer m.mu.Unlock() + // Always start the outbound dispatcher — channels may be added later via Reload(). + dispatchCtx, cancel := context.WithCancel(ctx) + m.dispatchTask = &asyncTask{cancel: cancel} + go m.dispatchOutbound(dispatchCtx) + if len(m.channels) == 0 { slog.Warn("no channels enabled") return nil @@ -56,11 +63,6 @@ func (m *Manager) StartAll(ctx context.Context) error { slog.Info("starting all channels") - dispatchCtx, cancel := context.WithCancel(ctx) - m.dispatchTask = &asyncTask{cancel: cancel} - - go m.dispatchOutbound(dispatchCtx) - for name, channel := range m.channels { slog.Info("starting channel", "channel", name) if err := channel.Start(ctx); err != nil {