cachekit 0.17.1__tar.gz → 0.18.0__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.
- {cachekit-0.17.1 → cachekit-0.18.0}/Cargo.lock +4 -3
- {cachekit-0.17.1 → cachekit-0.18.0}/PKG-INFO +36 -21
- {cachekit-0.17.1 → cachekit-0.18.0}/README.md +32 -17
- {cachekit-0.17.1 → cachekit-0.18.0}/pyproject.toml +8 -4
- {cachekit-0.17.1 → cachekit-0.18.0}/rust/Cargo.toml +7 -3
- {cachekit-0.17.1 → cachekit-0.18.0}/rust/README.md +32 -17
- {cachekit-0.17.1 → cachekit-0.18.0}/rust/src/lib.rs +2 -5
- {cachekit-0.17.1 → cachekit-0.18.0}/rust/src/python_bindings.rs +212 -46
- {cachekit-0.17.1 → cachekit-0.18.0}/src/cachekit/__init__.py +8 -7
- {cachekit-0.17.1 → cachekit-0.18.0}/src/cachekit/backends/cachekitio/backend.py +38 -13
- {cachekit-0.17.1 → cachekit-0.18.0}/src/cachekit/backends/file/backend.py +40 -15
- {cachekit-0.17.1 → cachekit-0.18.0}/src/cachekit/cache_handler.py +53 -6
- {cachekit-0.17.1 → cachekit-0.18.0}/src/cachekit/config/decorator.py +0 -6
- {cachekit-0.17.1 → cachekit-0.18.0}/src/cachekit/config/nested.py +0 -2
- {cachekit-0.17.1 → cachekit-0.18.0}/src/cachekit/config/settings.py +170 -2
- {cachekit-0.17.1 → cachekit-0.18.0}/src/cachekit/decorators/wrapper.py +18 -1
- {cachekit-0.17.1 → cachekit-0.18.0}/src/cachekit/key_generator.py +14 -8
- {cachekit-0.17.1 → cachekit-0.18.0}/src/cachekit/l1_cache.py +3 -200
- {cachekit-0.17.1 → cachekit-0.18.0}/src/cachekit/serializers/__init__.py +7 -1
- {cachekit-0.17.1 → cachekit-0.18.0}/src/cachekit/serializers/encryption_wrapper.py +245 -16
- {cachekit-0.17.1 → cachekit-0.18.0}/src/cachekit/serializers/standard_serializer.py +6 -2
- {cachekit-0.17.1 → cachekit-0.18.0}/Cargo.toml +0 -0
- {cachekit-0.17.1 → cachekit-0.18.0}/LICENSE +0 -0
- {cachekit-0.17.1 → cachekit-0.18.0}/rust/Makefile +0 -0
- {cachekit-0.17.1 → cachekit-0.18.0}/rust/TEST_EXPANSION_SUMMARY.md +0 -0
- {cachekit-0.17.1 → cachekit-0.18.0}/rust/supply-chain/audits.toml +0 -0
- {cachekit-0.17.1 → cachekit-0.18.0}/rust/supply-chain/config.toml +0 -0
- {cachekit-0.17.1 → cachekit-0.18.0}/rust/supply-chain/imports.lock +0 -0
- {cachekit-0.17.1 → cachekit-0.18.0}/rust/tsan_suppressions.txt +0 -0
- {cachekit-0.17.1 → cachekit-0.18.0}/src/cachekit/backends/__init__.py +0 -0
- {cachekit-0.17.1 → cachekit-0.18.0}/src/cachekit/backends/base.py +0 -0
- {cachekit-0.17.1 → cachekit-0.18.0}/src/cachekit/backends/base_config.py +0 -0
- {cachekit-0.17.1 → cachekit-0.18.0}/src/cachekit/backends/cachekitio/__init__.py +0 -0
- {cachekit-0.17.1 → cachekit-0.18.0}/src/cachekit/backends/cachekitio/client.py +0 -0
- {cachekit-0.17.1 → cachekit-0.18.0}/src/cachekit/backends/cachekitio/config.py +0 -0
- {cachekit-0.17.1 → cachekit-0.18.0}/src/cachekit/backends/cachekitio/error_handler.py +0 -0
- {cachekit-0.17.1 → cachekit-0.18.0}/src/cachekit/backends/cachekitio/session.py +0 -0
- {cachekit-0.17.1 → cachekit-0.18.0}/src/cachekit/backends/errors.py +0 -0
- {cachekit-0.17.1 → cachekit-0.18.0}/src/cachekit/backends/file/__init__.py +0 -0
- {cachekit-0.17.1 → cachekit-0.18.0}/src/cachekit/backends/file/config.py +0 -0
- {cachekit-0.17.1 → cachekit-0.18.0}/src/cachekit/backends/memcached/__init__.py +0 -0
- {cachekit-0.17.1 → cachekit-0.18.0}/src/cachekit/backends/memcached/backend.py +0 -0
- {cachekit-0.17.1 → cachekit-0.18.0}/src/cachekit/backends/memcached/config.py +0 -0
- {cachekit-0.17.1 → cachekit-0.18.0}/src/cachekit/backends/memcached/error_handler.py +0 -0
- {cachekit-0.17.1 → cachekit-0.18.0}/src/cachekit/backends/provider.py +0 -0
- {cachekit-0.17.1 → cachekit-0.18.0}/src/cachekit/backends/redis/__init__.py +0 -0
- {cachekit-0.17.1 → cachekit-0.18.0}/src/cachekit/backends/redis/backend.py +0 -0
- {cachekit-0.17.1 → cachekit-0.18.0}/src/cachekit/backends/redis/client.py +0 -0
- {cachekit-0.17.1 → cachekit-0.18.0}/src/cachekit/backends/redis/config.py +0 -0
- {cachekit-0.17.1 → cachekit-0.18.0}/src/cachekit/backends/redis/error_handler.py +0 -0
- {cachekit-0.17.1 → cachekit-0.18.0}/src/cachekit/backends/redis/provider.py +0 -0
- {cachekit-0.17.1 → cachekit-0.18.0}/src/cachekit/config/__init__.py +0 -0
- {cachekit-0.17.1 → cachekit-0.18.0}/src/cachekit/config/singleton.py +0 -0
- {cachekit-0.17.1 → cachekit-0.18.0}/src/cachekit/config/validation.py +0 -0
- {cachekit-0.17.1 → cachekit-0.18.0}/src/cachekit/decorators/__init__.py +0 -0
- {cachekit-0.17.1 → cachekit-0.18.0}/src/cachekit/decorators/intent.py +0 -0
- {cachekit-0.17.1 → cachekit-0.18.0}/src/cachekit/decorators/local_wrapper.py +0 -0
- {cachekit-0.17.1 → cachekit-0.18.0}/src/cachekit/decorators/main.py +0 -0
- {cachekit-0.17.1 → cachekit-0.18.0}/src/cachekit/decorators/orchestrator.py +0 -0
- {cachekit-0.17.1 → cachekit-0.18.0}/src/cachekit/decorators/session.py +0 -0
- {cachekit-0.17.1 → cachekit-0.18.0}/src/cachekit/decorators/stats_context.py +0 -0
- {cachekit-0.17.1 → cachekit-0.18.0}/src/cachekit/decorators/tenant_context.py +0 -0
- {cachekit-0.17.1 → cachekit-0.18.0}/src/cachekit/decorators/utils/__init__.py +0 -0
- {cachekit-0.17.1 → cachekit-0.18.0}/src/cachekit/di.py +0 -0
- {cachekit-0.17.1 → cachekit-0.18.0}/src/cachekit/hash_utils.py +0 -0
- {cachekit-0.17.1 → cachekit-0.18.0}/src/cachekit/health.py +0 -0
- {cachekit-0.17.1 → cachekit-0.18.0}/src/cachekit/hiredis_compat.py +0 -0
- {cachekit-0.17.1 → cachekit-0.18.0}/src/cachekit/imports.py +0 -0
- {cachekit-0.17.1 → cachekit-0.18.0}/src/cachekit/interop.py +0 -0
- {cachekit-0.17.1 → cachekit-0.18.0}/src/cachekit/logging.py +0 -0
- {cachekit-0.17.1 → cachekit-0.18.0}/src/cachekit/monitoring/__init__.py +0 -0
- {cachekit-0.17.1 → cachekit-0.18.0}/src/cachekit/monitoring/correlation_tracking.py +0 -0
- {cachekit-0.17.1 → cachekit-0.18.0}/src/cachekit/monitoring/pool_monitor.py +0 -0
- {cachekit-0.17.1 → cachekit-0.18.0}/src/cachekit/monitoring/protocols.py +0 -0
- {cachekit-0.17.1 → cachekit-0.18.0}/src/cachekit/object_cache.py +0 -0
- {cachekit-0.17.1 → cachekit-0.18.0}/src/cachekit/py.typed +0 -0
- {cachekit-0.17.1 → cachekit-0.18.0}/src/cachekit/reliability/__init__.py +0 -0
- {cachekit-0.17.1 → cachekit-0.18.0}/src/cachekit/reliability/async_metrics.py +0 -0
- {cachekit-0.17.1 → cachekit-0.18.0}/src/cachekit/reliability/circuit_breaker.py +0 -0
- {cachekit-0.17.1 → cachekit-0.18.0}/src/cachekit/reliability/error_classification.py +0 -0
- {cachekit-0.17.1 → cachekit-0.18.0}/src/cachekit/reliability/load_control.py +0 -0
- {cachekit-0.17.1 → cachekit-0.18.0}/src/cachekit/reliability/metrics_collection.py +0 -0
- {cachekit-0.17.1 → cachekit-0.18.0}/src/cachekit/reliability/profiles.py +0 -0
- {cachekit-0.17.1 → cachekit-0.18.0}/src/cachekit/serializers/arrow_serializer.py +0 -0
- {cachekit-0.17.1 → cachekit-0.18.0}/src/cachekit/serializers/auto_serializer.py +0 -0
- {cachekit-0.17.1 → cachekit-0.18.0}/src/cachekit/serializers/base.py +0 -0
- {cachekit-0.17.1 → cachekit-0.18.0}/src/cachekit/serializers/interop_serializer.py +0 -0
- {cachekit-0.17.1 → cachekit-0.18.0}/src/cachekit/serializers/orjson_serializer.py +0 -0
- {cachekit-0.17.1 → cachekit-0.18.0}/src/cachekit/serializers/wrapper.py +0 -0
|
@@ -245,9 +245,9 @@ checksum = "1e748733b7cbc798e1434b6ac524f0c1ff2ab456fe201501e6497c8417a4fc33"
|
|
|
245
245
|
|
|
246
246
|
[[package]]
|
|
247
247
|
name = "cachekit-core"
|
|
248
|
-
version = "0.
|
|
248
|
+
version = "0.5.0"
|
|
249
249
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
250
|
-
checksum = "
|
|
250
|
+
checksum = "12089baacc5ff661a62d2071588c895973bc48e42ed359178afaee22decb5559"
|
|
251
251
|
dependencies = [
|
|
252
252
|
"aes",
|
|
253
253
|
"aes-gcm",
|
|
@@ -271,7 +271,7 @@ dependencies = [
|
|
|
271
271
|
|
|
272
272
|
[[package]]
|
|
273
273
|
name = "cachekit-rs"
|
|
274
|
-
version = "0.
|
|
274
|
+
version = "0.18.0"
|
|
275
275
|
dependencies = [
|
|
276
276
|
"cachekit-core",
|
|
277
277
|
"criterion",
|
|
@@ -282,6 +282,7 @@ dependencies = [
|
|
|
282
282
|
"pprof",
|
|
283
283
|
"proptest",
|
|
284
284
|
"pyo3",
|
|
285
|
+
"zeroize",
|
|
285
286
|
]
|
|
286
287
|
|
|
287
288
|
[[package]]
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: cachekit
|
|
3
|
-
Version: 0.
|
|
4
|
-
Classifier: Development Status ::
|
|
3
|
+
Version: 0.18.0
|
|
4
|
+
Classifier: Development Status :: 4 - Beta
|
|
5
5
|
Classifier: Intended Audience :: Developers
|
|
6
6
|
Classifier: License :: OSI Approved :: MIT License
|
|
7
7
|
Classifier: Operating System :: OS Independent
|
|
@@ -21,7 +21,7 @@ Classifier: Framework :: AsyncIO
|
|
|
21
21
|
Classifier: Typing :: Typed
|
|
22
22
|
Requires-Dist: redis[hiredis]>=4.0.0
|
|
23
23
|
Requires-Dist: pydantic>=2.0.0
|
|
24
|
-
Requires-Dist: pydantic-settings>=2.
|
|
24
|
+
Requires-Dist: pydantic-settings>=2.7.0
|
|
25
25
|
Requires-Dist: prometheus-client>=0.22.1
|
|
26
26
|
Requires-Dist: psutil>=7.0.0
|
|
27
27
|
Requires-Dist: blake3>=1.0.5
|
|
@@ -37,7 +37,7 @@ Provides-Extra: data
|
|
|
37
37
|
Provides-Extra: json
|
|
38
38
|
Provides-Extra: memcached
|
|
39
39
|
License-File: LICENSE
|
|
40
|
-
Summary:
|
|
40
|
+
Summary: Backend-agnostic caching for Python — intent-based decorators with circuit breaker, distributed locking, Prometheus metrics, and optional zero-knowledge AES-256-GCM encryption, on a Rust-powered core. Zero-config L1 in-memory; scales to Redis, Memcached, File, or CachekitIO.
|
|
41
41
|
Keywords: redis,cache,caching,decorator,rust,performance,reliability,production,encryption,security,circuit-breaker,prometheus,messagepack,distributed-locking
|
|
42
42
|
Home-Page: https://github.com/cachekit-io/cachekit-py
|
|
43
43
|
Author-email: cachekit Contributors <noreply@cachekit.io>
|
|
@@ -57,7 +57,7 @@ Project-URL: Repository, https://github.com/cachekit-io/cachekit-py.git
|
|
|
57
57
|
|
|
58
58
|
> **Python caching, batteries included**
|
|
59
59
|
|
|
60
|
-
|
|
60
|
+
Backend-agnostic caching with intent-based decorators — circuit breaker, distributed locking, Prometheus metrics, and optional zero-knowledge encryption on a Rust-powered core. Zero config to start, any backend when you scale.
|
|
61
61
|
|
|
62
62
|
[![PyPI Version][pypi-badge]][pypi-url]
|
|
63
63
|
[![Python Versions][python-badge]][pypi-url]
|
|
@@ -68,20 +68,16 @@ Production-ready caching for Python with intelligent reliability features and Ru
|
|
|
68
68
|
|
|
69
69
|
---
|
|
70
70
|
|
|
71
|
-
> [!
|
|
72
|
-
> **
|
|
73
|
-
>
|
|
74
|
-
> 🐛 **Found a bug?** Please [open an issue][issues-url] — even small ones help us improve.
|
|
75
|
-
>
|
|
76
|
-
> 💡 **Something feel off?** We want to hear about rough edges, confusing APIs, or missing features.
|
|
71
|
+
> [!NOTE]
|
|
72
|
+
> **Status: beta** — CacheKit is in closed beta ahead of 1.0. APIs are stabilising; minor breaking changes may still occur between 0.x releases.
|
|
77
73
|
>
|
|
78
|
-
>
|
|
74
|
+
> 🐛 **Found a bug or a rough edge?** Please [open an issue][issues-url] — your feedback directly shapes the path to 1.0.
|
|
79
75
|
|
|
80
76
|
---
|
|
81
77
|
|
|
82
78
|
## Why cachekit?
|
|
83
79
|
|
|
84
|
-
**Simple to use,
|
|
80
|
+
**Simple to use, works out of the box.**
|
|
85
81
|
|
|
86
82
|
```python
|
|
87
83
|
from cachekit import cache
|
|
@@ -125,7 +121,7 @@ backend that fits your infrastructure — they're peers behind the same `@cache`
|
|
|
125
121
|
| Backend | Best for | Select with |
|
|
126
122
|
|---------|----------|-------------|
|
|
127
123
|
| Redis | Self-hosted, full control | `REDIS_URL` / `CACHEKIT_REDIS_URL` |
|
|
128
|
-
| CachekitIO | Managed, zero-ops (
|
|
124
|
+
| CachekitIO | Managed, zero-ops (beta) | `CACHEKIT_API_KEY` |
|
|
129
125
|
| Memcached | High-throughput, existing infra | `CACHEKIT_MEMCACHED_SERVERS` |
|
|
130
126
|
| File / L1-only | Local dev, tests, no external deps | `CACHEKIT_FILE_CACHE_DIR` / `backend=None` |
|
|
131
127
|
|
|
@@ -148,7 +144,7 @@ def expensive_api_call(user_id: int):
|
|
|
148
144
|
### More Backends
|
|
149
145
|
|
|
150
146
|
<details>
|
|
151
|
-
<summary><strong>CachekitIO — Managed SaaS (
|
|
147
|
+
<summary><strong>CachekitIO — Managed SaaS (Beta)</strong></summary>
|
|
152
148
|
|
|
153
149
|
```python notest
|
|
154
150
|
import os
|
|
@@ -162,7 +158,7 @@ def expensive_api_call(user_id: int):
|
|
|
162
158
|
return fetch_user_data(user_id)
|
|
163
159
|
```
|
|
164
160
|
|
|
165
|
-
*cachekit.io is in closed
|
|
161
|
+
*cachekit.io is in closed beta — [request access](https://cachekit.io) to get started.*
|
|
166
162
|
|
|
167
163
|
</details>
|
|
168
164
|
|
|
@@ -188,9 +184,9 @@ def expensive_api_call(user_id: int):
|
|
|
188
184
|
|
|
189
185
|
---
|
|
190
186
|
|
|
191
|
-
> **CachekitIO Cloud (
|
|
187
|
+
> **CachekitIO Cloud (Beta)**
|
|
192
188
|
> Managed caching with zero infrastructure. L1+L2 caching, circuit breaker, and automatic failover — no Redis to manage.
|
|
193
|
-
> *cachekit.io is in closed
|
|
189
|
+
> *cachekit.io is in closed beta — [request access](https://cachekit.io) to get started.*
|
|
194
190
|
|
|
195
191
|
---
|
|
196
192
|
|
|
@@ -221,9 +217,8 @@ def get_user_profile(user_id: int):
|
|
|
221
217
|
| Backpressure | ✅ | ✅ | - | ✅ | ✅ |
|
|
222
218
|
| Integrity Checking | - | ✅ | - | ✅ | ✅ 🔒 |
|
|
223
219
|
| Encryption | - | - | - | - | ✅ Required |
|
|
224
|
-
| L1 SWR | - | ✅ | - | ✅ | ✅ |
|
|
220
|
+
| L1 SWR (L1-only mode) | - | ✅ | - | ✅ | ✅ |
|
|
225
221
|
| L1 Invalidation | - | - | - | ✅ | ✅ |
|
|
226
|
-
| L1 Namespace Index | - | - | - | ✅ | ✅ |
|
|
227
222
|
| Prometheus Metrics | - | - | - | ✅ | ✅ |
|
|
228
223
|
| Tracing | - | ✅ | - | ✅ | ✅ |
|
|
229
224
|
| Structured Logging | - | ✅ | - | ✅ | ✅ |
|
|
@@ -231,6 +226,8 @@ def get_user_profile(user_id: int):
|
|
|
231
226
|
|
|
232
227
|
> 🔒 `@cache.secure` forces `integrity_checking=True` — it cannot be overridden.
|
|
233
228
|
>
|
|
229
|
+
> **L1 SWR** (within-TTL background refresh) runs only in L1-only mode (`backend=None`) — with a backend configured it has no effect. `@cache.io` additionally ships past-TTL SWR via `stale_ttl` ([docs](docs/configuration.md#stale-while-revalidate-stale_ttl)).
|
|
230
|
+
>
|
|
234
231
|
> **`@cache.io()`** mirrors `@cache.production` (full reliability + observability) but routes to the managed CachekitIO SaaS backend instead of Redis. **`@cache.local()`** is a separate in-process path backed by `ObjectCache` (raw object references, entry-count LRU, no serialization) — the reliability and encryption features listed above do not apply to it.
|
|
235
232
|
|
|
236
233
|
<details>
|
|
@@ -346,6 +343,12 @@ def get_patient_data(hospital_id: int):
|
|
|
346
343
|
> [!CAUTION]
|
|
347
344
|
> When handling PII, medical, or financial data, always use `@cache.secure` to enforce encryption.
|
|
348
345
|
|
|
346
|
+
**Zero-downtime key rotation**: promote a new `CACHEKIT_MASTER_KEY` and keep the
|
|
347
|
+
retiring key readable via `CACHEKIT_PREVIOUS_MASTER_KEYS` (comma-separated hex,
|
|
348
|
+
max 3 decrypt-only keys). Entries are selected by exact key fingerprint — never
|
|
349
|
+
trial decryption — and old entries age out via TTL, no cache flush required. See
|
|
350
|
+
[Zero-Knowledge Encryption](docs/features/zero-knowledge-encryption.md#key-rotation-pattern).
|
|
351
|
+
|
|
349
352
|
cachekit employs comprehensive security tooling:
|
|
350
353
|
|
|
351
354
|
- **Supply Chain Security**: cargo-deny for license compliance + RustSec scanning
|
|
@@ -443,6 +446,7 @@ info = expensive_func.cache_info()
|
|
|
443
446
|
| [Comparison Guide][comparison-url] | How cachekit compares to lru_cache, aiocache, cachetools |
|
|
444
447
|
| [Getting Started][getting-started-url] | Progressive tutorial from basics to advanced |
|
|
445
448
|
| [API Reference][api-reference-url] | Complete API documentation |
|
|
449
|
+
| [Skyline (live example)][skyline-url] | Canonical example project: this SDK ingests the Bluesky firehose and writes the analytics entries a TypeScript edge Worker serves live, on one shared interop namespace |
|
|
446
450
|
|
|
447
451
|
### Feature Deep Dives
|
|
448
452
|
|
|
@@ -453,6 +457,11 @@ info = expensive_func.cache_info()
|
|
|
453
457
|
| [Distributed Locking][distributed-locking-url] | Cache stampede prevention |
|
|
454
458
|
| [Prometheus Metrics][prometheus-url] | Built-in observability |
|
|
455
459
|
| [Zero-Knowledge Encryption][encryption-url] | Client-side security |
|
|
460
|
+
| [Interop Mode][interop-url] | Cross-SDK cache sharing with cachekit-ts/rs |
|
|
461
|
+
| [L1 Invalidation & SWR][l1-invalidation-url] | Process-local invalidation, stale-while-revalidate |
|
|
462
|
+
| [Reference Caching][reference-caching-url] | `@cache.local()` for non-serializable objects |
|
|
463
|
+
| [Rust Serialization][rust-serialization-url] | ByteStorage layer: LZ4, xxHash3, AES-256-GCM |
|
|
464
|
+
| [SSRF Protection][ssrf-url] | URL allowlisting for the CachekitIO backend |
|
|
456
465
|
|
|
457
466
|
---
|
|
458
467
|
|
|
@@ -465,7 +474,7 @@ info = expensive_func.cache_info()
|
|
|
465
474
|
CACHEKIT_REDIS_URL="redis://localhost:6379" # Primary (preferred)
|
|
466
475
|
REDIS_URL="redis://localhost:6379" # Fallback
|
|
467
476
|
|
|
468
|
-
# CachekitIO SaaS Backend (closed
|
|
477
|
+
# CachekitIO SaaS Backend (closed beta — request access at cachekit.io)
|
|
469
478
|
CACHEKIT_API_KEY="your-api-key" # Required for @cache.io() # pragma: allowlist secret
|
|
470
479
|
CACHEKIT_API_URL="https://api.cachekit.io" # Default SaaS endpoint
|
|
471
480
|
|
|
@@ -528,6 +537,7 @@ MIT License - see [LICENSE][license-file-url] for details.
|
|
|
528
537
|
[uv-url]: https://github.com/astral-sh/uv
|
|
529
538
|
[security-url]: SECURITY.md
|
|
530
539
|
[comparison-url]: docs/comparison.md
|
|
540
|
+
[skyline-url]: https://github.com/cachekit-io/bluesky-thinking
|
|
531
541
|
[getting-started-url]: docs/getting-started.md
|
|
532
542
|
[api-reference-url]: docs/api-reference.md
|
|
533
543
|
[serializer-guide-url]: docs/serializers/index.md
|
|
@@ -535,6 +545,11 @@ MIT License - see [LICENSE][license-file-url] for details.
|
|
|
535
545
|
[distributed-locking-url]: docs/features/distributed-locking.md
|
|
536
546
|
[prometheus-url]: docs/features/prometheus-metrics.md
|
|
537
547
|
[encryption-url]: docs/features/zero-knowledge-encryption.md
|
|
548
|
+
[interop-url]: docs/features/interop-mode.md
|
|
549
|
+
[l1-invalidation-url]: docs/features/l1-invalidation.md
|
|
550
|
+
[reference-caching-url]: docs/features/reference-caching.md
|
|
551
|
+
[rust-serialization-url]: docs/features/rust-serialization.md
|
|
552
|
+
[ssrf-url]: docs/features/ssrf-protection.md
|
|
538
553
|
[contributing-url]: CONTRIBUTING.md
|
|
539
554
|
[license-file-url]: LICENSE
|
|
540
555
|
[github-url]: https://github.com/cachekit-io/cachekit-py
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
> **Python caching, batteries included**
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
Backend-agnostic caching with intent-based decorators — circuit breaker, distributed locking, Prometheus metrics, and optional zero-knowledge encryption on a Rust-powered core. Zero config to start, any backend when you scale.
|
|
8
8
|
|
|
9
9
|
[![PyPI Version][pypi-badge]][pypi-url]
|
|
10
10
|
[![Python Versions][python-badge]][pypi-url]
|
|
@@ -15,20 +15,16 @@ Production-ready caching for Python with intelligent reliability features and Ru
|
|
|
15
15
|
|
|
16
16
|
---
|
|
17
17
|
|
|
18
|
-
> [!
|
|
19
|
-
> **
|
|
20
|
-
>
|
|
21
|
-
> 🐛 **Found a bug?** Please [open an issue][issues-url] — even small ones help us improve.
|
|
22
|
-
>
|
|
23
|
-
> 💡 **Something feel off?** We want to hear about rough edges, confusing APIs, or missing features.
|
|
18
|
+
> [!NOTE]
|
|
19
|
+
> **Status: beta** — CacheKit is in closed beta ahead of 1.0. APIs are stabilising; minor breaking changes may still occur between 0.x releases.
|
|
24
20
|
>
|
|
25
|
-
>
|
|
21
|
+
> 🐛 **Found a bug or a rough edge?** Please [open an issue][issues-url] — your feedback directly shapes the path to 1.0.
|
|
26
22
|
|
|
27
23
|
---
|
|
28
24
|
|
|
29
25
|
## Why cachekit?
|
|
30
26
|
|
|
31
|
-
**Simple to use,
|
|
27
|
+
**Simple to use, works out of the box.**
|
|
32
28
|
|
|
33
29
|
```python
|
|
34
30
|
from cachekit import cache
|
|
@@ -72,7 +68,7 @@ backend that fits your infrastructure — they're peers behind the same `@cache`
|
|
|
72
68
|
| Backend | Best for | Select with |
|
|
73
69
|
|---------|----------|-------------|
|
|
74
70
|
| Redis | Self-hosted, full control | `REDIS_URL` / `CACHEKIT_REDIS_URL` |
|
|
75
|
-
| CachekitIO | Managed, zero-ops (
|
|
71
|
+
| CachekitIO | Managed, zero-ops (beta) | `CACHEKIT_API_KEY` |
|
|
76
72
|
| Memcached | High-throughput, existing infra | `CACHEKIT_MEMCACHED_SERVERS` |
|
|
77
73
|
| File / L1-only | Local dev, tests, no external deps | `CACHEKIT_FILE_CACHE_DIR` / `backend=None` |
|
|
78
74
|
|
|
@@ -95,7 +91,7 @@ def expensive_api_call(user_id: int):
|
|
|
95
91
|
### More Backends
|
|
96
92
|
|
|
97
93
|
<details>
|
|
98
|
-
<summary><strong>CachekitIO — Managed SaaS (
|
|
94
|
+
<summary><strong>CachekitIO — Managed SaaS (Beta)</strong></summary>
|
|
99
95
|
|
|
100
96
|
```python notest
|
|
101
97
|
import os
|
|
@@ -109,7 +105,7 @@ def expensive_api_call(user_id: int):
|
|
|
109
105
|
return fetch_user_data(user_id)
|
|
110
106
|
```
|
|
111
107
|
|
|
112
|
-
*cachekit.io is in closed
|
|
108
|
+
*cachekit.io is in closed beta — [request access](https://cachekit.io) to get started.*
|
|
113
109
|
|
|
114
110
|
</details>
|
|
115
111
|
|
|
@@ -135,9 +131,9 @@ def expensive_api_call(user_id: int):
|
|
|
135
131
|
|
|
136
132
|
---
|
|
137
133
|
|
|
138
|
-
> **CachekitIO Cloud (
|
|
134
|
+
> **CachekitIO Cloud (Beta)**
|
|
139
135
|
> Managed caching with zero infrastructure. L1+L2 caching, circuit breaker, and automatic failover — no Redis to manage.
|
|
140
|
-
> *cachekit.io is in closed
|
|
136
|
+
> *cachekit.io is in closed beta — [request access](https://cachekit.io) to get started.*
|
|
141
137
|
|
|
142
138
|
---
|
|
143
139
|
|
|
@@ -168,9 +164,8 @@ def get_user_profile(user_id: int):
|
|
|
168
164
|
| Backpressure | ✅ | ✅ | - | ✅ | ✅ |
|
|
169
165
|
| Integrity Checking | - | ✅ | - | ✅ | ✅ 🔒 |
|
|
170
166
|
| Encryption | - | - | - | - | ✅ Required |
|
|
171
|
-
| L1 SWR | - | ✅ | - | ✅ | ✅ |
|
|
167
|
+
| L1 SWR (L1-only mode) | - | ✅ | - | ✅ | ✅ |
|
|
172
168
|
| L1 Invalidation | - | - | - | ✅ | ✅ |
|
|
173
|
-
| L1 Namespace Index | - | - | - | ✅ | ✅ |
|
|
174
169
|
| Prometheus Metrics | - | - | - | ✅ | ✅ |
|
|
175
170
|
| Tracing | - | ✅ | - | ✅ | ✅ |
|
|
176
171
|
| Structured Logging | - | ✅ | - | ✅ | ✅ |
|
|
@@ -178,6 +173,8 @@ def get_user_profile(user_id: int):
|
|
|
178
173
|
|
|
179
174
|
> 🔒 `@cache.secure` forces `integrity_checking=True` — it cannot be overridden.
|
|
180
175
|
>
|
|
176
|
+
> **L1 SWR** (within-TTL background refresh) runs only in L1-only mode (`backend=None`) — with a backend configured it has no effect. `@cache.io` additionally ships past-TTL SWR via `stale_ttl` ([docs](docs/configuration.md#stale-while-revalidate-stale_ttl)).
|
|
177
|
+
>
|
|
181
178
|
> **`@cache.io()`** mirrors `@cache.production` (full reliability + observability) but routes to the managed CachekitIO SaaS backend instead of Redis. **`@cache.local()`** is a separate in-process path backed by `ObjectCache` (raw object references, entry-count LRU, no serialization) — the reliability and encryption features listed above do not apply to it.
|
|
182
179
|
|
|
183
180
|
<details>
|
|
@@ -293,6 +290,12 @@ def get_patient_data(hospital_id: int):
|
|
|
293
290
|
> [!CAUTION]
|
|
294
291
|
> When handling PII, medical, or financial data, always use `@cache.secure` to enforce encryption.
|
|
295
292
|
|
|
293
|
+
**Zero-downtime key rotation**: promote a new `CACHEKIT_MASTER_KEY` and keep the
|
|
294
|
+
retiring key readable via `CACHEKIT_PREVIOUS_MASTER_KEYS` (comma-separated hex,
|
|
295
|
+
max 3 decrypt-only keys). Entries are selected by exact key fingerprint — never
|
|
296
|
+
trial decryption — and old entries age out via TTL, no cache flush required. See
|
|
297
|
+
[Zero-Knowledge Encryption](docs/features/zero-knowledge-encryption.md#key-rotation-pattern).
|
|
298
|
+
|
|
296
299
|
cachekit employs comprehensive security tooling:
|
|
297
300
|
|
|
298
301
|
- **Supply Chain Security**: cargo-deny for license compliance + RustSec scanning
|
|
@@ -390,6 +393,7 @@ info = expensive_func.cache_info()
|
|
|
390
393
|
| [Comparison Guide][comparison-url] | How cachekit compares to lru_cache, aiocache, cachetools |
|
|
391
394
|
| [Getting Started][getting-started-url] | Progressive tutorial from basics to advanced |
|
|
392
395
|
| [API Reference][api-reference-url] | Complete API documentation |
|
|
396
|
+
| [Skyline (live example)][skyline-url] | Canonical example project: this SDK ingests the Bluesky firehose and writes the analytics entries a TypeScript edge Worker serves live, on one shared interop namespace |
|
|
393
397
|
|
|
394
398
|
### Feature Deep Dives
|
|
395
399
|
|
|
@@ -400,6 +404,11 @@ info = expensive_func.cache_info()
|
|
|
400
404
|
| [Distributed Locking][distributed-locking-url] | Cache stampede prevention |
|
|
401
405
|
| [Prometheus Metrics][prometheus-url] | Built-in observability |
|
|
402
406
|
| [Zero-Knowledge Encryption][encryption-url] | Client-side security |
|
|
407
|
+
| [Interop Mode][interop-url] | Cross-SDK cache sharing with cachekit-ts/rs |
|
|
408
|
+
| [L1 Invalidation & SWR][l1-invalidation-url] | Process-local invalidation, stale-while-revalidate |
|
|
409
|
+
| [Reference Caching][reference-caching-url] | `@cache.local()` for non-serializable objects |
|
|
410
|
+
| [Rust Serialization][rust-serialization-url] | ByteStorage layer: LZ4, xxHash3, AES-256-GCM |
|
|
411
|
+
| [SSRF Protection][ssrf-url] | URL allowlisting for the CachekitIO backend |
|
|
403
412
|
|
|
404
413
|
---
|
|
405
414
|
|
|
@@ -412,7 +421,7 @@ info = expensive_func.cache_info()
|
|
|
412
421
|
CACHEKIT_REDIS_URL="redis://localhost:6379" # Primary (preferred)
|
|
413
422
|
REDIS_URL="redis://localhost:6379" # Fallback
|
|
414
423
|
|
|
415
|
-
# CachekitIO SaaS Backend (closed
|
|
424
|
+
# CachekitIO SaaS Backend (closed beta — request access at cachekit.io)
|
|
416
425
|
CACHEKIT_API_KEY="your-api-key" # Required for @cache.io() # pragma: allowlist secret
|
|
417
426
|
CACHEKIT_API_URL="https://api.cachekit.io" # Default SaaS endpoint
|
|
418
427
|
|
|
@@ -475,6 +484,7 @@ MIT License - see [LICENSE][license-file-url] for details.
|
|
|
475
484
|
[uv-url]: https://github.com/astral-sh/uv
|
|
476
485
|
[security-url]: SECURITY.md
|
|
477
486
|
[comparison-url]: docs/comparison.md
|
|
487
|
+
[skyline-url]: https://github.com/cachekit-io/bluesky-thinking
|
|
478
488
|
[getting-started-url]: docs/getting-started.md
|
|
479
489
|
[api-reference-url]: docs/api-reference.md
|
|
480
490
|
[serializer-guide-url]: docs/serializers/index.md
|
|
@@ -482,6 +492,11 @@ MIT License - see [LICENSE][license-file-url] for details.
|
|
|
482
492
|
[distributed-locking-url]: docs/features/distributed-locking.md
|
|
483
493
|
[prometheus-url]: docs/features/prometheus-metrics.md
|
|
484
494
|
[encryption-url]: docs/features/zero-knowledge-encryption.md
|
|
495
|
+
[interop-url]: docs/features/interop-mode.md
|
|
496
|
+
[l1-invalidation-url]: docs/features/l1-invalidation.md
|
|
497
|
+
[reference-caching-url]: docs/features/reference-caching.md
|
|
498
|
+
[rust-serialization-url]: docs/features/rust-serialization.md
|
|
499
|
+
[ssrf-url]: docs/features/ssrf-protection.md
|
|
485
500
|
[contributing-url]: CONTRIBUTING.md
|
|
486
501
|
[license-file-url]: LICENSE
|
|
487
502
|
[github-url]: https://github.com/cachekit-io/cachekit-py
|
|
@@ -4,8 +4,8 @@ build-backend = "maturin"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "cachekit"
|
|
7
|
-
version = "0.
|
|
8
|
-
description = "
|
|
7
|
+
version = "0.18.0"
|
|
8
|
+
description = "Backend-agnostic caching for Python — intent-based decorators with circuit breaker, distributed locking, Prometheus metrics, and optional zero-knowledge AES-256-GCM encryption, on a Rust-powered core. Zero-config L1 in-memory; scales to Redis, Memcached, File, or CachekitIO."
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = {text = "MIT"}
|
|
11
11
|
authors = [
|
|
@@ -31,7 +31,7 @@ keywords = [
|
|
|
31
31
|
"distributed-locking",
|
|
32
32
|
]
|
|
33
33
|
classifiers = [
|
|
34
|
-
"Development Status ::
|
|
34
|
+
"Development Status :: 4 - Beta",
|
|
35
35
|
"Intended Audience :: Developers",
|
|
36
36
|
"License :: OSI Approved :: MIT License",
|
|
37
37
|
"Operating System :: OS Independent",
|
|
@@ -56,7 +56,7 @@ dependencies = [
|
|
|
56
56
|
"redis[hiredis]>=4.0.0",
|
|
57
57
|
# Configuration and validation
|
|
58
58
|
"pydantic>=2.0.0",
|
|
59
|
-
"pydantic-settings>=2.
|
|
59
|
+
"pydantic-settings>=2.7.0", # NoDecode (previous_master_keys env parsing) first shipped in 2.7.0
|
|
60
60
|
# Monitoring and observability
|
|
61
61
|
"prometheus-client>=0.22.1",
|
|
62
62
|
"psutil>=7.0.0",
|
|
@@ -251,4 +251,8 @@ constraint-dependencies = [
|
|
|
251
251
|
# PYSEC-2026-196 (entry-point path traversal), GHSA-58qw-9mgm-455v (tar/zip
|
|
252
252
|
# confusion) and GHSA-jp4c-xjxw-mgf9 (self-update import ordering).
|
|
253
253
|
"pip>=26.1.2",
|
|
254
|
+
# h2 is a transitive dep (httpx[http2] -> h2). 4.4.1 fixes
|
|
255
|
+
# GHSA-6hr6-w5qg-qmwg (duplicate Host headers forwarded on HTTP/2 ->
|
|
256
|
+
# HTTP/1.1 downgrade — request smuggling primitive).
|
|
257
|
+
"h2>=4.4.1",
|
|
254
258
|
]
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[package]
|
|
2
2
|
name = "cachekit-rs"
|
|
3
|
-
version = "0.
|
|
3
|
+
version = "0.18.0"
|
|
4
4
|
edition = "2021"
|
|
5
5
|
authors = ["cachekit Contributors"]
|
|
6
6
|
description = "High-performance storage engine for caching with compression and encryption"
|
|
@@ -20,11 +20,15 @@ crate-type = ["cdylib", "rlib"]
|
|
|
20
20
|
|
|
21
21
|
[dependencies]
|
|
22
22
|
# Compression, checksums, encryption (https://crates.io/crates/cachekit-core)
|
|
23
|
-
cachekit-core = { version = "0.
|
|
23
|
+
cachekit-core = { version = "0.5.0", features = ["compression", "checksum", "messagepack", "encryption"] }
|
|
24
24
|
|
|
25
25
|
# Python integration - optional for Rust-only builds
|
|
26
26
|
pyo3 = { workspace = true, optional = true }
|
|
27
27
|
|
|
28
|
+
# Wipe the PyO3-side copies of master key material on drop. Only used behind
|
|
29
|
+
# the encryption feature, so gated the same way pyo3 is.
|
|
30
|
+
zeroize = { version = "1", optional = true }
|
|
31
|
+
|
|
28
32
|
# Feature flags
|
|
29
33
|
[features]
|
|
30
34
|
default = ["python", "compression", "checksum", "messagepack", "encryption"]
|
|
@@ -36,7 +40,7 @@ python = ["dep:pyo3"]
|
|
|
36
40
|
compression = []
|
|
37
41
|
checksum = []
|
|
38
42
|
messagepack = []
|
|
39
|
-
encryption = []
|
|
43
|
+
encryption = ["dep:zeroize"]
|
|
40
44
|
|
|
41
45
|
[dev-dependencies]
|
|
42
46
|
criterion = { version = "0.5", features = ["html_reports"] }
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
> **Python caching, batteries included**
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
Backend-agnostic caching with intent-based decorators — circuit breaker, distributed locking, Prometheus metrics, and optional zero-knowledge encryption on a Rust-powered core. Zero config to start, any backend when you scale.
|
|
8
8
|
|
|
9
9
|
[![PyPI Version][pypi-badge]][pypi-url]
|
|
10
10
|
[![Python Versions][python-badge]][pypi-url]
|
|
@@ -15,20 +15,16 @@ Production-ready caching for Python with intelligent reliability features and Ru
|
|
|
15
15
|
|
|
16
16
|
---
|
|
17
17
|
|
|
18
|
-
> [!
|
|
19
|
-
> **
|
|
20
|
-
>
|
|
21
|
-
> 🐛 **Found a bug?** Please [open an issue][issues-url] — even small ones help us improve.
|
|
22
|
-
>
|
|
23
|
-
> 💡 **Something feel off?** We want to hear about rough edges, confusing APIs, or missing features.
|
|
18
|
+
> [!NOTE]
|
|
19
|
+
> **Status: beta** — CacheKit is in closed beta ahead of 1.0. APIs are stabilising; minor breaking changes may still occur between 0.x releases.
|
|
24
20
|
>
|
|
25
|
-
>
|
|
21
|
+
> 🐛 **Found a bug or a rough edge?** Please [open an issue][issues-url] — your feedback directly shapes the path to 1.0.
|
|
26
22
|
|
|
27
23
|
---
|
|
28
24
|
|
|
29
25
|
## Why cachekit?
|
|
30
26
|
|
|
31
|
-
**Simple to use,
|
|
27
|
+
**Simple to use, works out of the box.**
|
|
32
28
|
|
|
33
29
|
```python
|
|
34
30
|
from cachekit import cache
|
|
@@ -72,7 +68,7 @@ backend that fits your infrastructure — they're peers behind the same `@cache`
|
|
|
72
68
|
| Backend | Best for | Select with |
|
|
73
69
|
|---------|----------|-------------|
|
|
74
70
|
| Redis | Self-hosted, full control | `REDIS_URL` / `CACHEKIT_REDIS_URL` |
|
|
75
|
-
| CachekitIO | Managed, zero-ops (
|
|
71
|
+
| CachekitIO | Managed, zero-ops (beta) | `CACHEKIT_API_KEY` |
|
|
76
72
|
| Memcached | High-throughput, existing infra | `CACHEKIT_MEMCACHED_SERVERS` |
|
|
77
73
|
| File / L1-only | Local dev, tests, no external deps | `CACHEKIT_FILE_CACHE_DIR` / `backend=None` |
|
|
78
74
|
|
|
@@ -95,7 +91,7 @@ def expensive_api_call(user_id: int):
|
|
|
95
91
|
### More Backends
|
|
96
92
|
|
|
97
93
|
<details>
|
|
98
|
-
<summary><strong>CachekitIO — Managed SaaS (
|
|
94
|
+
<summary><strong>CachekitIO — Managed SaaS (Beta)</strong></summary>
|
|
99
95
|
|
|
100
96
|
```python notest
|
|
101
97
|
import os
|
|
@@ -109,7 +105,7 @@ def expensive_api_call(user_id: int):
|
|
|
109
105
|
return fetch_user_data(user_id)
|
|
110
106
|
```
|
|
111
107
|
|
|
112
|
-
*cachekit.io is in closed
|
|
108
|
+
*cachekit.io is in closed beta — [request access](https://cachekit.io) to get started.*
|
|
113
109
|
|
|
114
110
|
</details>
|
|
115
111
|
|
|
@@ -135,9 +131,9 @@ def expensive_api_call(user_id: int):
|
|
|
135
131
|
|
|
136
132
|
---
|
|
137
133
|
|
|
138
|
-
> **CachekitIO Cloud (
|
|
134
|
+
> **CachekitIO Cloud (Beta)**
|
|
139
135
|
> Managed caching with zero infrastructure. L1+L2 caching, circuit breaker, and automatic failover — no Redis to manage.
|
|
140
|
-
> *cachekit.io is in closed
|
|
136
|
+
> *cachekit.io is in closed beta — [request access](https://cachekit.io) to get started.*
|
|
141
137
|
|
|
142
138
|
---
|
|
143
139
|
|
|
@@ -168,9 +164,8 @@ def get_user_profile(user_id: int):
|
|
|
168
164
|
| Backpressure | ✅ | ✅ | - | ✅ | ✅ |
|
|
169
165
|
| Integrity Checking | - | ✅ | - | ✅ | ✅ 🔒 |
|
|
170
166
|
| Encryption | - | - | - | - | ✅ Required |
|
|
171
|
-
| L1 SWR | - | ✅ | - | ✅ | ✅ |
|
|
167
|
+
| L1 SWR (L1-only mode) | - | ✅ | - | ✅ | ✅ |
|
|
172
168
|
| L1 Invalidation | - | - | - | ✅ | ✅ |
|
|
173
|
-
| L1 Namespace Index | - | - | - | ✅ | ✅ |
|
|
174
169
|
| Prometheus Metrics | - | - | - | ✅ | ✅ |
|
|
175
170
|
| Tracing | - | ✅ | - | ✅ | ✅ |
|
|
176
171
|
| Structured Logging | - | ✅ | - | ✅ | ✅ |
|
|
@@ -178,6 +173,8 @@ def get_user_profile(user_id: int):
|
|
|
178
173
|
|
|
179
174
|
> 🔒 `@cache.secure` forces `integrity_checking=True` — it cannot be overridden.
|
|
180
175
|
>
|
|
176
|
+
> **L1 SWR** (within-TTL background refresh) runs only in L1-only mode (`backend=None`) — with a backend configured it has no effect. `@cache.io` additionally ships past-TTL SWR via `stale_ttl` ([docs](docs/configuration.md#stale-while-revalidate-stale_ttl)).
|
|
177
|
+
>
|
|
181
178
|
> **`@cache.io()`** mirrors `@cache.production` (full reliability + observability) but routes to the managed CachekitIO SaaS backend instead of Redis. **`@cache.local()`** is a separate in-process path backed by `ObjectCache` (raw object references, entry-count LRU, no serialization) — the reliability and encryption features listed above do not apply to it.
|
|
182
179
|
|
|
183
180
|
<details>
|
|
@@ -293,6 +290,12 @@ def get_patient_data(hospital_id: int):
|
|
|
293
290
|
> [!CAUTION]
|
|
294
291
|
> When handling PII, medical, or financial data, always use `@cache.secure` to enforce encryption.
|
|
295
292
|
|
|
293
|
+
**Zero-downtime key rotation**: promote a new `CACHEKIT_MASTER_KEY` and keep the
|
|
294
|
+
retiring key readable via `CACHEKIT_PREVIOUS_MASTER_KEYS` (comma-separated hex,
|
|
295
|
+
max 3 decrypt-only keys). Entries are selected by exact key fingerprint — never
|
|
296
|
+
trial decryption — and old entries age out via TTL, no cache flush required. See
|
|
297
|
+
[Zero-Knowledge Encryption](docs/features/zero-knowledge-encryption.md#key-rotation-pattern).
|
|
298
|
+
|
|
296
299
|
cachekit employs comprehensive security tooling:
|
|
297
300
|
|
|
298
301
|
- **Supply Chain Security**: cargo-deny for license compliance + RustSec scanning
|
|
@@ -390,6 +393,7 @@ info = expensive_func.cache_info()
|
|
|
390
393
|
| [Comparison Guide][comparison-url] | How cachekit compares to lru_cache, aiocache, cachetools |
|
|
391
394
|
| [Getting Started][getting-started-url] | Progressive tutorial from basics to advanced |
|
|
392
395
|
| [API Reference][api-reference-url] | Complete API documentation |
|
|
396
|
+
| [Skyline (live example)][skyline-url] | Canonical example project: this SDK ingests the Bluesky firehose and writes the analytics entries a TypeScript edge Worker serves live, on one shared interop namespace |
|
|
393
397
|
|
|
394
398
|
### Feature Deep Dives
|
|
395
399
|
|
|
@@ -400,6 +404,11 @@ info = expensive_func.cache_info()
|
|
|
400
404
|
| [Distributed Locking][distributed-locking-url] | Cache stampede prevention |
|
|
401
405
|
| [Prometheus Metrics][prometheus-url] | Built-in observability |
|
|
402
406
|
| [Zero-Knowledge Encryption][encryption-url] | Client-side security |
|
|
407
|
+
| [Interop Mode][interop-url] | Cross-SDK cache sharing with cachekit-ts/rs |
|
|
408
|
+
| [L1 Invalidation & SWR][l1-invalidation-url] | Process-local invalidation, stale-while-revalidate |
|
|
409
|
+
| [Reference Caching][reference-caching-url] | `@cache.local()` for non-serializable objects |
|
|
410
|
+
| [Rust Serialization][rust-serialization-url] | ByteStorage layer: LZ4, xxHash3, AES-256-GCM |
|
|
411
|
+
| [SSRF Protection][ssrf-url] | URL allowlisting for the CachekitIO backend |
|
|
403
412
|
|
|
404
413
|
---
|
|
405
414
|
|
|
@@ -412,7 +421,7 @@ info = expensive_func.cache_info()
|
|
|
412
421
|
CACHEKIT_REDIS_URL="redis://localhost:6379" # Primary (preferred)
|
|
413
422
|
REDIS_URL="redis://localhost:6379" # Fallback
|
|
414
423
|
|
|
415
|
-
# CachekitIO SaaS Backend (closed
|
|
424
|
+
# CachekitIO SaaS Backend (closed beta — request access at cachekit.io)
|
|
416
425
|
CACHEKIT_API_KEY="your-api-key" # Required for @cache.io() # pragma: allowlist secret
|
|
417
426
|
CACHEKIT_API_URL="https://api.cachekit.io" # Default SaaS endpoint
|
|
418
427
|
|
|
@@ -475,6 +484,7 @@ MIT License - see [LICENSE][license-file-url] for details.
|
|
|
475
484
|
[uv-url]: https://github.com/astral-sh/uv
|
|
476
485
|
[security-url]: SECURITY.md
|
|
477
486
|
[comparison-url]: docs/comparison.md
|
|
487
|
+
[skyline-url]: https://github.com/cachekit-io/bluesky-thinking
|
|
478
488
|
[getting-started-url]: docs/getting-started.md
|
|
479
489
|
[api-reference-url]: docs/api-reference.md
|
|
480
490
|
[serializer-guide-url]: docs/serializers/index.md
|
|
@@ -482,6 +492,11 @@ MIT License - see [LICENSE][license-file-url] for details.
|
|
|
482
492
|
[distributed-locking-url]: docs/features/distributed-locking.md
|
|
483
493
|
[prometheus-url]: docs/features/prometheus-metrics.md
|
|
484
494
|
[encryption-url]: docs/features/zero-knowledge-encryption.md
|
|
495
|
+
[interop-url]: docs/features/interop-mode.md
|
|
496
|
+
[l1-invalidation-url]: docs/features/l1-invalidation.md
|
|
497
|
+
[reference-caching-url]: docs/features/reference-caching.md
|
|
498
|
+
[rust-serialization-url]: docs/features/rust-serialization.md
|
|
499
|
+
[ssrf-url]: docs/features/ssrf-protection.md
|
|
485
500
|
[contributing-url]: CONTRIBUTING.md
|
|
486
501
|
[license-file-url]: LICENSE
|
|
487
502
|
[github-url]: https://github.com/cachekit-io/cachekit-py
|
|
@@ -9,11 +9,8 @@ pub use cachekit_core::{ByteStorage, OperationMetrics, StorageEnvelope};
|
|
|
9
9
|
#[cfg(feature = "encryption")]
|
|
10
10
|
pub use cachekit_core::{
|
|
11
11
|
derive_domain_key,
|
|
12
|
-
encryption::{
|
|
13
|
-
|
|
14
|
-
key_rotation::KeyRotationState,
|
|
15
|
-
},
|
|
16
|
-
EncryptionError, ZeroKnowledgeEncryptor,
|
|
12
|
+
encryption::key_derivation::{derive_tenant_keys, key_fingerprint, TenantKeys},
|
|
13
|
+
EncryptionError, Keyring, ZeroKnowledgeEncryptor,
|
|
17
14
|
};
|
|
18
15
|
|
|
19
16
|
// Python bindings (gated behind python feature)
|