From ddef3435f6f38894251a99ab2e0ec8555eb2b5f5 Mon Sep 17 00:00:00 2001 From: LeonardoTrapani Date: Wed, 20 Aug 2025 20:06:59 +0200 Subject: [PATCH] fix config reloading notifier and add callback to the daemon --- internal/config/manager.go | 51 +++++++++++++++++++++++++++++++++++--- internal/daemon/daemon.go | 27 ++++++++++++-------- internal/notify/notify.go | 13 ++++++++++ 3 files changed, 77 insertions(+), 14 deletions(-) diff --git a/internal/config/manager.go b/internal/config/manager.go index dffe04c..93c2e30 100644 --- a/internal/config/manager.go +++ b/internal/config/manager.go @@ -5,6 +5,7 @@ import ( "log" "path/filepath" "sync" + "time" "github.com/fsnotify/fsnotify" ) @@ -14,6 +15,13 @@ type Manager struct { config *Config watcher *fsnotify.Watcher wg sync.WaitGroup + + onConfigReload func() + + // Debouncer for config reloads + debounceTimer *time.Timer + debounceMutex sync.Mutex + debounceDelay time.Duration } func NewManager() (*Manager, error) { @@ -31,7 +39,8 @@ func NewManager() (*Manager, error) { } m := &Manager{ - config: config, + config: config, + debounceDelay: 500 * time.Millisecond, // 500ms debounce delay } log.Printf("Config manager: initialization completed successfully") @@ -78,6 +87,14 @@ func (m *Manager) Stop() { if m.watcher != nil { m.watcher.Close() } + + // Clean up debounce timer + m.debounceMutex.Lock() + if m.debounceTimer != nil { + m.debounceTimer.Stop() + } + m.debounceMutex.Unlock() + m.wg.Wait() } @@ -100,8 +117,8 @@ func (m *Manager) watchLoop(ctx context.Context, configPath string) { // Only react to Write and Create events (ignore Chmod, Remove, etc.) if event.Op&fsnotify.Write == fsnotify.Write || event.Op&fsnotify.Create == fsnotify.Create { - log.Printf("Config manager: file change detected: %s. Reloading config...", event.Name) - m.reloadConfig() + log.Printf("Config manager: file change detected: %s. Debouncing reload...", event.Name) + m.debounceReloadConfig() } case err, ok := <-m.watcher.Errors: @@ -133,7 +150,35 @@ func (m *Manager) reloadConfig() { m.mu.Lock() m.config = newConfig + onConfigReload := m.onConfigReload m.mu.Unlock() + if onConfigReload != nil { + onConfigReload() + } + log.Printf("Config manager: configuration successfully reloaded") } + +func (m *Manager) SetOnConfigReload(onConfigReload func()) { + m.mu.Lock() + defer m.mu.Unlock() + m.onConfigReload = onConfigReload +} + +// debounceReloadConfig implements debouncing to prevent duplicate reloads +func (m *Manager) debounceReloadConfig() { + m.debounceMutex.Lock() + defer m.debounceMutex.Unlock() + + // Cancel existing timer if it exists + if m.debounceTimer != nil { + m.debounceTimer.Stop() + } + + // Create new timer with debounce delay + m.debounceTimer = time.AfterFunc(m.debounceDelay, func() { + log.Printf("Config manager: debounce period expired, reloading config...") + m.reloadConfig() + }) +} diff --git a/internal/daemon/daemon.go b/internal/daemon/daemon.go index e05ae74..d051bd2 100644 --- a/internal/daemon/daemon.go +++ b/internal/daemon/daemon.go @@ -35,22 +35,14 @@ func New() (*Daemon, error) { conf := configMgr.GetConfig() - var n notify.Notifier - - switch conf.Notifications.Type { - case "desktop": - n = notify.Desktop{} - case "log": - n = notify.Log{} - case "none": - n = notify.Nop{} - } - if err != nil { return nil, fmt.Errorf("failed to create config manager: %w", err) } ctx, cancel := context.WithCancel(context.Background()) + + n := notify.GetNotifierBasedOnConfig(conf) + d := &Daemon{ notifier: n, configMgr: configMgr, @@ -61,6 +53,17 @@ func New() (*Daemon, error) { return d, nil } +func (d *Daemon) onConfigReload() { + log.Printf("Config reloaded, restarting pipeline") + d.stopPipeline() + + d.notifier.Notify("Hyprvoice", "Config Reloaded") + + d.mu.Lock() + d.notifier = notify.GetNotifierBasedOnConfig(d.configMgr.GetConfig()) + d.mu.Unlock() +} + func (d *Daemon) status() pipeline.Status { d.mu.RLock() defer d.mu.RUnlock() @@ -86,6 +89,8 @@ func (d *Daemon) Run() error { return err } + d.configMgr.SetOnConfigReload(d.onConfigReload) + ln, err := bus.Listen() if err != nil { return err diff --git a/internal/notify/notify.go b/internal/notify/notify.go index ff54b9c..4b1a3c5 100644 --- a/internal/notify/notify.go +++ b/internal/notify/notify.go @@ -1,6 +1,7 @@ package notify import ( + "github.com/leonardotrapani/hyprvoice/internal/config" "log" "os/exec" ) @@ -48,3 +49,15 @@ type Nop struct{} func (Nop) Error(msg string) {} func (Nop) Notify(title, message string) {} + +func GetNotifierBasedOnConfig(c *config.Config) Notifier { + switch c.Notifications.Type { + case "desktop": + return Desktop{} + case "log": + return Log{} + case "none": + return Nop{} + } + return Nop{} +}