Remove unused ETag from invalidation tags to prevent non-volatile tag Set leak#180
Conversation
|
Warning Review limit reached
Next review available in: 45 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (1)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## 1.x #180 +/- ##
===========================================
Coverage 100.00% 100.00%
Complexity 247 247
===========================================
Files 53 53
Lines 749 748 -1
===========================================
- Hits 749 748 -1 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
…o-driver failure)
57622de to
e24c321
Compare
|
@coderabbitai review |
✅ Action performedReview finished.
|
Mirror of #180 (released in 1.16.2) for this branch: CacheTags::ofResource() — the extracted form of ResourceStorage::getTags() — still registered the ETag as an invalidation tag. The ETag is never invalidated by (all invalidation is by URI tag / surrogate keys; HTTP 304 uses the separate ETag pool), and being content-versioned it leaks one non-volatile tag Set per content version under a volatile-* eviction policy. Drop the ETag from the resource-state tags; add testEtagIsNotRegisteredAsInvalidationTag (invalidating by the ETag value must not purge the entry; the URI tag still does). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SJnuk1B1yXK6bxXuU9DGCo
Problem
ResourceStorage::getTags()registers the ETag as an invalidation tag for every resource-state (roPool) save:However, no code path ever invalidates by ETag. All invalidation goes through the URI tag (
deleteEtag()→invalidateTags([$uriTag])) or surrogate keys. HTTP 304 validation uses the separateetagPool(keyed by the ETag, not tagged by it), so it is unaffected.Because the ETag is content-versioned (
crc32of the view), each content version creates a new, non-volatile tag Set (\0tags\0{etag}). Under avolatile-*eviction policy (required byRedisTagAwareAdapter), these Sets are never reclaimed and never read — a write-only memory leak that grows monotonically.Production evidence
Measured on a production ElastiCache instance (full keyspace scan, read-only):
The ETag Sets accounted for 61% of all tag Sets and were growing ~1.9k/hour, steadily consuming non-volatile memory that
volatile-lrucannot evict.Fix
Stop registering the ETag as an invalidation tag. The cache entry remains fully purgeable via its URI tag and surrogate keys, and HTTP 304 handling (the
etagPool) is untouched.Test
Adds
testEtagIsNotRegisteredAsInvalidationTag: aftersaveValue(), invalidating by the ETag value must not purge the entry, while invalidating by the URI tag still does. Verified this test fails before the change (Failed asserting that null is not null) and passes after.