Ver Fonte

bugfix: Move all inotify to filehelper (#279)

James Read há 2 anos atrás
pai
commit
fafacfeafb

+ 5 - 68
internal/entityfiles/entityfiles.go

@@ -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)
-
-		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)
+		filehelper.WatchFileWrite(p, func(filename string) {
+			loadEntityFile(p, ef.Name)
+		})
 	}
 	}
 }
 }
 
 

+ 1 - 0
internal/executor/executor.go

@@ -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

+ 48 - 14
internal/filehelper/file_change_notify.go

@@ -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()) {
-	if event.Has(fsnotify.Write) {
+func consumeRelevantEvents(ctx *watchContext, event *fsnotify.Event) {
+	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)
 	}
 	}

+ 6 - 5
internal/oncalendarfile/calendar.go

@@ -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() {
-				parseCalendarFile(action, cfg, ex)
+			x := func(filename string) {
+				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)

+ 19 - 65
internal/onfileindir/fileindir.go

@@ -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"
-	log "github.com/sirupsen/logrus"
+	"github.com/OliveTin/OliveTin/internal/filehelper"
 )
 )
 
 
 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) {
-	log.WithFields(log.Fields{
-		"dir":       directory,
-		"eventType": eventType,
-	}).Infof("Watching dir")
-
-	watcher, err := fsnotify.NewWatcher()
-
-	if err != nil {
-		log.Errorf("Could not watch for files being created: %v", err)
-		return
-	}
-
-	defer watcher.Close()
-
-	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)
+func scheduleExec(action *config.Action, cfg *config.Config, ex *executor.Executor, filename string) {
+	req := &executor.ExecutionRequest{
+		ActionTitle: action.Title,
+		Cfg:         cfg,
+		Tags:        []string{"fileindir"},
+		Arguments: map[string]string{
+			"filename": filename,
+		},
+		AuthenticatedUser: &acl.AuthenticatedUser{
+			Username: "fileindir",
+		},
 	}
 	}
 
 
-	<-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)
-	}
+	ex.ExecRequest(req)
 }
 }