package config import ( "fmt" "path/filepath" "github.com/fsnotify/fsnotify" ) // Watcher represents a configuration file watcher type Watcher struct { watcher *fsnotify.Watcher configPath string onReload func() error } // NewWatcher creates a new configuration watcher func NewWatcher(configPath string, onReload func() error) (*Watcher, error) { fsWatcher, err := fsnotify.NewWatcher() if err != nil { return nil, fmt.Errorf("failed to create file watcher: %v", err) } w := &Watcher{ watcher: fsWatcher, configPath: configPath, onReload: onReload, } return w, nil } // Start begins watching the configuration file for changes func (w *Watcher) Start() error { // Watch the directory containing the config file configDir := filepath.Dir(w.configPath) if err := w.watcher.Add(configDir); err != nil { return fmt.Errorf("failed to watch config directory: %v", err) } go w.watch() return nil } // Stop stops watching for configuration changes func (w *Watcher) Stop() error { return w.watcher.Close() } func (w *Watcher) watch() { for { select { case event, ok := <-w.watcher.Events: if !ok { return } // Check if the config file was modified if event.Op&fsnotify.Write == fsnotify.Write && filepath.Base(event.Name) == filepath.Base(w.configPath) { if err := w.onReload(); err != nil { fmt.Printf("Error reloading config: %v\n", err) } } case err, ok := <-w.watcher.Errors: if !ok { return } fmt.Printf("Error watching config file: %v\n", err) } } }