From f2f7dfed755e29912c14d6ef60b5792f03cae232 Mon Sep 17 00:00:00 2001 From: Virgil Date: Sun, 5 Apr 2026 01:59:28 +0000 Subject: [PATCH] fix(proxy): align config watcher with RFC Co-Authored-By: Virgil --- core_impl.go | 74 +++++++++++++++++----------------------------------- go.mod | 4 --- go.sum | 4 --- proxy.go | 4 +-- 4 files changed, 26 insertions(+), 60 deletions(-) diff --git a/core_impl.go b/core_impl.go index bfe04ef..e5c54a7 100644 --- a/core_impl.go +++ b/core_impl.go @@ -11,13 +11,10 @@ import ( "math" "net" "os" - "path/filepath" "strconv" "strings" "sync" "time" - - "github.com/fsnotify/fsnotify" ) // Result is the success/error carrier used by constructors and loaders. @@ -367,6 +364,9 @@ func NewConfigWatcher(configPath string, onChange func(*Config)) *ConfigWatcher onChange: onChange, done: make(chan struct{}), } + if data, err := os.ReadFile(configPath); err == nil { + watcher.lastSum = sha256.Sum256(data) + } if info, err := os.Stat(configPath); err == nil { watcher.lastMod = info.ModTime() } @@ -379,65 +379,42 @@ func (w *ConfigWatcher) Start() { return } w.mu.Lock() - if w.watcher != nil { + if w.started { w.mu.Unlock() return } - fsWatcher, err := fsnotify.NewWatcher() - if err != nil { - w.mu.Unlock() - return - } - w.watcher = fsWatcher + w.started = true w.mu.Unlock() - watchPath := filepath.Clean(w.path) - watchDir := filepath.Dir(watchPath) - if watchDir == "" { - watchDir = "." - } - if err := fsWatcher.Add(watchDir); err != nil { - _ = fsWatcher.Close() - w.mu.Lock() - if w.watcher == fsWatcher { - w.watcher = nil - } - w.mu.Unlock() - return - } - go func() { - defer func() { - _ = fsWatcher.Close() - w.mu.Lock() - if w.watcher == fsWatcher { - w.watcher = nil - } - w.mu.Unlock() - }() + ticker := time.NewTicker(time.Second) + defer ticker.Stop() for { select { - case event, ok := <-fsWatcher.Events: - if !ok { - return - } - if filepath.Clean(event.Name) != watchPath { + case <-ticker.C: + data, err := os.ReadFile(w.path) + if err != nil { continue } - if event.Op&(fsnotify.Write|fsnotify.Create|fsnotify.Rename|fsnotify.Remove|fsnotify.Chmod) == 0 { + sum := sha256.Sum256(data) + w.mu.Lock() + changed := sum != w.lastSum + if changed { + w.lastSum = sum + } + w.mu.Unlock() + if !changed { continue } + if info, err := os.Stat(w.path); err == nil { + w.mu.Lock() + w.lastMod = info.ModTime() + w.mu.Unlock() + } config, result := LoadConfig(w.path) if result.OK && config != nil { - if info, err := os.Stat(w.path); err == nil { - w.lastMod = info.ModTime() - } w.onChange(config) } - case _, ok := <-fsWatcher.Errors: - if !ok { - return - } case <-w.done: return } @@ -451,10 +428,7 @@ func (w *ConfigWatcher) Stop() { return } w.mu.Lock() - if w.watcher != nil { - _ = w.watcher.Close() - w.watcher = nil - } + w.started = false w.mu.Unlock() select { case <-w.done: diff --git a/go.mod b/go.mod index f14ce7b..b954a44 100644 --- a/go.mod +++ b/go.mod @@ -1,7 +1,3 @@ module dappco.re/go/proxy go 1.26.0 - -require github.com/fsnotify/fsnotify v1.7.0 - -require golang.org/x/sys v0.4.0 // indirect diff --git a/go.sum b/go.sum index ccd7ce9..e69de29 100644 --- a/go.sum +++ b/go.sum @@ -1,4 +0,0 @@ -github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= -github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= -golang.org/x/sys v0.4.0 h1:Zr2JFtRQNX3BCZ8YtxRE9hNJYC8J6I1MVbMg6owUp18= -golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= diff --git a/proxy.go b/proxy.go index 16733d4..7ec9281 100644 --- a/proxy.go +++ b/proxy.go @@ -8,7 +8,6 @@ package proxy import ( - "github.com/fsnotify/fsnotify" "net/http" "sync" "sync/atomic" @@ -120,9 +119,10 @@ type ConfigWatcher struct { path string onChange func(*Config) lastMod time.Time + lastSum [32]byte done chan struct{} mu sync.Mutex - watcher *fsnotify.Watcher + started bool } // RateLimiter throttles new connections per source IP.