test(cmd/grafel): strictly advance cpu.json mtime in writeCPUJSON (Windows caps-store flake)#5897
Merged
Merged
Conversation
…ndows de-flake)
TestApplyDaemonGOMAXPROCSFromCaps flaked on windows-latest only, failing
step 3 with (n=2, changed=false) instead of (5, ..., true): the caps.Store
served the STALE cached parse of the first cpu.json write.
Root cause is a test artifact, not a product bug. The store caches the
parsed cpu.json keyed on its (mtime,size) -- a deliberate, documented
stat-only hot-path optimisation. The two payloads written back-to-back
({"daemon_gomaxprocs": 2} vs 5) are byte-identical in size, so mtime is
the sole cache discriminator. writeCPUJSON stamped BOTH writes with
time.Now().Add(2s); on Windows the wall clock is coarse (~15ms) so two
rapid writes read the same time.Now(), the constant offset cancels, both
files land on the same mtime, and the (mtime,size) key never changes ->
stale cache hit. Unix has finer mtime resolution, hence Unix-green /
Windows-flaky.
Fix is in the TEST (smallest deterministic change; keeps the store's
stat-only hot path intact -- a content-hash key would force a ReadFile on
every Load, regressing exactly what the package optimises for; in prod
operator edits are seconds-to-minutes apart on sub-second-resolution
filesystems, so the collision never occurs). writeCPUJSON now anchors the
new mtime to the previous file's mtime + 2s (falling back to now for the
first write), making each successive write strictly newer regardless of
clock resolution, so the cache key always advances.
Sibling caps tests (caps_test.go TestLoad_ReReadOnChange /
TestLoad_MalformedKeepsLastGood) are already safe: they Chtimes only the
SECOND write, so the +2s offset creates a guaranteed gap from the first
write's natural OS-timestamp mtime.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017quGgaqK7NRoxGT6BTqV2o
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes the sole windows-latest failure in v0.1.9 acceptance CI #2:
TestApplyDaemonGOMAXPROCSFromCaps→raise: got (n=2, prev=2, changed=false), want (5, 2, true). Pre-existing Windows flake, unrelated to the memory epic (this test passed on the prior CI run that already contained every epic change). Refs #5850.Root cause (test artifact, not product):
caps.Store.Load()caches the parsedcpu.jsonon a(mtime, size)key — a deliberate stat-only hot-path optimization (avoids re-parsing JSON on the reindex hot path). The test'swriteCPUJSONstamped both back-to-back writes with the samenow+2s, and the two step-3 payloads ({"daemon_gomaxprocs": 2}/5) are byte-identical in size, sosizecan't discriminate and mtime is the sole key. On Windows's coarse (~15ms) wall clock the two rapid writes get the identical mtime, the key never advances, andLoad()returns the stale parse (2). Unix's finer mtime distinguishes them → Unix-green, Windows-flaky.Fix:
writeCPUJSONanchors the new mtime tomax(now, prevFileMtime + 2s)(stat-before-overwrite), so each successive write is strictly newer regardless of clock resolution and the(mtime, size)key always advances. Deterministic on all platforms; macOS stays green. Store left unchanged — hardening it to a content-hash key would force aReadFileon everyLoad(), regressing exactly the stat-only cheapness it was built for, for a same-mtime-same-size collision that can't occur with real seconds-apart operator edits.Class scan: the sibling caps tests (
caps_test.go) already Chtimes only the second write, so they're safe;writeCPUJSONwas the sole symmetric-offset instance.🤖 Generated with Claude Code
https://claude.ai/code/session_017quGgaqK7NRoxGT6BTqV2o