{{ message }}
Repository navigation
Conversation
ellemedit
force-pushed
the
fix/ttl-gc-retain-20260907
branch
from
September 23, 2026 05:34
dee9372 to
303e99c
Compare
This branch has not been deployed
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.

With
shouldRetainWithinTTL_EXPERIMENTALenabled, an incremental GC pass can sweep an operation's records after the operation has been retained again.A screen can retain a query for use again, yet a previously complete read can become
isMissingDatasolely because of GC scheduling. Losing records while the caller correctly holds a retain can force the application to recover data it already had. This fix includes operations retained again while GC was yielding in the set of records to preserve, preventing their collection despite an active retain.Keeping data in memory and treating it as fresh are separate decisions. The change preserves the existing stale status so required revalidation is not skipped, while still allowing memory to be reclaimed after the final retain is released.
The failing sequence is:
retain(A)increments the existing root entry without a store write.Reinsert the existing root entry when its reference count changes from zero during an active TTL GC pass. The live Map iterator then visits it again before sweeping. Reusing the entry preserves its fetch time and invalidation epoch, and retention does not advance the store's write epoch.
The seven regression tests use public retain/dispose calls and a controllable GC scheduler. They cover both a zero-sized release buffer and actual eviction from the default ten-entry buffer, stale disposal that bypasses the buffer, TTL and release-buffer controls, freshness preservation, and collection after the final release.
Validation:
52c26aed65a496182f2fa978f9911db5be4f652dwith the new tests: four regressions fail and three controls pass.RelayModernStoretests pass: 331 tests across two suites.flow full-check --max-workers 2 --show-all-errors: zero errors.This change preserves the existing root-metadata cleanup policy; that policy can be reviewed separately from the retained-data race.