From 6d58e92fde3b0e6b63584088f7fda83cb99165a6 Mon Sep 17 00:00:00 2001 From: Kyle Brennan Date: Tue, 15 Apr 2025 17:23:49 +0000 Subject: [PATCH 1/4] Log the event name when hashConfig fails --- components/common-go/watch/file.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/common-go/watch/file.go b/components/common-go/watch/file.go index a86ec7bba1dbb8..fd3c9053eeb79c 100644 --- a/components/common-go/watch/file.go +++ b/components/common-go/watch/file.go @@ -85,7 +85,7 @@ func File(ctx context.Context, path string, onChange func()) error { currentHash, err := hashConfig(path) if err != nil { - log.WithError(err).Warn("Cannot check if config has changed") + log.WithError(err).WithField("event", event.Name).Warn("Cannot check if config has changed") return } From e43e0d80e12907e3965d6b1da052517235242922 Mon Sep 17 00:00:00 2001 From: Kyle Brennan Date: Tue, 15 Apr 2025 18:32:42 +0000 Subject: [PATCH 2/4] [common-go] backoff and retry watching files --- components/common-go/watch/file.go | 40 ++++++++++++++++++++++++------ 1 file changed, 32 insertions(+), 8 deletions(-) diff --git a/components/common-go/watch/file.go b/components/common-go/watch/file.go index fd3c9053eeb79c..c1d290f6f9ef9d 100644 --- a/components/common-go/watch/file.go +++ b/components/common-go/watch/file.go @@ -12,6 +12,7 @@ import ( "io" "os" "path/filepath" + "time" "github.com/fsnotify/fsnotify" @@ -59,6 +60,12 @@ func File(ctx context.Context, path string, onChange func()) error { fw.hash = hash go func() { + const ( + initialBackoff = 100 * time.Millisecond + maxBackoff = 15 * time.Second + ) + var currentBackoff time.Duration + defer func() { if err != nil { log.WithError(err).Error("Stopping file watch") @@ -83,23 +90,40 @@ func File(ctx context.Context, path string, onChange func()) error { continue } - currentHash, err := hashConfig(path) - if err != nil { - log.WithError(err).WithField("event", event.Name).Warn("Cannot check if config has changed") - return + currentHash, hashErr := hashConfig(path) + if hashErr != nil { + log.WithError(hashErr).WithField("event", event.Name).Warn("Cannot check if config has changed, backing off") + + if currentBackoff == 0 { + currentBackoff = initialBackoff + } else { + currentBackoff *= 2 + if currentBackoff > maxBackoff { + currentBackoff = maxBackoff + } + } + + select { + case <-time.After(currentBackoff): + case <-ctx.Done(): + log.Info("Context cancelled during backoff sleep, stopping file watcher") + return + } + continue } - // no change + currentBackoff = 0 + if currentHash == fw.hash { + log.WithField("path", path).Debug("Config file changed but content hash is the same") continue } log.WithField("path", path).Info("reloading file after change") - fw.hash = currentHash fw.onChange() - case err := <-watcher.Errors: - log.WithError(err).Error("Unexpected error watching event") + case watchErr := <-watcher.Errors: + log.WithError(watchErr).Error("Unexpected error watching event") case <-ctx.Done(): return } From 176c98ba4af83f7a676724f0db4114712d8cad2f Mon Sep 17 00:00:00 2001 From: Kyle Brennan Date: Wed, 16 Apr 2025 13:14:59 +0000 Subject: [PATCH 3/4] Revert "[common-go] backoff and retry watching files" This reverts commit e43e0d80e12907e3965d6b1da052517235242922. --- components/common-go/watch/file.go | 40 ++++++------------------------ 1 file changed, 8 insertions(+), 32 deletions(-) diff --git a/components/common-go/watch/file.go b/components/common-go/watch/file.go index c1d290f6f9ef9d..fd3c9053eeb79c 100644 --- a/components/common-go/watch/file.go +++ b/components/common-go/watch/file.go @@ -12,7 +12,6 @@ import ( "io" "os" "path/filepath" - "time" "github.com/fsnotify/fsnotify" @@ -60,12 +59,6 @@ func File(ctx context.Context, path string, onChange func()) error { fw.hash = hash go func() { - const ( - initialBackoff = 100 * time.Millisecond - maxBackoff = 15 * time.Second - ) - var currentBackoff time.Duration - defer func() { if err != nil { log.WithError(err).Error("Stopping file watch") @@ -90,40 +83,23 @@ func File(ctx context.Context, path string, onChange func()) error { continue } - currentHash, hashErr := hashConfig(path) - if hashErr != nil { - log.WithError(hashErr).WithField("event", event.Name).Warn("Cannot check if config has changed, backing off") - - if currentBackoff == 0 { - currentBackoff = initialBackoff - } else { - currentBackoff *= 2 - if currentBackoff > maxBackoff { - currentBackoff = maxBackoff - } - } - - select { - case <-time.After(currentBackoff): - case <-ctx.Done(): - log.Info("Context cancelled during backoff sleep, stopping file watcher") - return - } - continue + currentHash, err := hashConfig(path) + if err != nil { + log.WithError(err).WithField("event", event.Name).Warn("Cannot check if config has changed") + return } - currentBackoff = 0 - + // no change if currentHash == fw.hash { - log.WithField("path", path).Debug("Config file changed but content hash is the same") continue } log.WithField("path", path).Info("reloading file after change") + fw.hash = currentHash fw.onChange() - case watchErr := <-watcher.Errors: - log.WithError(watchErr).Error("Unexpected error watching event") + case err := <-watcher.Errors: + log.WithError(err).Error("Unexpected error watching event") case <-ctx.Done(): return } From 7a14aef6a93bec45f77c1733284dd8a5ef15596d Mon Sep 17 00:00:00 2001 From: Kyle Brennan Date: Wed, 16 Apr 2025 13:16:07 +0000 Subject: [PATCH 4/4] Continue watching, after hashConfig error This way, subsequent changes to the watched file may be honored --- components/common-go/watch/file.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/common-go/watch/file.go b/components/common-go/watch/file.go index fd3c9053eeb79c..564a63e3e9eaa0 100644 --- a/components/common-go/watch/file.go +++ b/components/common-go/watch/file.go @@ -86,7 +86,7 @@ func File(ctx context.Context, path string, onChange func()) error { currentHash, err := hashConfig(path) if err != nil { log.WithError(err).WithField("event", event.Name).Warn("Cannot check if config has changed") - return + continue } // no change