fix: reject non-finite (NaN/inf) TTL to prevent immortal cache entries#174
fix: reject non-finite (NaN/inf) TTL to prevent immortal cache entries#17427Bslash6 wants to merge 2 commits into
Conversation
A NaN or inf TTL slipped past every TTL guard because all of them use a `<` comparison, and NaN/inf comparisons are False. The result was an entry whose expiry never triggers, serving stale data indefinitely (DATA IS SACRED). - config/decorator.py: DecoratorConfig validation now rejects a non-finite ttl up front (math.isfinite) with a clear error, before the existing < 0 check. - l1_cache.py: put() skips caching when the computed expiry is non-finite (in addition to the existing too-short-TTL guard), so no immortal L1 entry forms. - object_cache.py: put() rejects a non-finite ttl alongside the existing ttl < 1 check. Tests cover all three sites with NaN and inf. Fixes #158
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: ASSERTIVE Plan: Pro Run ID: 📒 Files selected for processing (3)
WalkthroughThis pull request adds non-finite TTL validation across three cache layers: DecoratorConfig, L1Cache, and ObjectCache. Each layer imports math and applies isfinite() checks to reject NaN and infinity at configuration, put operations, and expiry computation, preventing immortal cache entries. ChangesNon-finite TTL validation across cache layers
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@tests/unit/config/test_decorator_config.py`:
- Around line 97-101: The parameterized test test_non_finite_ttl_rejected
currently checks float("nan") and float("inf") but misses negative infinity;
update the param list for bad_ttl in that test (the DecoratorConfig(ttl=bad_ttl)
assertion) to include negative infinity (e.g., float("-inf") or -float("inf"))
so the test asserts both +inf and -inf are rejected as non-finite TTLs.
In `@tests/unit/test_l1_memory_bounds.py`:
- Around line 71-79: The parameterized tests
test_non_finite_redis_ttl_not_stored and test_non_finite_expires_at_not_stored
only cover float("nan") and float("inf"); update both
`@pytest.mark.parametrize`("bad_ttl", [...]) decorators to also include negative
infinity (e.g. float("-inf")) so the tests cover ±inf; locate the decorators
above the functions test_non_finite_redis_ttl_not_stored and
test_non_finite_expires_at_not_stored and add float("-inf") to the list of
bad_ttl cases.
In `@tests/unit/test_object_cache.py`:
- Around line 76-81: Update the parameterized inputs for
test_non_finite_ttl_raises so it includes negative infinity as well as NaN and
positive infinity: modify the `@pytest.mark.parametrize` call that sets "bad_ttl"
in function test_non_finite_ttl_raises to include float("-inf") along with
float("nan") and float("inf"), ensuring the test rejects NaN/±inf TTLs when
calling ObjectCache.put("k", "value", ttl=bad_ttl).
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
Run ID: a41184f3-9ddf-4cf7-8ed9-78b416948b96
📒 Files selected for processing (7)
.secrets.baselinesrc/cachekit/config/decorator.pysrc/cachekit/l1_cache.pysrc/cachekit/object_cache.pytests/unit/config/test_decorator_config.pytests/unit/test_l1_memory_bounds.pytests/unit/test_object_cache.py
Codecov Report❌ Patch coverage is
📢 Thoughts on this report? Let us know! |
Summary
Fixes #158. A
NaNorinfTTL slipped past every TTL guard because they all use a<comparison and IEEE-754 comparisons against NaN/inf areFalse. The result was a cache entry whose expiry never triggers — stale data served indefinitely (DATA IS SACRED).Changes
All three TTL guard sites now reject non-finite values:
config/decorator.py:DecoratorConfigvalidation rejects a non-finitettlup front viamath.isfinite, before the existing< 0check — so@cache(ttl=float("nan"))fails loud at decoration.l1_cache.py:put()skips caching when the computedexpiryis non-finite (alongside the existing too-short-TTL guard), so no immortal L1 entry can form from aNaN/infredis_ttlorexpires_at.object_cache.py:put()rejects a non-finitettlalongside the existingttl < 1check.Tests
Unit tests (run on PRs) cover all three sites with both
NaNandinf:test_decorator_config.py: non-finite ttl raises at validationtest_l1_memory_bounds.py: non-finiteredis_ttl/expires_atare not storedtest_object_cache.py: non-finite ttl raisesVerification
ruffclean,basedpyright0 errors, 52 unit tests pass across the three touched test files.Summary by CodeRabbit
Bug Fixes
Tests