Fix bugs: corrupt entry telemetry, negative TTL docstring, RuntimeError crash, etc - #26
emiliano-go wants to merge 1 commit into
Conversation
5133e39 to
454a3ab
Compare
454a3ab to
a6e51af
Compare
More Bug FixesBug: Timedelta TTL sub-second precision lossProblem: Fix: Files: Bug: Warning for default TTL=0 (unbounded growth)Problem: Fix: Files: Bug: Missing reset_settings() for testingProblem: Fix: Files: Bug: cache_evict() with no args wipes ALL keysProblem: Fix: Files: Bug: Thundering herd / cache stampede protectionProblem: Fix: Files: Bug: Swallowed telemetry exceptions at DEBUG levelProblem: Fix: Files: |
|
I don't know how strict you guys are with AI usage, but PR messages were written partially by AI as English is not my native language, and some of the bugs were found with AI. |
Hey @emiliano-go , no problem, the descriptions are short and concise enough, which is important. AI usage is encouraged, when used in a sustainable way. I only have a problem with the amount of issues that are in the same PR - it is hard to comment on them when they are all grouped together; and it is harder to review. On the other side having one PR per issue is also a bit wasteful. Can we perhaps split them up to - let's say - no more than 3 separate issues per PR? |
|
Sure, willco! I'll leave it ready in 20ish min |
|
Per your feedback, the original set of changes has been split into 4 focused PRs:
|
|
Awesome! Can we close this PR? I think all the issues from it are already part of other PRs? |
Yes, everything as been moved. |
|
Thanks! |
Bug: Corrupt cache entry records double telemetry (hit + miss)
File: src/redis_fastapi/cache.py:401-418
When a cached entry contained corrupt JSON, the code path emitted two record_cache_request metrics, first "hit" then "miss", for a single request. The cache.hit span attribute was also set to True and then overwritten to False.
Root cause: record_cache_request(result="hit") and span.set_attribute("cache.hit", True) were called before attempting to deserialize the cached entry. When deserialization failed (caught json.JSONDecodeError/KeyError), execution fell through to the MISS path, which recorded a second metric and flipped the span attribute.
Fix: Moved response deserialization before telemetry emission. If deserialization fails, only "miss" is recorded. If it succeeds, "hit" is recorded and CacheHitException is raised. the MISS path is never reached.
Bug: Negative TTL docstring promises ValueError that never fires
File: src/redis_fastapi/cache_backend.py:190-191
The docstring for CacheBackend.set() stated "Raises ValueError: If ttl is negative", but the code silently treated negative TTLs as "no expiry" (identical to ttl=0 or ttl=None):
Fix: Updated the docstring to accurately reflect the actual behavior: "None or a value of 0 or below means the key will not be automatically expired."
Bug: _store_cache_entry crashes with unhandled RuntimeError (500)
File: src/redis_fastapi/cache.py:683-703
When pending.redis is None, _store_cache_entry falls back to _get_pool_state(app).get_async_client(). If no lifespan has been registered, this raises RuntimeError. The surrounding exception handler only caught (RedisError, OSError), so the RuntimeError propagated unhandled, crashing the response with a 500 error.
Fix: Added RuntimeError to the caught exception types. The error is now logged as a warning and the response is delivered without caching, matching the graceful degradation behavior of the other Redis error paths.
Additional changes