fix(proxy): align config watcher with RFC
Co-Authored-By: Virgil <virgil@lethean.io>
This commit is contained in:
parent
ce3b7a50cd
commit
f2f7dfed75
4 changed files with 26 additions and 60 deletions
74
core_impl.go
74
core_impl.go
|
|
@ -11,13 +11,10 @@ import (
|
||||||
"math"
|
"math"
|
||||||
"net"
|
"net"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/fsnotify/fsnotify"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Result is the success/error carrier used by constructors and loaders.
|
// 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,
|
onChange: onChange,
|
||||||
done: make(chan struct{}),
|
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 {
|
if info, err := os.Stat(configPath); err == nil {
|
||||||
watcher.lastMod = info.ModTime()
|
watcher.lastMod = info.ModTime()
|
||||||
}
|
}
|
||||||
|
|
@ -379,65 +379,42 @@ func (w *ConfigWatcher) Start() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
w.mu.Lock()
|
w.mu.Lock()
|
||||||
if w.watcher != nil {
|
if w.started {
|
||||||
w.mu.Unlock()
|
w.mu.Unlock()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
fsWatcher, err := fsnotify.NewWatcher()
|
w.started = true
|
||||||
if err != nil {
|
|
||||||
w.mu.Unlock()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
w.watcher = fsWatcher
|
|
||||||
w.mu.Unlock()
|
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() {
|
go func() {
|
||||||
defer func() {
|
ticker := time.NewTicker(time.Second)
|
||||||
_ = fsWatcher.Close()
|
defer ticker.Stop()
|
||||||
w.mu.Lock()
|
|
||||||
if w.watcher == fsWatcher {
|
|
||||||
w.watcher = nil
|
|
||||||
}
|
|
||||||
w.mu.Unlock()
|
|
||||||
}()
|
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case event, ok := <-fsWatcher.Events:
|
case <-ticker.C:
|
||||||
if !ok {
|
data, err := os.ReadFile(w.path)
|
||||||
return
|
if err != nil {
|
||||||
}
|
|
||||||
if filepath.Clean(event.Name) != watchPath {
|
|
||||||
continue
|
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
|
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)
|
config, result := LoadConfig(w.path)
|
||||||
if result.OK && config != nil {
|
if result.OK && config != nil {
|
||||||
if info, err := os.Stat(w.path); err == nil {
|
|
||||||
w.lastMod = info.ModTime()
|
|
||||||
}
|
|
||||||
w.onChange(config)
|
w.onChange(config)
|
||||||
}
|
}
|
||||||
case _, ok := <-fsWatcher.Errors:
|
|
||||||
if !ok {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
case <-w.done:
|
case <-w.done:
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
@ -451,10 +428,7 @@ func (w *ConfigWatcher) Stop() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
w.mu.Lock()
|
w.mu.Lock()
|
||||||
if w.watcher != nil {
|
w.started = false
|
||||||
_ = w.watcher.Close()
|
|
||||||
w.watcher = nil
|
|
||||||
}
|
|
||||||
w.mu.Unlock()
|
w.mu.Unlock()
|
||||||
select {
|
select {
|
||||||
case <-w.done:
|
case <-w.done:
|
||||||
|
|
|
||||||
4
go.mod
4
go.mod
|
|
@ -1,7 +1,3 @@
|
||||||
module dappco.re/go/proxy
|
module dappco.re/go/proxy
|
||||||
|
|
||||||
go 1.26.0
|
go 1.26.0
|
||||||
|
|
||||||
require github.com/fsnotify/fsnotify v1.7.0
|
|
||||||
|
|
||||||
require golang.org/x/sys v0.4.0 // indirect
|
|
||||||
|
|
|
||||||
4
go.sum
4
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=
|
|
||||||
4
proxy.go
4
proxy.go
|
|
@ -8,7 +8,6 @@
|
||||||
package proxy
|
package proxy
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/fsnotify/fsnotify"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"sync"
|
"sync"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
|
|
@ -120,9 +119,10 @@ type ConfigWatcher struct {
|
||||||
path string
|
path string
|
||||||
onChange func(*Config)
|
onChange func(*Config)
|
||||||
lastMod time.Time
|
lastMod time.Time
|
||||||
|
lastSum [32]byte
|
||||||
done chan struct{}
|
done chan struct{}
|
||||||
mu sync.Mutex
|
mu sync.Mutex
|
||||||
watcher *fsnotify.Watcher
|
started bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// RateLimiter throttles new connections per source IP.
|
// RateLimiter throttles new connections per source IP.
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue