Fix: Prevent unnecessary config reloads by checking file content hash
This commit is contained in:
parent
8175e36d60
commit
ea8ae63d70
1 changed files with 29 additions and 2 deletions
|
|
@ -1,6 +1,8 @@
|
||||||
package config
|
package config
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"crypto/sha256"
|
||||||
|
"encoding/hex"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"reflect"
|
"reflect"
|
||||||
|
|
@ -25,6 +27,7 @@ type ConfigWatcher struct {
|
||||||
stopChan chan struct{}
|
stopChan chan struct{}
|
||||||
stopOnce sync.Once // Ensures Stop() can only close channel once
|
stopOnce sync.Once // Ensures Stop() can only close channel once
|
||||||
lastModTime time.Time
|
lastModTime time.Time
|
||||||
|
lastEnvHash string
|
||||||
mockLastModTime time.Time
|
mockLastModTime time.Time
|
||||||
apiTokensLastModTime time.Time
|
apiTokensLastModTime time.Time
|
||||||
mu sync.RWMutex
|
mu sync.RWMutex
|
||||||
|
|
@ -114,9 +117,13 @@ func NewConfigWatcher(config *Config) (*ConfigWatcher, error) {
|
||||||
stopChan: make(chan struct{}),
|
stopChan: make(chan struct{}),
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get initial mod times
|
// Get initial mod times and hash
|
||||||
if stat, err := os.Stat(envPath); err == nil {
|
if stat, err := os.Stat(envPath); err == nil {
|
||||||
cw.lastModTime = stat.ModTime()
|
cw.lastModTime = stat.ModTime()
|
||||||
|
if content, err := os.ReadFile(envPath); err == nil {
|
||||||
|
hash := sha256.Sum256(content)
|
||||||
|
cw.lastEnvHash = hex.EncodeToString(hash[:])
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if mockEnvPath != "" {
|
if mockEnvPath != "" {
|
||||||
if stat, err := os.Stat(mockEnvPath); err == nil {
|
if stat, err := os.Stat(mockEnvPath); err == nil {
|
||||||
|
|
@ -195,9 +202,19 @@ func (cw *ConfigWatcher) watchForChanges() {
|
||||||
// Check if the event is for our .env file
|
// Check if the event is for our .env file
|
||||||
if filepath.Base(event.Name) == ".env" || event.Name == cw.envPath {
|
if filepath.Base(event.Name) == ".env" || event.Name == cw.envPath {
|
||||||
// Debounce - wait a bit for write to complete
|
// Debounce - wait a bit for write to complete
|
||||||
time.Sleep(100 * time.Millisecond)
|
time.Sleep(500 * time.Millisecond)
|
||||||
|
|
||||||
if event.Op&(fsnotify.Write|fsnotify.Create) != 0 {
|
if event.Op&(fsnotify.Write|fsnotify.Create) != 0 {
|
||||||
|
// Check if content actually changed to prevent restart loops on touch
|
||||||
|
newHash, err := cw.calculateFileHash(cw.envPath)
|
||||||
|
if err == nil {
|
||||||
|
if newHash == cw.lastEnvHash {
|
||||||
|
log.Debug().Msg("Detected .env file touch but content unchanged, skipping reload")
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
cw.lastEnvHash = newHash
|
||||||
|
}
|
||||||
|
|
||||||
log.Info().Str("event", event.Op.String()).Msg("Detected .env file change")
|
log.Info().Str("event", event.Op.String()).Msg("Detected .env file change")
|
||||||
cw.reloadConfig()
|
cw.reloadConfig()
|
||||||
}
|
}
|
||||||
|
|
@ -281,6 +298,16 @@ func (cw *ConfigWatcher) pollForChanges() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// calculateFileHash returns the SHA256 hash of a file
|
||||||
|
func (cw *ConfigWatcher) calculateFileHash(path string) (string, error) {
|
||||||
|
content, err := os.ReadFile(path)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
hash := sha256.Sum256(content)
|
||||||
|
return hex.EncodeToString(hash[:]), nil
|
||||||
|
}
|
||||||
|
|
||||||
// reloadConfig reloads the config from the .env file
|
// reloadConfig reloads the config from the .env file
|
||||||
func (cw *ConfigWatcher) reloadConfig() {
|
func (cw *ConfigWatcher) reloadConfig() {
|
||||||
cw.mu.Lock()
|
cw.mu.Lock()
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue