//+build linux package file import ( "os" "reflect" "github.com/fsnotify/fsnotify" "github.com/micro/go-micro/v3/config/source" ) type watcher struct { f *file fw *fsnotify.Watcher exit chan bool } func newWatcher(f *file) (source.Watcher, error) { fw, err := fsnotify.NewWatcher() if err != nil { return nil, err } fw.Add(f.path) return &watcher{ f: f, fw: fw, exit: make(chan bool), }, nil } func (w *watcher) Next() (*source.ChangeSet, error) { // is it closed? select { case <-w.exit: return nil, source.ErrWatcherStopped default: } for { // try get the event select { case event, _ := <-w.fw.Events: if event.Op == fsnotify.Rename { // check existence of file, and add watch again _, err := os.Stat(event.Name) if err == nil || os.IsExist(err) { w.fw.Add(event.Name) } } c, err := w.f.Read() if err != nil { return nil, err } // ARCH: Linux centos-7.shared 3.10.0-693.5.2.el7.x86_64 // Sometimes, ioutil.WriteFile triggers multiple fsnotify.Write events, which may be a bug. // Detect if the file has changed if reflect.DeepEqual(c.Data, w.f.data) { continue } w.f.data = c.Data return c, nil case err := <-w.fw.Errors: return nil, err case <-w.exit: return nil, source.ErrWatcherStopped } } } func (w *watcher) Stop() error { return w.fw.Close() }