Files
kgpz_web/helpers/watcher.go
Simon Martens 84fa6f7fa4 better logging
2024-11-16 17:30:14 +01:00

134 lines
2.3 KiB
Go

package helpers
import (
"errors"
"io/fs"
"path/filepath"
"sync"
"github.com/Theodor-Springmann-Stiftung/kgpz_web/helpers/logging"
"github.com/fsnotify/fsnotify"
)
var NotInitializedError = errors.New("FileWatcher not initialized")
var NoWatchFunctionError = errors.New("No watch function provided")
type IFileWatcher interface {
RecursiveDir(path string) error
Dir(path string) error
Append(fn func(string))
Prepend(fn func(string))
Watch() error
Close()
Restart()
}
type FileWatcher struct {
mu sync.Mutex
wf []func(string)
paths []string
watcher *fsnotify.Watcher
}
func NewFileWatcher() (*FileWatcher, error) {
fw := &FileWatcher{mu: sync.Mutex{}}
fw.Watch()
return fw, nil
}
func (fw *FileWatcher) RecursiveDir(path string) error {
err := filepath.WalkDir(path, func(path string, d fs.DirEntry, err error) error {
if d.IsDir() {
err := fw.Dir(path)
if err != nil {
return err
}
}
return nil
})
return err
}
func (fw *FileWatcher) Dir(path string) error {
fw.mu.Lock()
defer fw.mu.Unlock()
if fw.watcher != nil {
err := fw.watcher.Add(path)
if err != nil {
return err
}
}
fw.paths = append(fw.paths, path)
return nil
}
func (fw *FileWatcher) Append(fn func(string)) {
fw.mu.Lock()
defer fw.mu.Unlock()
fw.wf = append(fw.wf, fn)
}
func (fw *FileWatcher) Prepend(fn func(string)) {
fw.mu.Lock()
defer fw.mu.Unlock()
fw.wf = append([]func(string){fn}, fw.wf...)
}
func (fw *FileWatcher) Watch() error {
watcher, err := fsnotify.NewWatcher()
if err != nil {
return err
}
fw.mu.Lock()
fw.watcher = watcher
fw.mu.Unlock()
// Start listening for events.
go func() {
for {
select {
case event, ok := <-watcher.Events:
if !ok {
return
}
if !event.Has(fsnotify.Chmod) {
fw.mu.Lock()
for _, wf := range fw.wf {
wf(event.Name)
}
fw.mu.Unlock()
}
case err, ok := <-watcher.Errors:
if !ok {
return
}
logging.Error(err)
}
}
}()
return nil
}
// INFO: After closing the watcher, you can't use it anymore.
// Also, after a restart, you need to re add the paths
func (fw *FileWatcher) Close() {
fw.mu.Lock()
defer fw.mu.Unlock()
if fw.watcher != nil {
fw.watcher.Close()
}
fw.watcher = nil
fw.paths = nil
}
func (fw *FileWatcher) Restart() {
fw.Close()
fw.Watch()
}