Fix: file-watcher bugs (#1897)
* Fix: file-watcher bugs * Update watcher_linux.go Co-authored-by: 杨铭哲 <yangmz@weipaitang.com> Co-authored-by: Asim Aslam <asim@aslam.me>
This commit is contained in:
parent
991cdba91d
commit
dcf785677f
@ -10,6 +10,7 @@ import (
|
|||||||
|
|
||||||
type file struct {
|
type file struct {
|
||||||
path string
|
path string
|
||||||
|
data []byte
|
||||||
opts source.Options
|
opts source.Options
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -39,26 +39,36 @@ func (w *watcher) Next() (*source.ChangeSet, error) {
|
|||||||
default:
|
default:
|
||||||
}
|
}
|
||||||
|
|
||||||
// try get the event
|
for {
|
||||||
select {
|
// try get the event
|
||||||
case event, _ := <-w.fw.Events:
|
select {
|
||||||
if event.Op == fsnotify.Rename {
|
case event, _ := <-w.fw.Events:
|
||||||
// check existence of file, and add watch again
|
if event.Op == fsnotify.Rename {
|
||||||
_, err := os.Stat(event.Name)
|
// check existence of file, and add watch again
|
||||||
if err == nil || os.IsExist(err) {
|
_, err := os.Stat(event.Name)
|
||||||
w.fw.Add(event.Name)
|
if err == nil || os.IsExist(err) {
|
||||||
|
w.fw.Add(event.Name)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
c, err := w.f.Read()
|
// ARCH: Darwin Kernel Version 18.7.0
|
||||||
if err != nil {
|
// ioutil.WriteFile truncates it before writing, but the problem is that
|
||||||
|
// you will receive two events(fsnotify.Chmod and fsnotify.Write).
|
||||||
|
// We can solve this problem by ignoring fsnotify.Chmod event.
|
||||||
|
if event.Op&fsnotify.Write != fsnotify.Write {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
c, err := w.f.Read()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return c, nil
|
||||||
|
case err := <-w.fw.Errors:
|
||||||
return nil, err
|
return nil, err
|
||||||
|
case <-w.exit:
|
||||||
|
return nil, source.ErrWatcherStopped
|
||||||
}
|
}
|
||||||
return c, nil
|
|
||||||
case err := <-w.fw.Errors:
|
|
||||||
return nil, err
|
|
||||||
case <-w.exit:
|
|
||||||
return nil, source.ErrWatcherStopped
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,6 +4,7 @@ package file
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"os"
|
"os"
|
||||||
|
"reflect"
|
||||||
|
|
||||||
"github.com/fsnotify/fsnotify"
|
"github.com/fsnotify/fsnotify"
|
||||||
"github.com/micro/go-micro/v3/config/source"
|
"github.com/micro/go-micro/v3/config/source"
|
||||||
@ -39,30 +40,38 @@ func (w *watcher) Next() (*source.ChangeSet, error) {
|
|||||||
default:
|
default:
|
||||||
}
|
}
|
||||||
|
|
||||||
// try get the event
|
for {
|
||||||
select {
|
// try get the event
|
||||||
case event, _ := <-w.fw.Events:
|
select {
|
||||||
if event.Op == fsnotify.Rename {
|
case event, _ := <-w.fw.Events:
|
||||||
// check existence of file, and add watch again
|
if event.Op == fsnotify.Rename {
|
||||||
_, err := os.Stat(event.Name)
|
// check existence of file, and add watch again
|
||||||
if err == nil || os.IsExist(err) {
|
_, err := os.Stat(event.Name)
|
||||||
w.fw.Add(event.Name)
|
if err == nil || os.IsExist(err) {
|
||||||
|
w.fw.Add(event.Name)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
c, err := w.f.Read()
|
c, err := w.f.Read()
|
||||||
if err != nil {
|
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
|
return nil, err
|
||||||
|
case <-w.exit:
|
||||||
|
return nil, source.ErrWatcherStopped
|
||||||
}
|
}
|
||||||
|
|
||||||
// add path again for the event bug of fsnotify
|
|
||||||
w.fw.Add(w.f.path)
|
|
||||||
|
|
||||||
return c, nil
|
|
||||||
case err := <-w.fw.Errors:
|
|
||||||
return nil, err
|
|
||||||
case <-w.exit:
|
|
||||||
return nil, source.ErrWatcherStopped
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user