From dded3a56fe1df462046011fa38a5bbc6aa8f09c9 Mon Sep 17 00:00:00 2001 From: Lukasz Raczylo Date: Fri, 21 Aug 2026 11:49:51 +0100 Subject: [PATCH] test(integration): widen TestUsersFileHotReload deadline for VirtioFS lag Docker Desktop VirtioFS propagation of a host write to the guest's view of the bind-mounted users.json is not bounded by the plugin's own 5s reload throttle. Direct measurement (host write + polled guest-side read, independent of the plugin) showed convergence times from under 1s up to 18s, and a captured real test run took ~26s end to end, exceeding the prior 20s deadline. Raise it to 60s, more than 2x the worst value observed, and document the measurement so a future investigator does not have to re-derive it. users_file.go was verified correct for this failure class: it re-opens and re-reads the users file by path on every reload cycle, never caches by file descriptor or inode, which is also the correct pattern for a Kubernetes ConfigMap/Secret atomic symlink-swap update. No production code changed. --- integration/integration_test.go | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/integration/integration_test.go b/integration/integration_test.go index 8c73ef1..33f0005 100644 --- a/integration/integration_test.go +++ b/integration/integration_test.go @@ -583,20 +583,36 @@ func TestUsersFileHotReload(t *testing.T) { t.Fatalf("write users.json: %v", err) } - // 20s, not the plugin's 5s reload throttle alone: this is a real docker - // compose stack, not an in-process unit test, and needs margin for - // bind-mount propagation latency and scheduler jitter on a loaded host. - deadline := time.Now().Add(20 * time.Second) + // 60s, not the plugin's 5s reload throttle alone: this is a real docker + // compose stack, not an in-process unit test. On Docker Desktop for + // macOS, VirtioFS's host-write-to-guest-read propagation for a + // bind-mounted file is NOT bounded by the plugin's own reload logic — + // direct measurement (writing users.json on the host and polling the + // container's view of it via `docker compose exec`, independent of this + // plugin entirely) showed convergence times from under 1s up to ~18s, + // and one captured real run of this test took ~26s end to end (traefik1 + // logged repeated "unexpected end of JSON input" reload errors — a torn + // read of an in-flight VirtioFS content update — every ~5s until the + // guest's view finally caught up). That is a VirtioFS-level cache + // staleness/coherency artifact of this host/mount combination, not a + // plugin bug: users_file.go already re-opens and re-reads the file by + // path on every reload (see its own comment), which is the correct, + // production-safe pattern for a Kubernetes ConfigMap/Secret atomic + // symlink-swap update too. 60s gives >2x margin over the worst + // convergence time observed so far. + start := time.Now() + deadline := start.Add(60 * time.Second) var lastStatus int for time.Now().Before(deadline) { resp, _ := doJSON(t, http.MethodGet, traefik1URL+"/v1/models", carolKey, nil) lastStatus = resp.StatusCode if resp.StatusCode == http.StatusOK { + t.Logf("carol's key became valid %s after users.json changed", time.Since(start)) return } time.Sleep(time.Second) } - t.Fatalf("carol's key did not become valid within 20s of users.json changing (last status=%d)", lastStatus) + t.Fatalf("carol's key did not become valid within 60s of users.json changing (last status=%d)", lastStatus) } // TestPassthroughAndMCPStream covers integration test 6: native passthrough