feat: removed comments and uses the passed whitelists
This commit is contained in:
66
watcher.go
66
watcher.go
@@ -1,37 +1,19 @@
|
||||
// watcher.go — permanent whitelist file watcher
|
||||
//
|
||||
// The watcher polls the permanent whitelist file every cfg.WatchInterval
|
||||
// seconds and reloads the in-memory store if the file has changed.
|
||||
//
|
||||
// Why poll instead of inotify?
|
||||
//
|
||||
// - Polling is simpler and works inside Docker containers where inotify
|
||||
// may not be available (no host filesystem access).
|
||||
// - The polling interval (30s default) is fast enough for admin
|
||||
// whitelisting operations.
|
||||
// - If you want inotify, add it later.
|
||||
//
|
||||
// We only reload when the file's mtime changes, so frequent touch-
|
||||
// operations don't cause unnecessary reloads.
|
||||
//
|
||||
// The watcher uses a mutex to protect the in-memory store. This is
|
||||
// necessary because the watcher runs in a separate goroutine and the
|
||||
// auth handler reads from the same store.
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"log"
|
||||
"log/slog"
|
||||
"os"
|
||||
"time"
|
||||
)
|
||||
|
||||
// newPermanentWhitelistWatcher creates a watcher that reloads the
|
||||
// permanent whitelist file from disk.
|
||||
//
|
||||
// The watcher loads the file once immediately on creation, then polls
|
||||
// every interval.
|
||||
type watcher struct {
|
||||
path string
|
||||
interval time.Duration
|
||||
store *PermanentWhitelist
|
||||
lastMod time.Time
|
||||
}
|
||||
|
||||
func newPermanentWhitelistWatcher(path string, interval time.Duration, store *PermanentWhitelist) *watcher {
|
||||
w := &watcher{
|
||||
path: path,
|
||||
@@ -42,55 +24,32 @@ func newPermanentWhitelistWatcher(path string, interval time.Duration, store *Pe
|
||||
return w
|
||||
}
|
||||
|
||||
// watcher polls a file and reloads the whitelist when it changes.
|
||||
type watcher struct {
|
||||
path string
|
||||
interval time.Duration
|
||||
store *PermanentWhitelist
|
||||
lastMod time.Time
|
||||
}
|
||||
|
||||
// start begins the polling loop.
|
||||
func (w *watcher) start() {
|
||||
go func() {
|
||||
ticker := time.NewTicker(w.interval)
|
||||
defer ticker.Stop()
|
||||
|
||||
for {
|
||||
select {
|
||||
case <-ticker.C:
|
||||
for range ticker.C {
|
||||
w.reload()
|
||||
}
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
// reload reads the whitelist file and updates the in-memory store.
|
||||
//
|
||||
// We only reload if the file has changed (mtime). This prevents
|
||||
// unnecessary reloads when the file is touched frequently.
|
||||
func (w *watcher) reload() {
|
||||
info, err := os.Stat(w.path)
|
||||
if err != nil {
|
||||
// File doesn't exist yet — skip.
|
||||
return
|
||||
}
|
||||
|
||||
// Only reload if the file has changed.
|
||||
if info.ModTime().Equal(w.lastMod) {
|
||||
return
|
||||
}
|
||||
w.lastMod = info.ModTime()
|
||||
|
||||
// Read and parse the file.
|
||||
entries := make(map[string]struct{})
|
||||
f, err := os.Open(w.path)
|
||||
if err != nil {
|
||||
log.Printf("failed to open whitelist file: %v", err)
|
||||
slog.Error("failed to open whitelist file", "error", err)
|
||||
return
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
scanner := bufio.NewScanner(f)
|
||||
for scanner.Scan() {
|
||||
line := scanner.Text()
|
||||
@@ -99,11 +58,8 @@ func (w *watcher) reload() {
|
||||
}
|
||||
entries[line] = struct{}{}
|
||||
}
|
||||
|
||||
// Update the store.
|
||||
w.store.mu.Lock()
|
||||
w.store.entries = entries
|
||||
w.store.mu.Unlock()
|
||||
|
||||
log.Printf("loaded %d entries from %s", len(entries), w.path)
|
||||
slog.Info("reloaded permanent whitelist", "count", len(entries))
|
||||
}
|
||||
Reference in New Issue
Block a user