fix(cache): preserve on_release behavior in TTLCleanupCache.clear()#14180
Conversation
✅ PR preview is ready!
|
This stack of pull requests is managed by Graphite. Learn more about stacking. |
✅ Snyk checks have passed. No issues have been found so far.
💻 Catch issues earlier using the plugins for VS Code, JetBrains IDEs, Visual Studio, and Eclipse. |
There was a problem hiding this comment.
Pull request overview
This PR restores resource cleanup semantics for Streamlit’s TTL-based cache by ensuring TTLCleanupCache.clear() triggers on_release for each entry even after cachetools changed TTLCache.clear() internals.
Changes:
- Override
TTLCleanupCache.clear()to evict entries viapopitem()so per-entry release hooks run. - Update
cache_resource_apiinline comments to clarify exception and cleanup behavior during cache clearing.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
lib/streamlit/runtime/caching/ttl_cleanup_cache.py |
Adds a clear() override to preserve per-entry on_release behavior across cachetools versions. |
lib/streamlit/runtime/caching/cache_resource_api.py |
Refines comments explaining why cache entries are cleared individually and how callback exceptions are handled/logged. |
SummaryThis PR fixes a regression introduced by The fix adds a Code QualityThe implementation is clean, minimal, and well-documented:
One subtle edge case worth noting: if a user-provided Test CoverageTest coverage is adequate:
The PR description says "Covered by existing tests," which is accurate. The existing tests already validate the expected behavior; the fix ensures they continue to pass with cachetools 7.0.2+. Backwards CompatibilityNo breaking changes. The fix is purely defensive:
Security & RiskNo security concerns. The change is limited to internal cache cleanup logic with no impact on authentication, networking, or data handling. The regression risk is very low given the existing test coverage. External test recommendation
AccessibilityNo frontend changes; accessibility is not applicable. RecommendationsNo blocking issues. One optional suggestion:
VerdictAPPROVED: Clean, minimal fix that correctly preserves This is an automated AI review by |
ea9d58f to
9c54abb
Compare
|
The AI review job failed to complete. Please check the workflow run for details. You can retry by adding the 'ai-review' label again or manually triggering the workflow. |
1 similar comment
|
The AI review job failed to complete. Please check the workflow run for details. You can retry by adding the 'ai-review' label again or manually triggering the workflow. |
|
|
||
| # Invoke on_release outside the try/except so callback exceptions, | ||
| # including KeyError, propagate to the caller. | ||
| self._on_release(value) |
There was a problem hiding this comment.
question: An exception in _on_release would break the clear loop. Is that a problem or different to the current behaviour?
There was a problem hiding this comment.
Thanks for this comment. Technically what was written before was 99% the same, but changed up a rough edge in the existing implementation. In order to keep this narrowly scoped, I ended up switching this to a simpler implementation. This one exactly matches the behavior seen in <= 7.0.1 in an effort to reduce any potential differences across versions, rather than attempting to fix some long-standing behavior.
lukasmasuch
left a comment
There was a problem hiding this comment.
LGTM 👍 One potential issue to double check
cachetools 7.0.2 changed TTLCache.clear() to an O(1) implementation that bypasses popitem()/expire(). That skipped TTLCleanupCache release hooks and broke resource cleanup paths that expect on_release to run for each entry. Override TTLCleanupCache.clear() to evict entries via popitem(), preserving release semantics across cachetools versions.
9c54abb to
632a037
Compare
|
I'm going to merge this to get the CI unblocked |
…14180) ## Describe your changes cachetools 7.0.2 changed TTLCache.clear() to an O(1) implementation that bypasses `popitem()`/`expire()`. That skipped `TTLCleanupCache` release hooks and broke resource cleanup paths that expect on_release to run for each entry. Override `TTLCleanupCache.clear()` to evict entries via `popitem()`, preserving release semantics across `cachetools` versions. Update related inline comments in `cache_resource_api` to document the callback/exception behavior and why per-item cleanup is still used. ## Screenshot or video (only for visual changes) ## GitHub Issue Link (if applicable) ## Testing Plan - [x] Covered by existing tests --- **Contribution License Agreement** By submitting this pull request you agree that all contributions to this project are made under the Apache 2.0 license.

Describe your changes
cachetools 7.0.2 changed TTLCache.clear() to an O(1) implementation that bypasses
popitem()/expire(). That skippedTTLCleanupCacherelease hooks and broke resource cleanup paths that expect on_release to run for each entry.Override
TTLCleanupCache.clear()to evict entries viapopitem(), preserving release semantics acrosscachetoolsversions. Update related inline comments incache_resource_apito document the callback/exception behavior and why per-item cleanup is still used.Screenshot or video (only for visual changes)
GitHub Issue Link (if applicable)
Testing Plan
Contribution License Agreement
By submitting this pull request you agree that all contributions to this project are made under the Apache 2.0 license.