Files
geo/server/internal/shared/config/runtime/file/watcher.go
T

79 lines
1.5 KiB
Go
Raw Normal View History

package file
import (
"context"
"os"
"path/filepath"
"sync"
"github.com/fsnotify/fsnotify"
"github.com/geo-platform/tenant-api/internal/shared/config/runtime"
)
type watcher struct {
f *file
fw *fsnotify.Watcher
ctx context.Context
cancel context.CancelFunc
stopOnce sync.Once
}
func newWatcher(f *file) (runtime.Watcher, error) {
fw, err := fsnotify.NewWatcher()
if err != nil {
return nil, err
}
if err := fw.Add(f.path); err != nil {
_ = fw.Close()
return nil, err
}
ctx, cancel := context.WithCancel(context.Background())
return &watcher{f: f, fw: fw, ctx: ctx, cancel: cancel}, nil
}
func (w *watcher) Next() ([]*runtime.KeyValue, error) {
for {
select {
case <-w.ctx.Done():
return nil, w.ctx.Err()
case event := <-w.fw.Events:
if !w.f.match(event.Name) {
continue
}
if event.Op == fsnotify.Rename {
if _, err := os.Stat(event.Name); err == nil || os.IsExist(err) {
if err := w.fw.Add(event.Name); err != nil {
return nil, err
}
}
}
info, err := os.Stat(w.f.path)
if err != nil {
return nil, err
}
path := w.f.path
if info.IsDir() {
path = filepath.Join(w.f.path, filepath.Base(event.Name))
}
kv, err := w.f.loadFile(path)
if err != nil {
return nil, err
}
return []*runtime.KeyValue{kv}, nil
case err := <-w.fw.Errors:
return nil, err
}
}
}
func (w *watcher) Stop() error {
var err error
w.stopOnce.Do(func() {
w.cancel()
err = w.fw.Close()
})
return err
}