feat(cache): add build_cache_key() for custom key builders - #307
Merged
Merged
Conversation
build_cache_key(request, *components) returns the default key unchanged and appends each str/int component, escaped with escape_key_component, after the query string. clear_path() on the memory and Redis backends matches such keys by their path and no longer counts the extra components as a query string; the monitoring routes report them in extra_components. The per-user example in HTTP_CACHING.md now uses it.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds
build_cache_key(request, *components)(exported fromfastapi_cachex) so a customkey_buildercan add a dimension (user ID, tenant, locale) without rebuildingmethod|||host|||path|||queryby hand.default_key_builderstays public and returnsbuild_cache_key(request).str | int. Anintis written in decimal (1and"1"are the same component). Anything else, includingNoneandbool, raisesTypeError, so a missing user ID cannot silently put every such caller under a"None"key. An empty string is a component of its own.escape_key_component, so"a|||b"cannot line up with the components"a", "b".clear_path: extra components follow the query string. Memory's key splitter used to split at most three times, soGET|||h|||/me||||||usercounted as "has query params" andclear_path("/me")missed it; it now looks at the query component only. Redis now SCANs*|||path|||*and checks each returned key's third component and query in Python (a glob cannot tell an empty query followed by extras from a query). Side effect: a key where the path only appears as the host or an extra component is no longer cleared. Memcached is unchanged (exact-key only). A contract test runs on memory and live Redis./cached-hitsand/cached-recordsrecords get a newextra_componentslist (decoded);query_paramsnow holds only the query string._parse_cache_keykeeps its 4-tuple shape.build_cache_key, CACHE_FLOW.md points to it, API reference lists it; zh-TW mirrors updated.Changelog
changelog.d/264.added.mdTest plan
uv run ruff check fastapi_cachex tests && uv run ruff format --check fastapi_cachex tests && uv run mypy fastapi_cachex --strictuv run pytest(no live servers): 957 passed, 192 skipped, coverage 94%Closes #264