fastapi-cachex 0.2.4__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (31) hide show
  1. fastapi_cachex-0.2.4/PKG-INFO +269 -0
  2. fastapi_cachex-0.2.4/README.md +233 -0
  3. fastapi_cachex-0.2.4/fastapi_cachex/__init__.py +27 -0
  4. fastapi_cachex-0.2.4/fastapi_cachex/backends/__init__.py +15 -0
  5. fastapi_cachex-0.2.4/fastapi_cachex/backends/base.py +70 -0
  6. fastapi_cachex-0.2.4/fastapi_cachex/backends/config.py +15 -0
  7. fastapi_cachex-0.2.4/fastapi_cachex/backends/memcached.py +258 -0
  8. fastapi_cachex-0.2.4/fastapi_cachex/backends/memory.py +226 -0
  9. fastapi_cachex-0.2.4/fastapi_cachex/backends/redis.py +347 -0
  10. fastapi_cachex-0.2.4/fastapi_cachex/cache.py +341 -0
  11. fastapi_cachex-0.2.4/fastapi_cachex/dependencies.py +16 -0
  12. fastapi_cachex-0.2.4/fastapi_cachex/directives.py +21 -0
  13. fastapi_cachex-0.2.4/fastapi_cachex/exceptions.py +17 -0
  14. fastapi_cachex-0.2.4/fastapi_cachex/proxy.py +43 -0
  15. fastapi_cachex-0.2.4/fastapi_cachex/py.typed +0 -0
  16. fastapi_cachex-0.2.4/fastapi_cachex/routes.py +312 -0
  17. fastapi_cachex-0.2.4/fastapi_cachex/session/__init__.py +23 -0
  18. fastapi_cachex-0.2.4/fastapi_cachex/session/config.py +93 -0
  19. fastapi_cachex-0.2.4/fastapi_cachex/session/dependencies.py +99 -0
  20. fastapi_cachex-0.2.4/fastapi_cachex/session/exceptions.py +25 -0
  21. fastapi_cachex-0.2.4/fastapi_cachex/session/manager.py +445 -0
  22. fastapi_cachex-0.2.4/fastapi_cachex/session/middleware.py +158 -0
  23. fastapi_cachex-0.2.4/fastapi_cachex/session/models.py +185 -0
  24. fastapi_cachex-0.2.4/fastapi_cachex/session/security.py +111 -0
  25. fastapi_cachex-0.2.4/fastapi_cachex/session/token_serializers.py +166 -0
  26. fastapi_cachex-0.2.4/fastapi_cachex/state/__init__.py +8 -0
  27. fastapi_cachex-0.2.4/fastapi_cachex/state/exceptions.py +19 -0
  28. fastapi_cachex-0.2.4/fastapi_cachex/state/manager.py +258 -0
  29. fastapi_cachex-0.2.4/fastapi_cachex/state/models.py +31 -0
  30. fastapi_cachex-0.2.4/fastapi_cachex/types.py +34 -0
  31. fastapi_cachex-0.2.4/pyproject.toml +173 -0
@@ -0,0 +1,269 @@
1
+ Metadata-Version: 2.4
2
+ Name: fastapi-cachex
3
+ Version: 0.2.4
4
+ Summary: A caching library for FastAPI with support for Cache-Control, ETag, and multiple backends.
5
+ Keywords: fastapi,cache,etag,cache-control,redis,memcached,in-memory
6
+ Author: allen0099
7
+ Author-email: allen0099 <s96016641@gmail.com>
8
+ License-Expression: Apache-2.0
9
+ Classifier: Development Status :: 3 - Alpha
10
+ Classifier: Intended Audience :: Developers
11
+ Classifier: Programming Language :: Python
12
+ Classifier: Programming Language :: Python :: 3
13
+ Classifier: Programming Language :: Python :: 3.10
14
+ Classifier: Programming Language :: Python :: 3.11
15
+ Classifier: Programming Language :: Python :: 3.12
16
+ Classifier: Programming Language :: Python :: 3.13
17
+ Classifier: Programming Language :: Python :: 3.14
18
+ Classifier: Programming Language :: Python :: 3 :: Only
19
+ Classifier: Framework :: FastAPI
20
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
21
+ Classifier: Topic :: Internet :: WWW/HTTP :: HTTP Servers
22
+ Requires-Dist: fastapi
23
+ Requires-Dist: pydantic
24
+ Requires-Dist: pyjwt>=2.9.0 ; extra == 'jwt'
25
+ Requires-Dist: pymemcache ; extra == 'memcache'
26
+ Requires-Dist: redis[hiredis] ; extra == 'redis'
27
+ Requires-Dist: orjson ; extra == 'redis'
28
+ Requires-Python: >=3.10
29
+ Project-URL: Homepage, https://github.com/allen0099/FastAPI-CacheX
30
+ Project-URL: Issues, https://github.com/allen0099/FastAPI-CacheX/issues
31
+ Project-URL: Repository, https://github.com/allen0099/FastAPI-CacheX.git
32
+ Provides-Extra: jwt
33
+ Provides-Extra: memcache
34
+ Provides-Extra: redis
35
+ Description-Content-Type: text/markdown
36
+
37
+ # FastAPI-Cache X
38
+
39
+ [![uv](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/uv/main/assets/badge/v0.json)](https://github.com/astral-sh/uv)
40
+ [![Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json)](https://github.com/astral-sh/ruff)
41
+ [![Tests](https://github.com/allen0099/FastAPI-CacheX/actions/workflows/test.yml/badge.svg)](https://github.com/allen0099/FastAPI-CacheX/actions/workflows/test.yml)
42
+ [![Coverage Status](https://raw.githubusercontent.com/allen0099/FastAPI-CacheX/coverage-badge/coverage.svg)](https://github.com/allen0099/FastAPI-CacheX/actions/workflows/coverage.yml)
43
+
44
+ [![Downloads](https://static.pepy.tech/badge/fastapi-cachex)](https://pepy.tech/project/fastapi-cachex)
45
+ [![Weekly downloads](https://static.pepy.tech/badge/fastapi-cachex/week)](https://pepy.tech/project/fastapi-cachex)
46
+ [![Monthly downloads](https://static.pepy.tech/badge/fastapi-cachex/month)](https://pepy.tech/project/fastapi-cachex)
47
+
48
+ [![PyPI version](https://img.shields.io/pypi/v/fastapi-cachex.svg?logo=pypi&logoColor=gold&label=PyPI)](https://pypi.org/project/fastapi-cachex)
49
+ [![Python Versions](https://img.shields.io/pypi/pyversions/fastapi-cachex.svg?logo=python&label=Python&logoColor=gold)](https://pypi.org/project/fastapi-cachex/)
50
+
51
+ [English](README.md) | [繁體中文](docs/README.zh-TW.md)
52
+
53
+ A high-performance caching extension for FastAPI, providing comprehensive HTTP caching support and optional session management.
54
+
55
+ ## Features
56
+
57
+ ### HTTP Caching
58
+ - Support for HTTP caching headers
59
+ - `Cache-Control`
60
+ - `ETag`
61
+ - `If-None-Match`
62
+ - Multiple backend cache support
63
+ - Redis
64
+ - Memcached
65
+ - In-memory cache
66
+ - Complete Cache-Control directive implementation
67
+ - Easy-to-use `@cache` decorator
68
+
69
+ ### Session Management (Optional Extension)
70
+ - Secure session management with HMAC-SHA256 token signing
71
+ - Optional JWT token format for interoperability (install extra `jwt`)
72
+ - IP address and User-Agent binding (optional security features)
73
+ - Header and bearer token support (API-first architecture)
74
+ - Automatic session renewal (sliding expiration)
75
+ - Flash messages for cross-request communication
76
+ - Multiple backend support (Redis, Memcached, In-Memory)
77
+ - Complete session lifecycle management (create, validate, refresh, invalidate)
78
+
79
+ ### Cache-Control Directives
80
+
81
+ | Directive | Supported | Description |
82
+ |--------------------------|--------------------|---------------------------------------------------------------------------------------------------------|
83
+ | `max-age` | :white_check_mark: | Specifies the maximum amount of time a resource is considered fresh. |
84
+ | `s-maxage` | :x: | Specifies the maximum amount of time a resource is considered fresh for shared caches. |
85
+ | `no-cache` | :white_check_mark: | Forces caches to submit the request to the origin server for validation before releasing a cached copy. |
86
+ | `no-store` | :white_check_mark: | Instructs caches not to store any part of the request or response. |
87
+ | `no-transform` | :x: | Instructs caches not to transform the response content. |
88
+ | `must-revalidate` | :white_check_mark: | Forces caches to revalidate the response with the origin server after it becomes stale. |
89
+ | `proxy-revalidate` | :x: | Similar to `must-revalidate`, but only for shared caches. |
90
+ | `must-understand` | :x: | Indicates that the recipient must understand the directive or treat it as an error. |
91
+ | `private` | :white_check_mark: | Indicates that the response is intended for a single user and should not be stored by shared caches. |
92
+ | `public` | :white_check_mark: | Indicates that the response may be cached by any cache, even if it is normally non-cacheable. |
93
+ | `immutable` | :white_check_mark: | Indicates that the response body will not change over time, allowing for longer caching. |
94
+ | `stale-while-revalidate` | :white_check_mark: | Indicates that a cache can serve a stale response while it revalidates the response in the background. |
95
+ | `stale-if-error` | :white_check_mark: | Indicates that a cache can serve a stale response if the origin server is unavailable. |
96
+
97
+ ## Installation
98
+
99
+ ```bash
100
+ uv add fastapi-cachex
101
+ ```
102
+
103
+ To enable JWT token format support for sessions:
104
+
105
+ ```bash
106
+ uv add "fastapi-cachex[jwt]"
107
+ ```
108
+
109
+ ### Development Installation
110
+
111
+ ```bash
112
+ uv add git+https://github.com/allen0099/FastAPI-CacheX.git
113
+ ```
114
+
115
+ ## Quick Start
116
+
117
+ ```python
118
+ from fastapi import FastAPI
119
+ from fastapi_cachex import cache
120
+ from fastapi_cachex import CacheBackend
121
+
122
+ app = FastAPI()
123
+
124
+
125
+ @app.get("/")
126
+ @cache(ttl=60) # Cache for 60 seconds
127
+ async def read_root():
128
+ return {"Hello": "World"}
129
+
130
+
131
+ @app.get("/no-cache")
132
+ @cache(no_cache=True) # Mark this endpoint as non-cacheable
133
+ async def non_cache_endpoint():
134
+ return {"Hello": "World"}
135
+
136
+
137
+ @app.get("/no-store")
138
+ @cache(no_store=True) # Mark this endpoint as non-cacheable
139
+ async def non_store_endpoint():
140
+ return {"Hello": "World"}
141
+
142
+
143
+ @app.get("/clear_cache")
144
+ async def remove_cache(cache: CacheBackend):
145
+ await cache.clear_path("/path/to/clear") # Clear cache for a specific path
146
+ await cache.clear_pattern("/path/to/clear/*") # Clear cache for a specific pattern
147
+ ```
148
+
149
+ ## Backend Configuration
150
+
151
+ FastAPI-CacheX supports multiple caching backends. You can easily switch between them using the `BackendProxy`.
152
+
153
+ ### Cache Key Format
154
+
155
+ Cache keys are generated in the following format to avoid collisions:
156
+
157
+ ```
158
+ {method}|||{host}|||{path}|||{query_params}
159
+ ```
160
+
161
+ This ensures that:
162
+ - Different HTTP methods (GET, POST, etc.) don't share cache
163
+ - Different hosts don't share cache (useful for multi-tenant scenarios)
164
+ - Different query parameters get separate cache entries
165
+ - The same endpoint with different parameters can be cached independently
166
+
167
+ All backends automatically namespace keys with a prefix (e.g., `fastapi_cachex:`) to avoid conflicts with other applications.
168
+
169
+ ### Cache Hit Behavior
170
+
171
+ When a cached entry is valid (within TTL):
172
+ - **Default behavior**: Returns the cached content with HTTP 200 status code directly without re-executing the endpoint handler
173
+ - **With `If-None-Match` header**: Returns HTTP 304 Not Modified if the ETag matches
174
+ - **With `no-cache` directive**: Forces revalidation with fresh content before deciding on 304
175
+
176
+ This means **cached hits are extremely fast** - the endpoint handler function is never executed.
177
+
178
+ ### In-Memory Cache (default)
179
+
180
+ If you don't specify a backend, FastAPI-CacheX will use the in-memory cache by default.
181
+ This is suitable for development and testing purposes. The backend automatically runs
182
+ a cleanup task to remove expired entries every 60 seconds.
183
+
184
+ ```python
185
+ from fastapi_cachex.backends import MemoryBackend
186
+ from fastapi_cachex import BackendProxy
187
+
188
+ backend = MemoryBackend()
189
+ BackendProxy.set_backend(backend)
190
+ ```
191
+
192
+ **Note**: In-memory cache is not suitable for production with multiple processes.
193
+ Each process maintains its own separate cache.
194
+
195
+ ### Memcached
196
+
197
+ ```python
198
+ from fastapi_cachex.backends import MemcachedBackend
199
+ from fastapi_cachex import BackendProxy
200
+
201
+ backend = MemcachedBackend(servers=["localhost:11211"])
202
+ BackendProxy.set_backend(backend)
203
+ ```
204
+
205
+ **Limitations**:
206
+ - Pattern-based key clearing (`clear_pattern`) is not supported by the Memcached protocol
207
+ - Keys are namespaced with `fastapi_cachex:` prefix to avoid conflicts
208
+ - Consider using Redis backend if you need pattern-based cache clearing
209
+
210
+ ### Redis
211
+
212
+ ```python
213
+ from fastapi_cachex.backends import AsyncRedisCacheBackend
214
+ from fastapi_cachex import BackendProxy
215
+
216
+ backend = AsyncRedisCacheBackend(host="127.0.0.1", port=6379, db=0)
217
+ BackendProxy.set_backend(backend)
218
+ ```
219
+
220
+ **Features**:
221
+ - Fully async implementation
222
+ - Supports pattern-based key clearing
223
+ - Uses SCAN instead of KEYS for safe production use (non-blocking)
224
+ - Namespaced with `fastapi_cachex:` prefix by default
225
+ - Optional custom key prefix for multi-tenant scenarios
226
+
227
+ **Example with custom prefix**:
228
+
229
+ ```python
230
+ backend = AsyncRedisCacheBackend(
231
+ host="127.0.0.1",
232
+ port=6379,
233
+ key_prefix="myapp:cache:",
234
+ )
235
+ BackendProxy.set_backend(backend)
236
+ ```
237
+
238
+ ## Performance Considerations
239
+
240
+ ### Cache Hit Performance
241
+
242
+ When a cache hit occurs (within TTL), the response is returned directly without executing your endpoint handler. This is extremely fast:
243
+
244
+ ```python
245
+ @app.get("/expensive")
246
+ @cache(ttl=3600) # Cache for 1 hour
247
+ async def expensive_operation():
248
+ # This is ONLY executed when cache misses
249
+ # On cache hits, this function is never called
250
+ result = perform_expensive_calculation()
251
+ return result
252
+ ```
253
+
254
+ ### Backend Selection
255
+
256
+ - **MemoryBackend**: Fastest for single-process development; not suitable for production
257
+ - **Memcached**: Good for distributed systems; has limitations on pattern clearing
258
+ - **Redis**: Best for production; fully async, supports all features, non-blocking operations
259
+
260
+ ## Documentation
261
+
262
+ - [Cache Flow Explanation](docs/CACHE_FLOW.md)
263
+ - [Development Guide](docs/DEVELOPMENT.md)
264
+ - [Contributing Guidelines](docs/CONTRIBUTING.md)
265
+ - [Session Management Guide](docs/SESSION.md) - Complete guide for session features
266
+
267
+ ## License
268
+
269
+ This project is licensed under the Apache License 2.0 - see the [LICENSE](LICENSE) file for details.
@@ -0,0 +1,233 @@
1
+ # FastAPI-Cache X
2
+
3
+ [![uv](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/uv/main/assets/badge/v0.json)](https://github.com/astral-sh/uv)
4
+ [![Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json)](https://github.com/astral-sh/ruff)
5
+ [![Tests](https://github.com/allen0099/FastAPI-CacheX/actions/workflows/test.yml/badge.svg)](https://github.com/allen0099/FastAPI-CacheX/actions/workflows/test.yml)
6
+ [![Coverage Status](https://raw.githubusercontent.com/allen0099/FastAPI-CacheX/coverage-badge/coverage.svg)](https://github.com/allen0099/FastAPI-CacheX/actions/workflows/coverage.yml)
7
+
8
+ [![Downloads](https://static.pepy.tech/badge/fastapi-cachex)](https://pepy.tech/project/fastapi-cachex)
9
+ [![Weekly downloads](https://static.pepy.tech/badge/fastapi-cachex/week)](https://pepy.tech/project/fastapi-cachex)
10
+ [![Monthly downloads](https://static.pepy.tech/badge/fastapi-cachex/month)](https://pepy.tech/project/fastapi-cachex)
11
+
12
+ [![PyPI version](https://img.shields.io/pypi/v/fastapi-cachex.svg?logo=pypi&logoColor=gold&label=PyPI)](https://pypi.org/project/fastapi-cachex)
13
+ [![Python Versions](https://img.shields.io/pypi/pyversions/fastapi-cachex.svg?logo=python&label=Python&logoColor=gold)](https://pypi.org/project/fastapi-cachex/)
14
+
15
+ [English](README.md) | [繁體中文](docs/README.zh-TW.md)
16
+
17
+ A high-performance caching extension for FastAPI, providing comprehensive HTTP caching support and optional session management.
18
+
19
+ ## Features
20
+
21
+ ### HTTP Caching
22
+ - Support for HTTP caching headers
23
+ - `Cache-Control`
24
+ - `ETag`
25
+ - `If-None-Match`
26
+ - Multiple backend cache support
27
+ - Redis
28
+ - Memcached
29
+ - In-memory cache
30
+ - Complete Cache-Control directive implementation
31
+ - Easy-to-use `@cache` decorator
32
+
33
+ ### Session Management (Optional Extension)
34
+ - Secure session management with HMAC-SHA256 token signing
35
+ - Optional JWT token format for interoperability (install extra `jwt`)
36
+ - IP address and User-Agent binding (optional security features)
37
+ - Header and bearer token support (API-first architecture)
38
+ - Automatic session renewal (sliding expiration)
39
+ - Flash messages for cross-request communication
40
+ - Multiple backend support (Redis, Memcached, In-Memory)
41
+ - Complete session lifecycle management (create, validate, refresh, invalidate)
42
+
43
+ ### Cache-Control Directives
44
+
45
+ | Directive | Supported | Description |
46
+ |--------------------------|--------------------|---------------------------------------------------------------------------------------------------------|
47
+ | `max-age` | :white_check_mark: | Specifies the maximum amount of time a resource is considered fresh. |
48
+ | `s-maxage` | :x: | Specifies the maximum amount of time a resource is considered fresh for shared caches. |
49
+ | `no-cache` | :white_check_mark: | Forces caches to submit the request to the origin server for validation before releasing a cached copy. |
50
+ | `no-store` | :white_check_mark: | Instructs caches not to store any part of the request or response. |
51
+ | `no-transform` | :x: | Instructs caches not to transform the response content. |
52
+ | `must-revalidate` | :white_check_mark: | Forces caches to revalidate the response with the origin server after it becomes stale. |
53
+ | `proxy-revalidate` | :x: | Similar to `must-revalidate`, but only for shared caches. |
54
+ | `must-understand` | :x: | Indicates that the recipient must understand the directive or treat it as an error. |
55
+ | `private` | :white_check_mark: | Indicates that the response is intended for a single user and should not be stored by shared caches. |
56
+ | `public` | :white_check_mark: | Indicates that the response may be cached by any cache, even if it is normally non-cacheable. |
57
+ | `immutable` | :white_check_mark: | Indicates that the response body will not change over time, allowing for longer caching. |
58
+ | `stale-while-revalidate` | :white_check_mark: | Indicates that a cache can serve a stale response while it revalidates the response in the background. |
59
+ | `stale-if-error` | :white_check_mark: | Indicates that a cache can serve a stale response if the origin server is unavailable. |
60
+
61
+ ## Installation
62
+
63
+ ```bash
64
+ uv add fastapi-cachex
65
+ ```
66
+
67
+ To enable JWT token format support for sessions:
68
+
69
+ ```bash
70
+ uv add "fastapi-cachex[jwt]"
71
+ ```
72
+
73
+ ### Development Installation
74
+
75
+ ```bash
76
+ uv add git+https://github.com/allen0099/FastAPI-CacheX.git
77
+ ```
78
+
79
+ ## Quick Start
80
+
81
+ ```python
82
+ from fastapi import FastAPI
83
+ from fastapi_cachex import cache
84
+ from fastapi_cachex import CacheBackend
85
+
86
+ app = FastAPI()
87
+
88
+
89
+ @app.get("/")
90
+ @cache(ttl=60) # Cache for 60 seconds
91
+ async def read_root():
92
+ return {"Hello": "World"}
93
+
94
+
95
+ @app.get("/no-cache")
96
+ @cache(no_cache=True) # Mark this endpoint as non-cacheable
97
+ async def non_cache_endpoint():
98
+ return {"Hello": "World"}
99
+
100
+
101
+ @app.get("/no-store")
102
+ @cache(no_store=True) # Mark this endpoint as non-cacheable
103
+ async def non_store_endpoint():
104
+ return {"Hello": "World"}
105
+
106
+
107
+ @app.get("/clear_cache")
108
+ async def remove_cache(cache: CacheBackend):
109
+ await cache.clear_path("/path/to/clear") # Clear cache for a specific path
110
+ await cache.clear_pattern("/path/to/clear/*") # Clear cache for a specific pattern
111
+ ```
112
+
113
+ ## Backend Configuration
114
+
115
+ FastAPI-CacheX supports multiple caching backends. You can easily switch between them using the `BackendProxy`.
116
+
117
+ ### Cache Key Format
118
+
119
+ Cache keys are generated in the following format to avoid collisions:
120
+
121
+ ```
122
+ {method}|||{host}|||{path}|||{query_params}
123
+ ```
124
+
125
+ This ensures that:
126
+ - Different HTTP methods (GET, POST, etc.) don't share cache
127
+ - Different hosts don't share cache (useful for multi-tenant scenarios)
128
+ - Different query parameters get separate cache entries
129
+ - The same endpoint with different parameters can be cached independently
130
+
131
+ All backends automatically namespace keys with a prefix (e.g., `fastapi_cachex:`) to avoid conflicts with other applications.
132
+
133
+ ### Cache Hit Behavior
134
+
135
+ When a cached entry is valid (within TTL):
136
+ - **Default behavior**: Returns the cached content with HTTP 200 status code directly without re-executing the endpoint handler
137
+ - **With `If-None-Match` header**: Returns HTTP 304 Not Modified if the ETag matches
138
+ - **With `no-cache` directive**: Forces revalidation with fresh content before deciding on 304
139
+
140
+ This means **cached hits are extremely fast** - the endpoint handler function is never executed.
141
+
142
+ ### In-Memory Cache (default)
143
+
144
+ If you don't specify a backend, FastAPI-CacheX will use the in-memory cache by default.
145
+ This is suitable for development and testing purposes. The backend automatically runs
146
+ a cleanup task to remove expired entries every 60 seconds.
147
+
148
+ ```python
149
+ from fastapi_cachex.backends import MemoryBackend
150
+ from fastapi_cachex import BackendProxy
151
+
152
+ backend = MemoryBackend()
153
+ BackendProxy.set_backend(backend)
154
+ ```
155
+
156
+ **Note**: In-memory cache is not suitable for production with multiple processes.
157
+ Each process maintains its own separate cache.
158
+
159
+ ### Memcached
160
+
161
+ ```python
162
+ from fastapi_cachex.backends import MemcachedBackend
163
+ from fastapi_cachex import BackendProxy
164
+
165
+ backend = MemcachedBackend(servers=["localhost:11211"])
166
+ BackendProxy.set_backend(backend)
167
+ ```
168
+
169
+ **Limitations**:
170
+ - Pattern-based key clearing (`clear_pattern`) is not supported by the Memcached protocol
171
+ - Keys are namespaced with `fastapi_cachex:` prefix to avoid conflicts
172
+ - Consider using Redis backend if you need pattern-based cache clearing
173
+
174
+ ### Redis
175
+
176
+ ```python
177
+ from fastapi_cachex.backends import AsyncRedisCacheBackend
178
+ from fastapi_cachex import BackendProxy
179
+
180
+ backend = AsyncRedisCacheBackend(host="127.0.0.1", port=6379, db=0)
181
+ BackendProxy.set_backend(backend)
182
+ ```
183
+
184
+ **Features**:
185
+ - Fully async implementation
186
+ - Supports pattern-based key clearing
187
+ - Uses SCAN instead of KEYS for safe production use (non-blocking)
188
+ - Namespaced with `fastapi_cachex:` prefix by default
189
+ - Optional custom key prefix for multi-tenant scenarios
190
+
191
+ **Example with custom prefix**:
192
+
193
+ ```python
194
+ backend = AsyncRedisCacheBackend(
195
+ host="127.0.0.1",
196
+ port=6379,
197
+ key_prefix="myapp:cache:",
198
+ )
199
+ BackendProxy.set_backend(backend)
200
+ ```
201
+
202
+ ## Performance Considerations
203
+
204
+ ### Cache Hit Performance
205
+
206
+ When a cache hit occurs (within TTL), the response is returned directly without executing your endpoint handler. This is extremely fast:
207
+
208
+ ```python
209
+ @app.get("/expensive")
210
+ @cache(ttl=3600) # Cache for 1 hour
211
+ async def expensive_operation():
212
+ # This is ONLY executed when cache misses
213
+ # On cache hits, this function is never called
214
+ result = perform_expensive_calculation()
215
+ return result
216
+ ```
217
+
218
+ ### Backend Selection
219
+
220
+ - **MemoryBackend**: Fastest for single-process development; not suitable for production
221
+ - **Memcached**: Good for distributed systems; has limitations on pattern clearing
222
+ - **Redis**: Best for production; fully async, supports all features, non-blocking operations
223
+
224
+ ## Documentation
225
+
226
+ - [Cache Flow Explanation](docs/CACHE_FLOW.md)
227
+ - [Development Guide](docs/DEVELOPMENT.md)
228
+ - [Contributing Guidelines](docs/CONTRIBUTING.md)
229
+ - [Session Management Guide](docs/SESSION.md) - Complete guide for session features
230
+
231
+ ## License
232
+
233
+ This project is licensed under the Apache License 2.0 - see the [LICENSE](LICENSE) file for details.
@@ -0,0 +1,27 @@
1
+ """FastAPI-CacheX: A powerful and flexible caching extension for FastAPI."""
2
+
3
+ import logging
4
+
5
+ from .cache import cache as cache
6
+ from .cache import default_key_builder as default_key_builder
7
+ from .dependencies import CacheBackend as CacheBackend
8
+ from .dependencies import get_cache_backend as get_cache_backend
9
+ from .proxy import BackendProxy as BackendProxy
10
+ from .routes import add_routes as add_routes
11
+ from .types import CacheKeyBuilder as CacheKeyBuilder
12
+
13
+ _package_logger = logging.getLogger("fastapi_cachex")
14
+ _package_logger.addHandler(
15
+ logging.NullHandler()
16
+ ) # Attach a NullHandler to avoid "No handler found" warnings in user applications.
17
+
18
+ # Session management (optional feature)
19
+ __all__ = [
20
+ "BackendProxy",
21
+ "CacheBackend",
22
+ "CacheKeyBuilder",
23
+ "add_routes",
24
+ "cache",
25
+ "default_key_builder",
26
+ "get_cache_backend",
27
+ ]
@@ -0,0 +1,15 @@
1
+ """Cache backend implementations for FastAPI-CacheX."""
2
+
3
+ from .base import BaseCacheBackend
4
+ from .config import RedisConfig
5
+ from .memcached import MemcachedBackend
6
+ from .memory import MemoryBackend
7
+ from .redis import AsyncRedisCacheBackend
8
+
9
+ __all__ = [
10
+ "AsyncRedisCacheBackend",
11
+ "BaseCacheBackend",
12
+ "MemcachedBackend",
13
+ "MemoryBackend",
14
+ "RedisConfig",
15
+ ]
@@ -0,0 +1,70 @@
1
+ """Base cache backend interface and abstract implementation."""
2
+
3
+ from abc import ABC
4
+ from abc import abstractmethod
5
+ from typing import Any
6
+
7
+ from fastapi_cachex.types import ETagContent
8
+
9
+
10
+ class BaseCacheBackend(ABC):
11
+ """Base class for all cache backends."""
12
+
13
+ @abstractmethod
14
+ async def get(self, key: str) -> ETagContent | None:
15
+ """Retrieve a cached response."""
16
+
17
+ @abstractmethod
18
+ async def set(self, key: str, value: ETagContent, ttl: int | None = None) -> None:
19
+ """Store a response in the cache."""
20
+
21
+ @abstractmethod
22
+ async def delete(self, key: str) -> None:
23
+ """Remove a response from the cache."""
24
+
25
+ @abstractmethod
26
+ async def clear(self) -> None:
27
+ """Clear all cached responses."""
28
+
29
+ @abstractmethod
30
+ async def clear_path(self, path: str, include_params: bool = False) -> int:
31
+ """Clear cached responses for a specific path.
32
+
33
+ Args:
34
+ path: The path to clear cache for
35
+ include_params: Whether to clear all parameter variations of the path
36
+
37
+ Returns:
38
+ Number of cache entries cleared
39
+ """
40
+
41
+ @abstractmethod
42
+ async def clear_pattern(self, pattern: str) -> int:
43
+ """Clear cached responses matching a pattern.
44
+
45
+ Args:
46
+ pattern: A glob pattern to match cache keys against (e.g., "/users/*")
47
+
48
+ Returns:
49
+ Number of cache entries cleared
50
+ """
51
+
52
+ @abstractmethod
53
+ async def get_all_keys(self) -> list[str]:
54
+ """Get all cache keys in the backend.
55
+
56
+ Returns:
57
+ List of all cache keys currently stored in the backend
58
+ """
59
+
60
+ @abstractmethod
61
+ async def get_cache_data(self) -> dict[str, tuple[Any, float | None]]:
62
+ """Get all cache data with expiry information.
63
+
64
+ This method is primarily used for cache monitoring and statistics.
65
+ Returns cache keys mapped to tuples of (value, expiry_time).
66
+
67
+ Returns:
68
+ Dictionary mapping cache keys to (value, expiry) tuples.
69
+ Expiry is None if the item never expires.
70
+ """
@@ -0,0 +1,15 @@
1
+ """Configuration models for cache backends."""
2
+
3
+ from pydantic import BaseModel
4
+ from pydantic import Field
5
+ from pydantic import SecretStr
6
+
7
+
8
+ class RedisConfig(BaseModel):
9
+ """Configuration for Redis backend."""
10
+
11
+ host: str = Field(default="localhost", description="Redis server address")
12
+ port: int = Field(default=6379, description="Redis server port")
13
+ password: SecretStr | None = Field(
14
+ default=None, description="Redis server password"
15
+ )