mirror of
https://github.com/lukaszraczylo/traefik-llmgateway.git
synced 2026-10-18 05:47:38 +00:00
fix(auth): non-blocking reload check, stat-before-load, mtime inequality trigger
- users_file.go: maybeReload uses reloadMu.TryLock() instead of Lock(). A full reload (stat+read+parse+replaceFileUsers, incl. per-user resolveSecret file reads) could otherwise block every concurrent ServeHTTP request for its whole duration, negating the buildMu/mu lock split. A request that finds a reload in flight now skips this cycle; reload stays throttled and best-effort. - users_file.go: mtime check changed from ModTime().After(lastModTime) to ModTime().Equal(lastModTime), so a backward mtime move (restore from backup, cp -p) still triggers a reload instead of being skipped. Added a regression test with os.Chtimes into the past. - llmgateway.go: attachUsersFile now stats the file before loading it, matching maybeReload's ordering, so a write landing between stat and load is caught on the next check instead of being lost. Documented why the ignored statErr is safe (falls back to zero lastModTime, causing one harmless extra reload).
This commit is contained in:
+13
-1
@@ -143,6 +143,18 @@ func newGateway(ctx context.Context, next http.Handler, config *Config, name str
|
||||
// constructor error — fail fast on bad config rather than start with an
|
||||
// empty file-sourced user set.
|
||||
func attachUsersFile(auth *authStore, path string, log gatewayLogger) error {
|
||||
// Stat before load, matching maybeReload's ordering: capturing the mtime
|
||||
// before reading content means a write landing between the stat and the
|
||||
// read still shows up as a further mtime change on the first post-
|
||||
// startup reload check, instead of being silently lost forever — a
|
||||
// stat-after-load can observe a newer mtime for content it never read.
|
||||
//
|
||||
// statErr is intentionally ignored here: if the stat fails, lastModTime
|
||||
// stays at its zero value, so the first maybeReload call sees any real
|
||||
// mtime as "changed" and reloads once more — a harmless extra reload of
|
||||
// content already loaded, not a correctness problem.
|
||||
info, statErr := os.Stat(path)
|
||||
|
||||
uf := newUsersFile(path)
|
||||
initial, err := uf.load()
|
||||
if err != nil {
|
||||
@@ -154,7 +166,7 @@ func attachUsersFile(auth *authStore, path string, log gatewayLogger) error {
|
||||
|
||||
auth.usersFile = uf
|
||||
auth.log = log
|
||||
if info, statErr := os.Stat(path); statErr == nil {
|
||||
if statErr == nil {
|
||||
auth.lastModTime = info.ModTime()
|
||||
}
|
||||
auth.lastCheck = auth.nowFn()
|
||||
|
||||
Reference in New Issue
Block a user