Files
postmoogle/vendor/gitlab.com/etke.cc/go/fswatcher/fswatcher.go
2023-04-09 22:19:52 +03:00

90 lines
1.5 KiB
Go

package fswatcher
import (
"math"
"path/filepath"
"sync"
"time"
"github.com/fsnotify/fsnotify"
)
// DefaultDelay to avoid unnecessary handler calls
const DefaultDelay = 100 * time.Millisecond
// Watcher of file system changes
type Watcher struct {
watcher *fsnotify.Watcher
delay time.Duration
files []string
mu sync.Mutex
t map[string]*time.Timer
}
// Creates FS Watcher
func New(files []string, delay time.Duration) (*Watcher, error) {
if delay <= 0 {
delay = DefaultDelay
}
watcher, err := fsnotify.NewWatcher()
if err != nil {
return nil, err
}
for _, file := range files {
err = watcher.Add(filepath.Dir(file))
if err != nil {
return nil, err
}
}
fswatcher := &Watcher{
watcher: watcher,
delay: delay,
files: files,
t: make(map[string]*time.Timer),
}
return fswatcher, nil
}
func (w *Watcher) watch(handler func(e fsnotify.Event)) {
for e := range w.watcher.Events {
handler(e)
}
}
// Start watcher
func (w *Watcher) Start(handler func(e fsnotify.Event)) {
w.watch(func(e fsnotify.Event) {
var found bool
for _, f := range w.files {
if f == e.Name {
found = true
}
}
if !found {
return
}
w.mu.Lock()
t, ok := w.t[e.Name]
w.mu.Unlock()
if !ok {
t = time.AfterFunc(math.MaxInt64, func() {
handler(e)
})
t.Stop()
w.mu.Lock()
w.t[e.Name] = t
w.mu.Unlock()
}
t.Reset(w.delay)
})
}
// Stop watcher
func (w *Watcher) Stop() error {
return w.watcher.Close()
}