bugfix: Move all inotify to filehelper (#279)
This commit is contained in:
parent
362019738d
commit
fafacfeafb
|
|
@ -5,10 +5,9 @@ import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
config "github.com/OliveTin/OliveTin/internal/config"
|
config "github.com/OliveTin/OliveTin/internal/config"
|
||||||
|
"github.com/OliveTin/OliveTin/internal/filehelper"
|
||||||
sv "github.com/OliveTin/OliveTin/internal/stringvariables"
|
sv "github.com/OliveTin/OliveTin/internal/stringvariables"
|
||||||
"github.com/fsnotify/fsnotify"
|
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
"github.com/spf13/viper"
|
|
||||||
"gopkg.in/yaml.v3"
|
"gopkg.in/yaml.v3"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
|
|
@ -17,7 +16,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
func SetupEntityFileWatchers(cfg *config.Config) {
|
func SetupEntityFileWatchers(cfg *config.Config) {
|
||||||
configDir := filepath.Dir(viper.ConfigFileUsed())
|
configDir := cfg.GetDir()
|
||||||
|
|
||||||
configDirVar := filepath.Join(configDir, "var") // for development purposes
|
configDirVar := filepath.Join(configDir, "var") // for development purposes
|
||||||
|
|
||||||
|
|
@ -36,71 +35,9 @@ func SetupEntityFileWatchers(cfg *config.Config) {
|
||||||
}).Debugf("Adding config dir to entity file path")
|
}).Debugf("Adding config dir to entity file path")
|
||||||
}
|
}
|
||||||
|
|
||||||
go watch(p, ef.Name)
|
filehelper.WatchFileWrite(p, func(filename string) {
|
||||||
|
loadEntityFile(p, ef.Name)
|
||||||
loadEntityFile(p, ef.Name)
|
})
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func watch(file string, entityname string) {
|
|
||||||
log.WithFields(log.Fields{
|
|
||||||
"file": file,
|
|
||||||
"name": entityname,
|
|
||||||
}).Infof("Watching entity file")
|
|
||||||
|
|
||||||
watcher, err := fsnotify.NewWatcher()
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("Could not watch entity file: %v", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
defer watcher.Close()
|
|
||||||
|
|
||||||
done := make(chan bool)
|
|
||||||
|
|
||||||
go func() {
|
|
||||||
for {
|
|
||||||
processEvent(watcher, file, entityname)
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
err = watcher.Add(file)
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
log.WithFields(log.Fields{
|
|
||||||
"file": file,
|
|
||||||
}).Errorf("Could not create entity watcher: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
<-done
|
|
||||||
}
|
|
||||||
|
|
||||||
func processEvent(watcher *fsnotify.Watcher, filename string, entityname string) {
|
|
||||||
select {
|
|
||||||
case event, ok := <-watcher.Events:
|
|
||||||
if !ok {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
loadEntityFileIfWritten(&event, filename, entityname)
|
|
||||||
|
|
||||||
return
|
|
||||||
case err := <-watcher.Errors:
|
|
||||||
log.Errorf("Error in fsnotify: %v", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func loadEntityFileIfWritten(event *fsnotify.Event, filename string, entityname string) {
|
|
||||||
if event.Has(fsnotify.Remove) {
|
|
||||||
log.WithFields(log.Fields{
|
|
||||||
"file": filename,
|
|
||||||
}).Warnf("Entity file deleted! Will no longer be able to watch for changes!")
|
|
||||||
}
|
|
||||||
|
|
||||||
if event.Has(fsnotify.Write) {
|
|
||||||
loadEntityFile(filename, entityname)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -305,6 +305,7 @@ func stepRequestAction(req *ExecutionRequest) bool {
|
||||||
|
|
||||||
log.WithFields(log.Fields{
|
log.WithFields(log.Fields{
|
||||||
"actionTitle": req.logEntry.ActionTitle,
|
"actionTitle": req.logEntry.ActionTitle,
|
||||||
|
"tags": req.Tags,
|
||||||
}).Infof("Action requested")
|
}).Infof("Action requested")
|
||||||
|
|
||||||
return true
|
return true
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,44 @@ import (
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
)
|
)
|
||||||
|
|
||||||
func WatchFile(fullpath string, callback func()) {
|
type watchContext struct {
|
||||||
|
filename string
|
||||||
|
filedir string
|
||||||
|
callback func(filename string)
|
||||||
|
interestedEvent fsnotify.Op
|
||||||
|
}
|
||||||
|
|
||||||
|
func WatchDirectoryCreate(fullpath string, callback func(filename string)) {
|
||||||
|
watchPath(&watchContext{
|
||||||
|
filedir: fullpath,
|
||||||
|
filename: "",
|
||||||
|
callback: callback,
|
||||||
|
interestedEvent: fsnotify.Create,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func WatchDirectoryWrite(fullpath string, callback func(filename string)) {
|
||||||
|
watchPath(&watchContext{
|
||||||
|
filedir: fullpath,
|
||||||
|
filename: "",
|
||||||
|
callback: callback,
|
||||||
|
interestedEvent: fsnotify.Write,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func WatchFileWrite(fullpath string, callback func(filename string)) {
|
||||||
|
filename := filepath.Base(fullpath)
|
||||||
|
filedir := filepath.Dir(fullpath)
|
||||||
|
|
||||||
|
watchPath(&watchContext{
|
||||||
|
filedir: filedir,
|
||||||
|
filename: filename,
|
||||||
|
callback: callback,
|
||||||
|
interestedEvent: fsnotify.Write,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func watchPath(ctx *watchContext) {
|
||||||
watcher, err := fsnotify.NewWatcher()
|
watcher, err := fsnotify.NewWatcher()
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -18,16 +55,13 @@ func WatchFile(fullpath string, callback func()) {
|
||||||
|
|
||||||
done := make(chan bool)
|
done := make(chan bool)
|
||||||
|
|
||||||
filename := filepath.Base(fullpath)
|
|
||||||
filedir := filepath.Dir(fullpath)
|
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
for {
|
for {
|
||||||
processEvent(filename, watcher, fsnotify.Write, callback)
|
processEvent(ctx, watcher)
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
err = watcher.Add(filedir)
|
err = watcher.Add(ctx.filedir)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Errorf("Could not create watcher: %v", err)
|
log.Errorf("Could not create watcher: %v", err)
|
||||||
|
|
@ -36,10 +70,10 @@ func WatchFile(fullpath string, callback func()) {
|
||||||
<-done
|
<-done
|
||||||
}
|
}
|
||||||
|
|
||||||
func processEvent(filename string, watcher *fsnotify.Watcher, eventType fsnotify.Op, callback func()) {
|
func processEvent(ctx *watchContext, watcher *fsnotify.Watcher) {
|
||||||
select {
|
select {
|
||||||
case event, ok := <-watcher.Events:
|
case event, ok := <-watcher.Events:
|
||||||
if !consumeEvent(ok, filename, &event, callback) {
|
if !consumeEvent(ok, ctx, &event) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -50,25 +84,25 @@ func processEvent(filename string, watcher *fsnotify.Watcher, eventType fsnotify
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func consumeEvent(ok bool, filename string, event *fsnotify.Event, callback func()) bool {
|
func consumeEvent(ok bool, ctx *watchContext, event *fsnotify.Event) bool {
|
||||||
if !ok {
|
if !ok {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
if filepath.Base(event.Name) != filename {
|
if ctx.filename != "" && filepath.Base(event.Name) != ctx.filename {
|
||||||
log.Tracef("fsnotify irreleventa event different file %+v", event)
|
log.Tracef("fsnotify irreleventa event different file %+v", event)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
consumeWriteEvents(event, callback)
|
consumeRelevantEvents(ctx, event)
|
||||||
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func consumeWriteEvents(event *fsnotify.Event, callback func()) {
|
func consumeRelevantEvents(ctx *watchContext, event *fsnotify.Event) {
|
||||||
if event.Has(fsnotify.Write) {
|
if event.Has(ctx.interestedEvent) {
|
||||||
log.Debugf("fsnotify write event: %v", event)
|
log.Debugf("fsnotify write event: %v", event)
|
||||||
callback()
|
ctx.callback(event.Name)
|
||||||
} else {
|
} else {
|
||||||
log.Debugf("fsnotify irrelevant event on file %v", event)
|
log.Debugf("fsnotify irrelevant event on file %v", event)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -19,22 +19,23 @@ func Schedule(cfg *config.Config, ex *executor.Executor) {
|
||||||
|
|
||||||
for _, action := range cfg.Actions {
|
for _, action := range cfg.Actions {
|
||||||
if action.ExecOnCalendarFile != "" {
|
if action.ExecOnCalendarFile != "" {
|
||||||
x := func() {
|
x := func(filename string) {
|
||||||
parseCalendarFile(action, cfg, ex)
|
parseCalendarFile(action, cfg, ex, filename)
|
||||||
}
|
}
|
||||||
|
|
||||||
go filehelper.WatchFile(action.ExecOnCalendarFile, x)
|
go filehelper.WatchFileWrite(action.ExecOnCalendarFile, x)
|
||||||
|
|
||||||
x()
|
x(action.ExecOnCalendarFile)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseCalendarFile(action *config.Action, cfg *config.Config, ex *executor.Executor) {
|
func parseCalendarFile(action *config.Action, cfg *config.Config, ex *executor.Executor, filename string) {
|
||||||
filehelper.Touch(action.ExecOnCalendarFile, "calendar file")
|
filehelper.Touch(action.ExecOnCalendarFile, "calendar file")
|
||||||
|
|
||||||
log.WithFields(log.Fields{
|
log.WithFields(log.Fields{
|
||||||
"actionTitle": action.Title,
|
"actionTitle": action.Title,
|
||||||
|
"filename": filename,
|
||||||
}).Infof("Parsing calendar file")
|
}).Infof("Parsing calendar file")
|
||||||
|
|
||||||
yfile, err := ioutil.ReadFile(action.ExecOnCalendarFile)
|
yfile, err := ioutil.ReadFile(action.ExecOnCalendarFile)
|
||||||
|
|
|
||||||
|
|
@ -4,83 +4,37 @@ import (
|
||||||
"github.com/OliveTin/OliveTin/internal/acl"
|
"github.com/OliveTin/OliveTin/internal/acl"
|
||||||
"github.com/OliveTin/OliveTin/internal/config"
|
"github.com/OliveTin/OliveTin/internal/config"
|
||||||
"github.com/OliveTin/OliveTin/internal/executor"
|
"github.com/OliveTin/OliveTin/internal/executor"
|
||||||
"github.com/fsnotify/fsnotify"
|
"github.com/OliveTin/OliveTin/internal/filehelper"
|
||||||
log "github.com/sirupsen/logrus"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func WatchFilesInDirectory(cfg *config.Config, ex *executor.Executor) {
|
func WatchFilesInDirectory(cfg *config.Config, ex *executor.Executor) {
|
||||||
for _, action := range cfg.Actions {
|
for _, action := range cfg.Actions {
|
||||||
for _, dirname := range action.ExecOnFileChangedInDir {
|
for _, dirname := range action.ExecOnFileChangedInDir {
|
||||||
watch(dirname, action, cfg, ex, fsnotify.Write)
|
filehelper.WatchDirectoryWrite(dirname, func(filename string) {
|
||||||
|
scheduleExec(action, cfg, ex, filename)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, dirname := range action.ExecOnFileCreatedInDir {
|
for _, dirname := range action.ExecOnFileCreatedInDir {
|
||||||
watch(dirname, action, cfg, ex, fsnotify.Create)
|
filehelper.WatchDirectoryCreate(dirname, func(filename string) {
|
||||||
|
scheduleExec(action, cfg, ex, filename)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func watch(directory string, action *config.Action, cfg *config.Config, ex *executor.Executor, eventType fsnotify.Op) {
|
func scheduleExec(action *config.Action, cfg *config.Config, ex *executor.Executor, filename string) {
|
||||||
log.WithFields(log.Fields{
|
req := &executor.ExecutionRequest{
|
||||||
"dir": directory,
|
ActionTitle: action.Title,
|
||||||
"eventType": eventType,
|
Cfg: cfg,
|
||||||
}).Infof("Watching dir")
|
Tags: []string{"fileindir"},
|
||||||
|
Arguments: map[string]string{
|
||||||
watcher, err := fsnotify.NewWatcher()
|
"filename": filename,
|
||||||
|
},
|
||||||
if err != nil {
|
AuthenticatedUser: &acl.AuthenticatedUser{
|
||||||
log.Errorf("Could not watch for files being created: %v", err)
|
Username: "fileindir",
|
||||||
return
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
defer watcher.Close()
|
ex.ExecRequest(req)
|
||||||
|
|
||||||
done := make(chan bool)
|
|
||||||
|
|
||||||
go func() {
|
|
||||||
for {
|
|
||||||
processEvent(watcher, action, cfg, ex, eventType)
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
err = watcher.Add("/tmp")
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("Could not create watcher: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
<-done
|
|
||||||
}
|
|
||||||
|
|
||||||
func processEvent(watcher *fsnotify.Watcher, action *config.Action, cfg *config.Config, ex *executor.Executor, eventType fsnotify.Op) {
|
|
||||||
select {
|
|
||||||
case event, ok := <-watcher.Events:
|
|
||||||
if !ok {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
checkEvent(&event, action, cfg, ex, eventType)
|
|
||||||
break
|
|
||||||
case err := <-watcher.Errors:
|
|
||||||
log.Errorf("Error in fsnotify: %v", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func checkEvent(event *fsnotify.Event, action *config.Action, cfg *config.Config, ex *executor.Executor, eventType fsnotify.Op) {
|
|
||||||
if event.Has(eventType) {
|
|
||||||
req := &executor.ExecutionRequest{
|
|
||||||
ActionTitle: action.Title,
|
|
||||||
Cfg: cfg,
|
|
||||||
Tags: []string{"fileindir"},
|
|
||||||
Arguments: map[string]string{
|
|
||||||
"filename": event.Name,
|
|
||||||
},
|
|
||||||
AuthenticatedUser: &acl.AuthenticatedUser{
|
|
||||||
Username: "fileindir",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
ex.ExecRequest(req)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue