Skip to content
Snippets Groups Projects
Verified Commit b81a2b5f authored by Volker Schukai's avatar Volker Schukai :alien:
Browse files

feat: new function StopWatching

parent 1d5bac6c
No related branches found
No related tags found
No related merge requests found
...@@ -29,9 +29,30 @@ func (e WatcherNotActiveError) Error() string { ...@@ -29,9 +29,30 @@ func (e WatcherNotActiveError) Error() string {
return "Watcher is not active" return "Watcher is not active"
} }
// WatcherNotActiveError represents an error when trying to add a path that is already being watched.
type WatcherNotRunningError struct{}
func (e WatcherNotRunningError) Error() string {
return "Watcher is not active"
}
// WatcherAlreadyRunningError represents an error when trying to add a path that is already being watched.
type WatcherAlreadyRunningError struct{}
func (e WatcherAlreadyRunningError) Error() string {
return "Watcher is already running"
}
// LighthouseNotActiveError represents an error when trying to add a path that is already being watched. // LighthouseNotActiveError represents an error when trying to add a path that is already being watched.
type LighthouseNotActiveError struct{} type LighthouseNotActiveError struct{}
func (e LighthouseNotActiveError) Error() string { func (e LighthouseNotActiveError) Error() string {
return "lighthouse is not active" return "lighthouse is not active"
} }
// WatcherNotActiveError represents an error when trying to add a path that is already being watched.
type WatcherAlreadyActiveError struct{}
func (e WatcherAlreadyActiveError) Error() string {
return "Watcher is already active"
}
...@@ -23,8 +23,10 @@ type lighthouse struct { ...@@ -23,8 +23,10 @@ type lighthouse struct {
fsnotify *fsnotify.Watcher fsnotify *fsnotify.Watcher
mutex sync.Mutex mutex sync.Mutex
active bool active bool
running bool
onError EventErrorCallback onError EventErrorCallback
debounce time.Duration debounce time.Duration
quit chan struct{}
} }
// SetOnError Methode, um onError zu setzen // SetOnError Methode, um onError zu setzen
...@@ -47,7 +49,11 @@ type Lighthouse interface { ...@@ -47,7 +49,11 @@ type Lighthouse interface {
IsActiveWatched(path string) bool IsActiveWatched(path string) bool
IsWatched(path string) bool IsWatched(path string) bool
IsRunning() bool IsRunning() bool
StartWatching()
IsActive() bool
StartWatching() error
StopWatching() error
SetOnError(callback EventErrorCallback) SetOnError(callback EventErrorCallback)
SetDebounce(duration time.Duration) SetDebounce(duration time.Duration)
...@@ -56,6 +62,7 @@ type Lighthouse interface { ...@@ -56,6 +62,7 @@ type Lighthouse interface {
// NewLighthouse creates a new lighthouse instance. // NewLighthouse creates a new lighthouse instance.
func NewLighthouse() Lighthouse { func NewLighthouse() Lighthouse {
l := &lighthouse{} l := &lighthouse{}
l.debounce = 500 * time.Millisecond
l.checkAndInit() l.checkAndInit()
return l return l
...@@ -63,30 +70,49 @@ func NewLighthouse() Lighthouse { ...@@ -63,30 +70,49 @@ func NewLighthouse() Lighthouse {
func (l *lighthouse) checkAndInit() { func (l *lighthouse) checkAndInit() {
var err error
if l.active { if l.active {
return return
} }
l.debounce = 500 * time.Millisecond
if l.watchers == nil { if l.watchers == nil {
l.watchers = make(map[string]*Watch) l.watchers = make(map[string]*Watch)
} }
if l.fsnotify == nil { if l.fsnotify == nil {
var err error
l.fsnotify, err = fsnotify.NewWatcher() l.fsnotify, err = fsnotify.NewWatcher()
if err != nil { if err != nil {
return return
} }
} }
// test if fsnotify is running
err = l.fsnotify.Add("/undefined-path-123456789")
if err != nil {
if err.Error() == "inotify instance already closed" {
l.fsnotify, err = fsnotify.NewWatcher()
if err != nil {
return
}
}
}
l.active = true l.active = true
} }
// IsRunning returns true if the watcher is active, false otherwise. // IsRunning returns true if the watcher is active, false otherwise.
func (l *lighthouse) IsRunning() bool { func (l *lighthouse) IsRunning() bool {
l.mutex.Lock()
defer l.mutex.Unlock()
return l.running
}
// IsActive returns true if the watcher is active, false otherwise.
func (l *lighthouse) IsActive() bool {
l.mutex.Lock()
defer l.mutex.Unlock()
return l.active return l.active
} }
......
...@@ -48,7 +48,7 @@ func TestRemoveWatch(t *testing.T) { ...@@ -48,7 +48,7 @@ func TestRemoveWatch(t *testing.T) {
func TestNewLighthouse(t *testing.T) { func TestNewLighthouse(t *testing.T) {
l := NewLighthouse() l := NewLighthouse()
assert.NotNil(t, l) assert.NotNil(t, l)
assert.True(t, l.IsRunning()) assert.True(t, l.IsActive())
} }
func TestIsWatched(t *testing.T) { func TestIsWatched(t *testing.T) {
......
...@@ -7,7 +7,34 @@ import ( ...@@ -7,7 +7,34 @@ import (
"time" "time"
) )
func (l *lighthouse) StartWatching() { // StopWatching stops watching the given file for changes
// If the watcher is not running, an error WatcherNotRunningError is returned.
func (l *lighthouse) StopWatching() error {
if !l.IsRunning() {
return WatcherNotRunningError{}
}
l.mutex.Lock()
defer l.mutex.Unlock()
close(l.quit)
l.running = false
return nil
}
// StartWatching starts watching the given file for changes
func (l *lighthouse) StartWatching() error {
if l.IsRunning() {
return WatcherAlreadyRunningError{}
}
l.mutex.Lock()
defer l.mutex.Unlock()
l.quit = make(chan struct{})
l.running = true
l.checkAndInit()
go func() { go func() {
eventChannel := make(chan fsnotify.Event, 100) eventChannel := make(chan fsnotify.Event, 100)
errorChannel := make(chan error, 100) errorChannel := make(chan error, 100)
...@@ -17,7 +44,14 @@ func (l *lighthouse) StartWatching() { ...@@ -17,7 +44,14 @@ func (l *lighthouse) StartWatching() {
go func() { go func() {
for { for {
l.mutex.Lock()
quit := l.quit
l.mutex.Unlock()
select { select {
case <-quit:
return
case event := <-l.fsnotify.Events: case event := <-l.fsnotify.Events:
eventChannel <- event eventChannel <- event
case err := <-l.fsnotify.Errors: case err := <-l.fsnotify.Errors:
...@@ -27,7 +61,14 @@ func (l *lighthouse) StartWatching() { ...@@ -27,7 +61,14 @@ func (l *lighthouse) StartWatching() {
}() }()
for { for {
l.mutex.Lock()
quit := l.quit
l.mutex.Unlock()
select { select {
case <-quit:
return
case event := <-eventChannel: case event := <-eventChannel:
debounceMutex.Lock() debounceMutex.Lock()
...@@ -123,8 +164,12 @@ func (l *lighthouse) StartWatching() { ...@@ -123,8 +164,12 @@ func (l *lighthouse) StartWatching() {
debounceMutex.Unlock() debounceMutex.Unlock()
case err := <-errorChannel: case err := <-errorChannel:
go l.onError(err) if l.onError != nil {
go l.onError(err)
}
} }
} }
}() }()
return nil
} }
...@@ -143,3 +143,31 @@ func TestRecreateEvent(t *testing.T) { ...@@ -143,3 +143,31 @@ func TestRecreateEvent(t *testing.T) {
t.Fail() t.Fail()
} }
} }
func TestStopWatching(t *testing.T) {
l := NewLighthouse() // Erstellen Sie eine neue Instanz der `lighthouse`-Struktur.
// Start Watching
_ = l.StartWatching()
// Erlauben Sie dem System etwas Zeit, um den Watch-Prozess zu starten.
time.Sleep(time.Second * 1)
if !l.IsRunning() {
t.Fatal("l.active is false, but should be true after StartWatching")
}
// Stop Watching
err := l.StopWatching()
if err != nil {
t.Fatalf("StopWatching failed: %v", err)
}
// Überprüfen Sie, ob die Goroutine und der Watcher gestoppt wurden.
if l.IsRunning() {
t.Fatal("l.active is true, but should be false after StopWatching")
}
_ = l.StartWatching()
assert.True(t, l.IsRunning())
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment