Repository navigation
Conversation
The tracked go.mod snapshot and the Go caller source cache treated a file as unchanged when its size and mtime matched. A same-size edit within one clock tick, such as renaming a module to a path of equal length and back on Windows, kept the old module path or the old caller facts. The go.mod stamp now carries a content hash, and a missing go.mod is a valid absent state. Other stat or read errors no longer compare equal. The one-second check throttle is unchanged. Caller recovery always reads the file and reuses cached facts only for an equal digest, so unchanged files are still not parsed again. The stamp invalidation calls on the save paths are removed, since the digest check now covers them. Tests hold size and mtime equal with os.Chtimes for a module rename and rename back and for a caller edit on the in-memory and SQLite stores, and cover failed reads and snapshot reuse with Go and non-Go roots.
Reading and hashing every queued Go caller on each provider save made unchanged callers cost one read each. The caller cache now keeps size, mtime and the wall time taken before its read. It trusts equal stats without a read only when the file's mtime is older than that time minus a two-second window (Git's racy-file rule; FAT timestamps can cover two seconds). Recent stats, such as a same-size edit in one clock tick, still verify the digest. Known saves clear the trust again, so an editor that restores an old mtime after a save is verified. Limit, as in Git: an unobserved same-size edit that restores an mtime older than the window is trusted until the next save of that file.
The snapshot hashed one read of each root's go.mod, and the module path and replacements came from two later reads. An edit between those reads could pair the hash of one version with the parse of another, and later checks would keep the stale identity. Each check now reads every root's go.mod once and takes the hash, module path and replacements from those bytes. A missing go.mod is still a valid absent state, and a failed read still blocks reuse. Untrack now asks whether go.mod was present instead of whether a stored mtime was set.
Caller recovery stat'ed the file, and shared parse admission stat'ed it again. Recovery now passes the size it already has to admission, and skips an oversized caller before admission and before the read. The check after the read for a file that grew stays as it was.
TestGoModuleSourceCacheVerifiesTouchedContent registered its extraction spy after the touched-mtime save, so that save's "never re-parsed" claim was not checked, and its message still described the removed stamp refresh. The spy now starts before the first save. The test checks one read and zero parses for the touched save, then no read once the stat is outside the racy window.
The snapshot now takes module paths from goModuleIdentities, so readGoModModule had no production caller and repeated its parse. Its test now checks goModuleIdentities on the same go.mod inputs.
Three tests set a caller's mtime from the wall clock and expected the recovery that follows to stay inside the two-second racy window. On a slow or loaded runner, setup could take longer, and the recovery would trust the stat and skip the read the test depends on. The time a verifying read is recorded now comes from goModuleSourceNow, which these tests pin to the caller's fixed mtime (or an hour after it for the old-stat case), so each case takes one branch of the rule.
Caller recovery reads and hashes a file without the cache lock, then stores the result with a fresh trusted stamp. Repository lanes can run a provider-lane recovery while the caller's own repository saves that file. If the save kept the size and an old mtime, the stored pre-save digest was then trusted by stat, and later recoveries reused stale calls until the caller was saved again. Each known save now bumps a per-indexer epoch under the cache lock. Recovery reads the epoch with the entry and, when it stores its result, keeps the facts but drops the stat trust if the epoch moved. The next recovery then verifies the bytes. A test runs a save during the read and checks that the next recovery reads again and the one after does not.
|
Important Review skippedAuto reviews are limited based on label configuration. 🏷️ Required labels (at least one): 1
Please check the settings in the CodeRabbit UI or the
|
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.
Fork-only draft to run CI for fix/go-module-content-stamp at 784e922 (zzet#953 follow-up: compare go.mod and Go caller contents before cache reuse, with a Git-style racy-stat rule). Upstream zzet#980 test layout; no fork-only commit. Do not merge.