Skip to content

refactor(cache): build the key only where the backend is used; report media_type - #276

Merged
allen0099 merged 1 commit into
masterfrom
refactor/http-cache-internals-182-184
Sep 27, 2026
Merged

allen0099 merged 1 commit into
masterfrom
refactor/http-cache-internals-182-184

Conversation

@allen0099

@allen0099 allen0099 commented Sep 26, 2026 •

Copy link
Copy Markdown
Owner

Summary

Closes #182
Closes #184

Both are part of #121.

#182: @cache wrapper

  • The cache key is now built right before the backend read. The no-store branch and the backend-bypass branch (private, no ttl, ttl=0) never touch the backend, so they used the key only in debug logs, and a custom key_builder ran for nothing there. Those logs now show the request path.
  • if not req (which relies on Request.__len__) becomes if req is None.
  • The build_cache_control closure is now a module-level _build_cache_control(...) with keyword-only arguments and the same output. It is still built once per decorated route.

No behaviour change apart from when key_builder is called. It still runs exactly once per GET that reads the backend: miss, hit and 304 alike.

#184: monitoring routes

  • /cached-records gains a media_type field with the stored CacheEntry.media_type, or null when there is none. content_type stays and is always "bytes" for compatibility.
  • CACHE_KEY_MAX_PARTS is a maxsplit count, so it is renamed CACHE_KEY_MAX_SPLIT. The old name remains as an alias.
  • HTTP_CACHING.md (EN and zh-TW) documents media_type and points readers away from content_type.

Tests

  • New file tests/test_cache_internals.py:
    • key_builder is not called for no_store, private, no ttl, ttl=0 (including a revalidating request) or non-GET;
    • it is called exactly once per request on a cached route (miss, hit, 304);
    • _build_cache_control covers the directive order, stale-if-error and no-cache dropping the rest.
  • tests/test_routes.py: media_type for JSON and text/plain entries, null for an entry without one, and the constant alias.
  • Mutation-checked each change against the full suite:
    • building the key before no_store fails only the new key-builder tests;
    • reporting media_type=None fails only the new media-type test;
    • dropping must-revalidate under no-cache fails the new _build_cache_control case plus the existing test_no_cache_with_revalidate.
  • uv run pytest passed without live servers: 813 passed and 190 skipped, where the skips are the Redis/Memcached tests. Coverage is 93.03%, with cache.py and routes.py at 100%.
  • pre-commit passed on all files, and both strict docs builds (EN and zh-TW) passed.

CHANGELOG

Added

  • /cached-records reports each entry's media_type. It is the media type the response was stored with, or null when it had none. content_type is still returned for compatibility but is always "bytes". CACHE_KEY_MAX_PARTS in fastapi_cachex.routes is renamed CACHE_KEY_MAX_SPLIT, since it is a maxsplit count; the old name remains as an alias. (#184)

Changed

  • @cache builds the cache key only when it reads or writes the backend. A custom key_builder is no longer called for no_store, private or TTL-less routes, where the key only fed debug logs. (#182)

… media_type

@cache built the cache key before the no-store and backend-bypass branches,
where it only fed debug logs, so a custom key_builder ran for nothing on
those routes. Build it right before the backend read, log the path in the
bypass branches, test the request with 'is None' instead of Request.__len__,
and move the Cache-Control closure to a module-level _build_cache_control.

/cached-records now reports each entry's stored media_type; content_type
stays "bytes" for compatibility. CACHE_KEY_MAX_PARTS is renamed to
CACHE_KEY_MAX_SPLIT, since it is a maxsplit count, with the old name kept
as an alias.

Closes #182
Closes #184
@allen0099 allen0099 added this to the 0.3.8 milestone Sep 26, 2026
@allen0099 allen0099 added enhancement New feature or request http-cache The @cache decorator, cache keys and Cache-Control handling labels Sep 26, 2026
@allen0099
allen0099 merged commit a02530b into master Sep 27, 2026
11 checks passed
@allen0099
allen0099 deleted the refactor/http-cache-internals-182-184 branch September 27, 2026 09:56
allen0099 added a commit that referenced this pull request Sep 27, 2026
Copies the CHANGELOG sections of #207, #208, #209, #211, #212, #272,
#273, #274, #275, #276, #279 and #284 into Unreleased. The #273 entry
drops expire_if_equals from its list of methods that changed, since that
primitive is new in 0.3.8.
allen0099 added a commit that referenced this pull request Sep 27, 2026
Copies the CHANGELOG sections of #207, #208, #209, #211, #212, #272,
#273, #274, #275, #276, #279 and #284 into Unreleased. The #273 entry
drops expire_if_equals from its list of methods that changed, since that
primitive is new in 0.3.8.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request http-cache The @cache decorator, cache keys and Cache-Control handling

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Monitoring routes: report media_type and rename the key-split constants @cache wrapper: build the key lazily and tidy the request check

1 participant