cachekit 0.24.1__tar.gz → 0.25.1__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.24.1 → cachekit-0.25.1}/Cargo.lock +9 -182
- {cachekit-0.24.1 → cachekit-0.25.1}/PKG-INFO +49 -23
- {cachekit-0.24.1 → cachekit-0.25.1}/README.md +46 -19
- {cachekit-0.24.1 → cachekit-0.25.1}/pyproject.toml +21 -11
- {cachekit-0.24.1 → cachekit-0.25.1}/rust/Cargo.toml +3 -3
- {cachekit-0.24.1 → cachekit-0.25.1}/rust/Makefile +12 -12
- {cachekit-0.24.1 → cachekit-0.25.1}/rust/README.md +46 -19
- cachekit-0.25.1/rust/src/hit_counter.rs +164 -0
- {cachekit-0.24.1 → cachekit-0.25.1}/rust/src/lib.rs +19 -10
- {cachekit-0.24.1 → cachekit-0.25.1}/rust/src/python_bindings.rs +156 -49
- {cachekit-0.24.1 → cachekit-0.25.1}/src/cachekit/__init__.py +12 -1
- {cachekit-0.24.1 → cachekit-0.25.1}/src/cachekit/backends/base.py +1 -1
- {cachekit-0.24.1 → cachekit-0.25.1}/src/cachekit/backends/cachekitio/backend.py +14 -15
- {cachekit-0.24.1 → cachekit-0.25.1}/src/cachekit/backends/errors.py +2 -2
- {cachekit-0.24.1 → cachekit-0.25.1}/src/cachekit/backends/file/backend.py +5 -5
- {cachekit-0.24.1 → cachekit-0.25.1}/src/cachekit/backends/provider.py +2 -3
- {cachekit-0.24.1 → cachekit-0.25.1}/src/cachekit/backends/redis/backend.py +2 -2
- {cachekit-0.24.1 → cachekit-0.25.1}/src/cachekit/backends/redis/client.py +3 -3
- {cachekit-0.24.1 → cachekit-0.25.1}/src/cachekit/backends/redis/provider.py +110 -44
- {cachekit-0.24.1 → cachekit-0.25.1}/src/cachekit/cache_handler.py +254 -66
- {cachekit-0.24.1 → cachekit-0.25.1}/src/cachekit/config/decorator.py +19 -7
- {cachekit-0.24.1 → cachekit-0.25.1}/src/cachekit/config/nested.py +93 -30
- {cachekit-0.24.1 → cachekit-0.25.1}/src/cachekit/config/settings.py +8 -8
- {cachekit-0.24.1 → cachekit-0.25.1}/src/cachekit/config/validation.py +4 -7
- {cachekit-0.24.1 → cachekit-0.25.1}/src/cachekit/decorators/intent.py +7 -7
- {cachekit-0.24.1 → cachekit-0.25.1}/src/cachekit/decorators/local_wrapper.py +3 -3
- {cachekit-0.24.1 → cachekit-0.25.1}/src/cachekit/decorators/single_flight.py +17 -8
- {cachekit-0.24.1 → cachekit-0.25.1}/src/cachekit/decorators/wrapper.py +781 -315
- cachekit-0.25.1/src/cachekit/decorators/write_behind.py +261 -0
- {cachekit-0.24.1 → cachekit-0.25.1}/src/cachekit/health.py +40 -36
- {cachekit-0.24.1 → cachekit-0.25.1}/src/cachekit/interop.py +5 -18
- {cachekit-0.24.1 → cachekit-0.25.1}/src/cachekit/key_generator.py +7 -7
- {cachekit-0.24.1 → cachekit-0.25.1}/src/cachekit/l1_cache.py +54 -15
- {cachekit-0.24.1 → cachekit-0.25.1}/src/cachekit/logging.py +1 -1
- {cachekit-0.24.1 → cachekit-0.25.1}/src/cachekit/monitoring/protocols.py +11 -19
- {cachekit-0.24.1 → cachekit-0.25.1}/src/cachekit/object_cache.py +64 -20
- {cachekit-0.24.1 → cachekit-0.25.1}/src/cachekit/reliability/async_metrics.py +451 -160
- {cachekit-0.24.1 → cachekit-0.25.1}/src/cachekit/reliability/circuit_breaker.py +28 -25
- {cachekit-0.24.1 → cachekit-0.25.1}/src/cachekit/serializers/__init__.py +1 -2
- {cachekit-0.24.1 → cachekit-0.25.1}/src/cachekit/serializers/arrow_serializer.py +4 -4
- {cachekit-0.24.1 → cachekit-0.25.1}/src/cachekit/serializers/auto_serializer.py +15 -14
- {cachekit-0.24.1 → cachekit-0.25.1}/src/cachekit/serializers/base.py +16 -14
- {cachekit-0.24.1 → cachekit-0.25.1}/src/cachekit/serializers/encryption_wrapper.py +81 -63
- {cachekit-0.24.1 → cachekit-0.25.1}/src/cachekit/serializers/orjson_serializer.py +1 -1
- {cachekit-0.24.1 → cachekit-0.25.1}/src/cachekit/serializers/standard_serializer.py +59 -8
- {cachekit-0.24.1 → cachekit-0.25.1}/src/cachekit/serializers/wrapper.py +2 -2
- cachekit-0.24.1/rust/src/msgpack_bounds.rs +0 -87
- {cachekit-0.24.1 → cachekit-0.25.1}/Cargo.toml +0 -0
- {cachekit-0.24.1 → cachekit-0.25.1}/LICENSE +0 -0
- {cachekit-0.24.1 → cachekit-0.25.1}/rust/TEST_EXPANSION_SUMMARY.md +0 -0
- {cachekit-0.24.1 → cachekit-0.25.1}/rust/tsan_suppressions.txt +0 -0
- {cachekit-0.24.1 → cachekit-0.25.1}/src/cachekit/_fork.py +0 -0
- {cachekit-0.24.1 → cachekit-0.25.1}/src/cachekit/backends/__init__.py +0 -0
- {cachekit-0.24.1 → cachekit-0.25.1}/src/cachekit/backends/_uninterrupted.py +0 -0
- {cachekit-0.24.1 → cachekit-0.25.1}/src/cachekit/backends/base_config.py +0 -0
- {cachekit-0.24.1 → cachekit-0.25.1}/src/cachekit/backends/cachekitio/__init__.py +0 -0
- {cachekit-0.24.1 → cachekit-0.25.1}/src/cachekit/backends/cachekitio/client.py +0 -0
- {cachekit-0.24.1 → cachekit-0.25.1}/src/cachekit/backends/cachekitio/config.py +0 -0
- {cachekit-0.24.1 → cachekit-0.25.1}/src/cachekit/backends/cachekitio/error_handler.py +0 -0
- {cachekit-0.24.1 → cachekit-0.25.1}/src/cachekit/backends/cachekitio/session.py +0 -0
- {cachekit-0.24.1 → cachekit-0.25.1}/src/cachekit/backends/file/__init__.py +0 -0
- {cachekit-0.24.1 → cachekit-0.25.1}/src/cachekit/backends/file/config.py +0 -0
- {cachekit-0.24.1 → cachekit-0.25.1}/src/cachekit/backends/memcached/__init__.py +0 -0
- {cachekit-0.24.1 → cachekit-0.25.1}/src/cachekit/backends/memcached/backend.py +0 -0
- {cachekit-0.24.1 → cachekit-0.25.1}/src/cachekit/backends/memcached/config.py +0 -0
- {cachekit-0.24.1 → cachekit-0.25.1}/src/cachekit/backends/memcached/error_handler.py +0 -0
- {cachekit-0.24.1 → cachekit-0.25.1}/src/cachekit/backends/redis/__init__.py +0 -0
- {cachekit-0.24.1 → cachekit-0.25.1}/src/cachekit/backends/redis/config.py +0 -0
- {cachekit-0.24.1 → cachekit-0.25.1}/src/cachekit/backends/redis/error_handler.py +0 -0
- {cachekit-0.24.1 → cachekit-0.25.1}/src/cachekit/config/__init__.py +0 -0
- {cachekit-0.24.1 → cachekit-0.25.1}/src/cachekit/config/singleton.py +0 -0
- {cachekit-0.24.1 → cachekit-0.25.1}/src/cachekit/decorators/__init__.py +0 -0
- {cachekit-0.24.1 → cachekit-0.25.1}/src/cachekit/decorators/main.py +0 -0
- {cachekit-0.24.1 → cachekit-0.25.1}/src/cachekit/decorators/orchestrator.py +0 -0
- {cachekit-0.24.1 → cachekit-0.25.1}/src/cachekit/decorators/session.py +0 -0
- {cachekit-0.24.1 → cachekit-0.25.1}/src/cachekit/decorators/stats_context.py +0 -0
- {cachekit-0.24.1 → cachekit-0.25.1}/src/cachekit/decorators/tenant_context.py +0 -0
- {cachekit-0.24.1 → cachekit-0.25.1}/src/cachekit/decorators/utils/__init__.py +0 -0
- {cachekit-0.24.1 → cachekit-0.25.1}/src/cachekit/di.py +0 -0
- {cachekit-0.24.1 → cachekit-0.25.1}/src/cachekit/hash_utils.py +0 -0
- {cachekit-0.24.1 → cachekit-0.25.1}/src/cachekit/hiredis_compat.py +0 -0
- {cachekit-0.24.1 → cachekit-0.25.1}/src/cachekit/imports.py +0 -0
- {cachekit-0.24.1 → cachekit-0.25.1}/src/cachekit/invalidation.py +0 -0
- {cachekit-0.24.1 → cachekit-0.25.1}/src/cachekit/monitoring/__init__.py +0 -0
- {cachekit-0.24.1 → cachekit-0.25.1}/src/cachekit/py.typed +0 -0
- {cachekit-0.24.1 → cachekit-0.25.1}/src/cachekit/reliability/__init__.py +0 -0
- {cachekit-0.24.1 → cachekit-0.25.1}/src/cachekit/reliability/error_classification.py +0 -0
- {cachekit-0.24.1 → cachekit-0.25.1}/src/cachekit/reliability/load_control.py +0 -0
- {cachekit-0.24.1 → cachekit-0.25.1}/src/cachekit/reliability/metrics_collection.py +0 -0
- {cachekit-0.24.1 → cachekit-0.25.1}/src/cachekit/serializers/interop_serializer.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# This file is automatically @generated by Cargo.
|
|
2
2
|
# It is not intended for manual editing.
|
|
3
|
-
version =
|
|
3
|
+
version = 4
|
|
4
4
|
|
|
5
5
|
[[package]]
|
|
6
6
|
name = "addr2line"
|
|
@@ -100,56 +100,12 @@ version = "0.1.6"
|
|
|
100
100
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
101
101
|
checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299"
|
|
102
102
|
|
|
103
|
-
[[package]]
|
|
104
|
-
name = "anstream"
|
|
105
|
-
version = "1.0.0"
|
|
106
|
-
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
107
|
-
checksum = "824a212faf96e9acacdbd09febd34438f8f711fb84e09a8916013cd7815ca28d"
|
|
108
|
-
dependencies = [
|
|
109
|
-
"anstyle",
|
|
110
|
-
"anstyle-parse",
|
|
111
|
-
"anstyle-query",
|
|
112
|
-
"anstyle-wincon",
|
|
113
|
-
"colorchoice",
|
|
114
|
-
"is_terminal_polyfill",
|
|
115
|
-
"utf8parse",
|
|
116
|
-
]
|
|
117
|
-
|
|
118
103
|
[[package]]
|
|
119
104
|
name = "anstyle"
|
|
120
105
|
version = "1.0.14"
|
|
121
106
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
122
107
|
checksum = "940b3a0ca603d1eade50a4846a2afffd5ef57a9feac2c0e2ec2e14f9ead76000"
|
|
123
108
|
|
|
124
|
-
[[package]]
|
|
125
|
-
name = "anstyle-parse"
|
|
126
|
-
version = "1.0.0"
|
|
127
|
-
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
128
|
-
checksum = "52ce7f38b242319f7cabaa6813055467063ecdc9d355bbb4ce0c68908cd8130e"
|
|
129
|
-
dependencies = [
|
|
130
|
-
"utf8parse",
|
|
131
|
-
]
|
|
132
|
-
|
|
133
|
-
[[package]]
|
|
134
|
-
name = "anstyle-query"
|
|
135
|
-
version = "1.1.5"
|
|
136
|
-
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
137
|
-
checksum = "40c48f72fd53cd289104fc64099abca73db4166ad86ea0b4341abe65af83dadc"
|
|
138
|
-
dependencies = [
|
|
139
|
-
"windows-sys 0.60.2",
|
|
140
|
-
]
|
|
141
|
-
|
|
142
|
-
[[package]]
|
|
143
|
-
name = "anstyle-wincon"
|
|
144
|
-
version = "3.0.11"
|
|
145
|
-
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
146
|
-
checksum = "291e6a250ff86cd4a820112fb8898808a366d8f9f58ce16d1f538353ad55747d"
|
|
147
|
-
dependencies = [
|
|
148
|
-
"anstyle",
|
|
149
|
-
"once_cell_polyfill",
|
|
150
|
-
"windows-sys 0.60.2",
|
|
151
|
-
]
|
|
152
|
-
|
|
153
109
|
[[package]]
|
|
154
110
|
name = "anyhow"
|
|
155
111
|
version = "1.0.102"
|
|
@@ -240,29 +196,14 @@ version = "1.25.0"
|
|
|
240
196
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
241
197
|
checksum = "c8efb64bd706a16a1bdde310ae86b351e4d21550d98d056f22f8a7f7a2183fec"
|
|
242
198
|
|
|
243
|
-
[[package]]
|
|
244
|
-
name = "byteorder"
|
|
245
|
-
version = "1.5.0"
|
|
246
|
-
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
247
|
-
checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
|
|
248
|
-
|
|
249
|
-
[[package]]
|
|
250
|
-
name = "bytes"
|
|
251
|
-
version = "1.11.1"
|
|
252
|
-
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
253
|
-
checksum = "1e748733b7cbc798e1434b6ac524f0c1ff2ab456fe201501e6497c8417a4fc33"
|
|
254
|
-
|
|
255
199
|
[[package]]
|
|
256
200
|
name = "cachekit-core"
|
|
257
|
-
version = "0.
|
|
201
|
+
version = "0.7.2"
|
|
258
202
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
259
|
-
checksum = "
|
|
203
|
+
checksum = "101672176881ef05b17e8399476eb6fc2082e6a5c33788c84c9bb4d1a8d512d7"
|
|
260
204
|
dependencies = [
|
|
261
205
|
"aes",
|
|
262
206
|
"aes-gcm",
|
|
263
|
-
"byteorder",
|
|
264
|
-
"bytes",
|
|
265
|
-
"cbindgen",
|
|
266
207
|
"generic-array",
|
|
267
208
|
"getrandom 0.2.17",
|
|
268
209
|
"hkdf",
|
|
@@ -280,7 +221,7 @@ dependencies = [
|
|
|
280
221
|
|
|
281
222
|
[[package]]
|
|
282
223
|
name = "cachekit-rs"
|
|
283
|
-
version = "0.
|
|
224
|
+
version = "0.25.1"
|
|
284
225
|
dependencies = [
|
|
285
226
|
"cachekit-core",
|
|
286
227
|
"criterion 0.8.2",
|
|
@@ -300,25 +241,6 @@ version = "0.3.0"
|
|
|
300
241
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
301
242
|
checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5"
|
|
302
243
|
|
|
303
|
-
[[package]]
|
|
304
|
-
name = "cbindgen"
|
|
305
|
-
version = "0.29.2"
|
|
306
|
-
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
307
|
-
checksum = "befbfd072a8e81c02f8c507aefce431fe5e7d051f83d48a23ffc9b9fe5a11799"
|
|
308
|
-
dependencies = [
|
|
309
|
-
"clap",
|
|
310
|
-
"heck",
|
|
311
|
-
"indexmap",
|
|
312
|
-
"log",
|
|
313
|
-
"proc-macro2",
|
|
314
|
-
"quote",
|
|
315
|
-
"serde",
|
|
316
|
-
"serde_json",
|
|
317
|
-
"syn",
|
|
318
|
-
"tempfile",
|
|
319
|
-
"toml",
|
|
320
|
-
]
|
|
321
|
-
|
|
322
244
|
[[package]]
|
|
323
245
|
name = "cc"
|
|
324
246
|
version = "1.2.57"
|
|
@@ -387,10 +309,8 @@ version = "4.6.0"
|
|
|
387
309
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
388
310
|
checksum = "714a53001bf66416adb0e2ef5ac857140e7dc3a0c48fb28b2f10762fc4b5069f"
|
|
389
311
|
dependencies = [
|
|
390
|
-
"anstream",
|
|
391
312
|
"anstyle",
|
|
392
313
|
"clap_lex",
|
|
393
|
-
"strsim",
|
|
394
314
|
"terminal_size",
|
|
395
315
|
]
|
|
396
316
|
|
|
@@ -400,12 +320,6 @@ version = "1.1.0"
|
|
|
400
320
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
401
321
|
checksum = "c8d4a3bb8b1e0c1050499d1815f5ab16d04f0959b233085fb31653fbfc9d98f9"
|
|
402
322
|
|
|
403
|
-
[[package]]
|
|
404
|
-
name = "colorchoice"
|
|
405
|
-
version = "1.0.5"
|
|
406
|
-
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
407
|
-
checksum = "1d07550c9036bf2ae0c684c4297d503f838287c83c53686d05370d0e139ae570"
|
|
408
|
-
|
|
409
323
|
[[package]]
|
|
410
324
|
name = "condtype"
|
|
411
325
|
version = "1.3.0"
|
|
@@ -667,7 +581,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
|
667
581
|
checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb"
|
|
668
582
|
dependencies = [
|
|
669
583
|
"libc",
|
|
670
|
-
"windows-sys 0.
|
|
584
|
+
"windows-sys 0.61.2",
|
|
671
585
|
]
|
|
672
586
|
|
|
673
587
|
[[package]]
|
|
@@ -888,15 +802,9 @@ checksum = "3640c1c38b8e4e43584d8df18be5fc6b0aa314ce6ebf51b53313d4306cca8e46"
|
|
|
888
802
|
dependencies = [
|
|
889
803
|
"hermit-abi",
|
|
890
804
|
"libc",
|
|
891
|
-
"windows-sys 0.
|
|
805
|
+
"windows-sys 0.61.2",
|
|
892
806
|
]
|
|
893
807
|
|
|
894
|
-
[[package]]
|
|
895
|
-
name = "is_terminal_polyfill"
|
|
896
|
-
version = "1.70.2"
|
|
897
|
-
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
898
|
-
checksum = "a6cb138bb79a146c1bd460005623e142ef0181e3d0219cb493e02f7d08a35695"
|
|
899
|
-
|
|
900
808
|
[[package]]
|
|
901
809
|
name = "itertools"
|
|
902
810
|
version = "0.10.5"
|
|
@@ -987,9 +895,6 @@ name = "lz4_flex"
|
|
|
987
895
|
version = "0.12.2"
|
|
988
896
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
989
897
|
checksum = "90071f8077f8e40adfc4b7fe9cd495ce316263f19e75c2211eeff3fdf475a3d9"
|
|
990
|
-
dependencies = [
|
|
991
|
-
"twox-hash",
|
|
992
|
-
]
|
|
993
898
|
|
|
994
899
|
[[package]]
|
|
995
900
|
name = "memchr"
|
|
@@ -1060,12 +965,6 @@ version = "1.21.4"
|
|
|
1060
965
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
1061
966
|
checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50"
|
|
1062
967
|
|
|
1063
|
-
[[package]]
|
|
1064
|
-
name = "once_cell_polyfill"
|
|
1065
|
-
version = "1.70.2"
|
|
1066
|
-
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
1067
|
-
checksum = "384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4fe"
|
|
1068
|
-
|
|
1069
968
|
[[package]]
|
|
1070
969
|
name = "oorandom"
|
|
1071
970
|
version = "11.1.5"
|
|
@@ -1538,7 +1437,7 @@ dependencies = [
|
|
|
1538
1437
|
"errno",
|
|
1539
1438
|
"libc",
|
|
1540
1439
|
"linux-raw-sys 0.12.1",
|
|
1541
|
-
"windows-sys 0.
|
|
1440
|
+
"windows-sys 0.61.2",
|
|
1542
1441
|
]
|
|
1543
1442
|
|
|
1544
1443
|
[[package]]
|
|
@@ -1633,15 +1532,6 @@ dependencies = [
|
|
|
1633
1532
|
"zmij",
|
|
1634
1533
|
]
|
|
1635
1534
|
|
|
1636
|
-
[[package]]
|
|
1637
|
-
name = "serde_spanned"
|
|
1638
|
-
version = "1.0.4"
|
|
1639
|
-
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
1640
|
-
checksum = "f8bbf91e5a4d6315eee45e704372590b30e260ee83af6639d64557f51b067776"
|
|
1641
|
-
dependencies = [
|
|
1642
|
-
"serde_core",
|
|
1643
|
-
]
|
|
1644
|
-
|
|
1645
1535
|
[[package]]
|
|
1646
1536
|
name = "sha2"
|
|
1647
1537
|
version = "0.10.9"
|
|
@@ -1686,12 +1576,6 @@ version = "0.1.0"
|
|
|
1686
1576
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
1687
1577
|
checksum = "9091b6114800a5f2141aee1d1b9d6ca3592ac062dc5decb3764ec5895a47b4eb"
|
|
1688
1578
|
|
|
1689
|
-
[[package]]
|
|
1690
|
-
name = "strsim"
|
|
1691
|
-
version = "0.11.1"
|
|
1692
|
-
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
1693
|
-
checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
|
|
1694
|
-
|
|
1695
1579
|
[[package]]
|
|
1696
1580
|
name = "subtle"
|
|
1697
1581
|
version = "2.6.1"
|
|
@@ -1748,7 +1632,7 @@ dependencies = [
|
|
|
1748
1632
|
"getrandom 0.3.4",
|
|
1749
1633
|
"once_cell",
|
|
1750
1634
|
"rustix 1.1.4",
|
|
1751
|
-
"windows-sys 0.
|
|
1635
|
+
"windows-sys 0.61.2",
|
|
1752
1636
|
]
|
|
1753
1637
|
|
|
1754
1638
|
[[package]]
|
|
@@ -1811,51 +1695,6 @@ dependencies = [
|
|
|
1811
1695
|
"serde_json",
|
|
1812
1696
|
]
|
|
1813
1697
|
|
|
1814
|
-
[[package]]
|
|
1815
|
-
name = "toml"
|
|
1816
|
-
version = "0.9.12+spec-1.1.0"
|
|
1817
|
-
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
1818
|
-
checksum = "cf92845e79fc2e2def6a5d828f0801e29a2f8acc037becc5ab08595c7d5e9863"
|
|
1819
|
-
dependencies = [
|
|
1820
|
-
"indexmap",
|
|
1821
|
-
"serde_core",
|
|
1822
|
-
"serde_spanned",
|
|
1823
|
-
"toml_datetime",
|
|
1824
|
-
"toml_parser",
|
|
1825
|
-
"toml_writer",
|
|
1826
|
-
"winnow",
|
|
1827
|
-
]
|
|
1828
|
-
|
|
1829
|
-
[[package]]
|
|
1830
|
-
name = "toml_datetime"
|
|
1831
|
-
version = "0.7.5+spec-1.1.0"
|
|
1832
|
-
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
1833
|
-
checksum = "92e1cfed4a3038bc5a127e35a2d360f145e1f4b971b551a2ba5fd7aedf7e1347"
|
|
1834
|
-
dependencies = [
|
|
1835
|
-
"serde_core",
|
|
1836
|
-
]
|
|
1837
|
-
|
|
1838
|
-
[[package]]
|
|
1839
|
-
name = "toml_parser"
|
|
1840
|
-
version = "1.0.9+spec-1.1.0"
|
|
1841
|
-
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
1842
|
-
checksum = "702d4415e08923e7e1ef96cd5727c0dfed80b4d2fa25db9647fe5eb6f7c5a4c4"
|
|
1843
|
-
dependencies = [
|
|
1844
|
-
"winnow",
|
|
1845
|
-
]
|
|
1846
|
-
|
|
1847
|
-
[[package]]
|
|
1848
|
-
name = "toml_writer"
|
|
1849
|
-
version = "1.0.6+spec-1.1.0"
|
|
1850
|
-
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
1851
|
-
checksum = "ab16f14aed21ee8bfd8ec22513f7287cd4a91aa92e44edfe2c17ddd004e92607"
|
|
1852
|
-
|
|
1853
|
-
[[package]]
|
|
1854
|
-
name = "twox-hash"
|
|
1855
|
-
version = "2.1.2"
|
|
1856
|
-
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
1857
|
-
checksum = "9ea3136b675547379c4bd395ca6b938e5ad3c3d20fad76e7fe85f9e0d011419c"
|
|
1858
|
-
|
|
1859
1698
|
[[package]]
|
|
1860
1699
|
name = "typenum"
|
|
1861
1700
|
version = "1.19.0"
|
|
@@ -1890,12 +1729,6 @@ version = "0.9.0"
|
|
|
1890
1729
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
1891
1730
|
checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1"
|
|
1892
1731
|
|
|
1893
|
-
[[package]]
|
|
1894
|
-
name = "utf8parse"
|
|
1895
|
-
version = "0.2.2"
|
|
1896
|
-
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
1897
|
-
checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
|
|
1898
|
-
|
|
1899
1732
|
[[package]]
|
|
1900
1733
|
name = "uuid"
|
|
1901
1734
|
version = "1.22.0"
|
|
@@ -2035,7 +1868,7 @@ version = "0.1.11"
|
|
|
2035
1868
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
2036
1869
|
checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22"
|
|
2037
1870
|
dependencies = [
|
|
2038
|
-
"windows-sys 0.
|
|
1871
|
+
"windows-sys 0.61.2",
|
|
2039
1872
|
]
|
|
2040
1873
|
|
|
2041
1874
|
[[package]]
|
|
@@ -2215,12 +2048,6 @@ version = "0.53.1"
|
|
|
2215
2048
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
2216
2049
|
checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650"
|
|
2217
2050
|
|
|
2218
|
-
[[package]]
|
|
2219
|
-
name = "winnow"
|
|
2220
|
-
version = "0.7.15"
|
|
2221
|
-
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
2222
|
-
checksum = "df79d97927682d2fd8adb29682d1140b343be4ac0f08fd68b7765d9c059d3945"
|
|
2223
|
-
|
|
2224
2051
|
[[package]]
|
|
2225
2052
|
name = "wit-bindgen"
|
|
2226
2053
|
version = "0.51.0"
|
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: cachekit
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.25.1
|
|
4
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
|
|
8
8
|
Classifier: Programming Language :: Python :: 3
|
|
9
|
-
Classifier: Programming Language :: Python :: 3.10
|
|
10
9
|
Classifier: Programming Language :: Python :: 3.11
|
|
11
10
|
Classifier: Programming Language :: Python :: 3.12
|
|
12
11
|
Classifier: Programming Language :: Python :: 3.13
|
|
13
12
|
Classifier: Programming Language :: Python :: 3.14
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.15
|
|
14
14
|
Classifier: Programming Language :: Python :: Implementation :: CPython
|
|
15
15
|
Classifier: Programming Language :: Rust
|
|
16
16
|
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
@@ -24,7 +24,6 @@ Requires-Dist: redis[hiredis]>=4.6.0
|
|
|
24
24
|
Requires-Dist: pydantic>=2.0.0
|
|
25
25
|
Requires-Dist: pydantic-settings>=2.13.0
|
|
26
26
|
Requires-Dist: prometheus-client>=0.22.1
|
|
27
|
-
Requires-Dist: psutil>=7.0.0
|
|
28
27
|
Requires-Dist: blake3>=1.0.5
|
|
29
28
|
Requires-Dist: msgpack>=1.2.1
|
|
30
29
|
Requires-Dist: xxhash>=3.5.0
|
|
@@ -44,7 +43,7 @@ Home-Page: https://github.com/cachekit-io/cachekit-py
|
|
|
44
43
|
Author-email: cachekit Contributors <noreply@cachekit.io>
|
|
45
44
|
Maintainer-email: cachekit Contributors <noreply@cachekit.io>
|
|
46
45
|
License: MIT
|
|
47
|
-
Requires-Python: >=3.
|
|
46
|
+
Requires-Python: >=3.11
|
|
48
47
|
Description-Content-Type: text/markdown; charset=UTF-8; variant=GFM
|
|
49
48
|
Project-URL: Changelog, https://github.com/cachekit-io/cachekit-py/blob/main/CHANGELOG.md
|
|
50
49
|
Project-URL: Documentation, https://github.com/cachekit-io/cachekit-py#readme
|
|
@@ -297,9 +296,9 @@ def test_cached_function():
|
|
|
297
296
|
│ │ Breaker │ │ Timeouts │ │ Locking │ │
|
|
298
297
|
│ └─────────────┘ └─────────────┘ └─────────────────────┘ │
|
|
299
298
|
├─────────────────────────────────────────────────────────────┤
|
|
300
|
-
│ L1 Cache (In-Memory) │ L2 Cache (Pluggable Backend)
|
|
301
|
-
│
|
|
302
|
-
│ │ Memcached
|
|
299
|
+
│ L1 Cache (In-Memory) │ L2 Cache (Pluggable Backend) │
|
|
300
|
+
│ in-process │ Redis / CachekitIO / File / │
|
|
301
|
+
│ │ Memcached: one backend round trip │
|
|
303
302
|
├─────────────────────────────────────────────────────────────┤
|
|
304
303
|
│ Rust Core (PyO3) │
|
|
305
304
|
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────────────┐ │
|
|
@@ -314,12 +313,31 @@ def test_cached_function():
|
|
|
314
313
|
|
|
315
314
|
---
|
|
316
315
|
|
|
316
|
+
## Performance
|
|
317
|
+
|
|
318
|
+
What a call costs inside your process, from the wall-clock guards in `tests/performance/` run on a GitHub-hosted `ubuntu-latest` runner (AMD EPYC 7763, 4 vCPUs) with CPython 3.14.7. Each figure is the mean of five run medians with its 95% band.
|
|
319
|
+
|
|
320
|
+
| Path | Time per call |
|
|
321
|
+
|:-----|--------------:|
|
|
322
|
+
| `@cache(backend=None)` L1 hit, 100-user nested dict (23.5 KB as MessagePack) | 0.906 ± 0.007 µs |
|
|
323
|
+
| `@cache(backend=None)` L1 hit, 10K-row DataFrame | 0.91 ± 0.01 µs |
|
|
324
|
+
| L1 hit with an L2 backend configured, same dict | 310 ± 20 µs |
|
|
325
|
+
| Redis L2 hit with L1 disabled, same dict, Redis in a container on the same machine | 551 ± 18 µs |
|
|
326
|
+
|
|
327
|
+
- With no backend, L1 keeps the returned object itself, whatever the payload's size, and a repeat call with a few short scalar arguments finds its cache key in a per-function memo instead of building it again ([which calls](https://github.com/cachekit-io/cachekit-py/blob/main/docs/performance.md#decorator--l1-hit-hot-path)). Any other call builds its key every time, as does every call to a function with a backend.
|
|
328
|
+
- With an L2 backend, L1 holds the serialized bytes and every hit deserializes them: for this dict, about 340 times the L1-only hit. Encryption adds a decrypt to each such hit; on this run that added 10 ± 21 µs, inside the noise.
|
|
329
|
+
- An L2 hit adds the backend's round trip. A Redis on another machine adds its network latency to the last row.
|
|
330
|
+
|
|
331
|
+
Hosted runners come with other CPU models too: in a run of an earlier commit, an EPYC 9V45 runner took about half as long on every row, and other machines give other figures. The [Performance Guide](https://github.com/cachekit-io/cachekit-py/blob/main/docs/performance.md#github-hosted-runner) names the guard behind each figure and how to run it, and the repository's `Bench` workflow repeats the run.
|
|
332
|
+
|
|
333
|
+
---
|
|
334
|
+
|
|
317
335
|
## Features
|
|
318
336
|
|
|
319
337
|
### Production Hardened
|
|
320
338
|
|
|
321
339
|
- Circuit breaker with graceful degradation
|
|
322
|
-
- Connection pooling with thread affinity
|
|
340
|
+
- Connection pooling with thread affinity
|
|
323
341
|
- CachekitIO keeps idle connections pooled until the server closes them, with TCP keepalive probes, so a request after a pause skips a new TLS handshake
|
|
324
342
|
- Distributed locking prevents cache stampedes
|
|
325
343
|
- Pluggable backend abstraction (Redis, CachekitIO, File, Memcached, custom)
|
|
@@ -333,7 +351,7 @@ def test_cached_function():
|
|
|
333
351
|
| Serializer | Speed | Use Case |
|
|
334
352
|
|:-----------|:-----:|:---------|
|
|
335
353
|
| **StandardSerializer** | ★★★★☆ | General Python types; not NumPy arrays or pandas objects |
|
|
336
|
-
| **OrjsonSerializer** | ★★★★★ | JSON APIs
|
|
354
|
+
| **OrjsonSerializer** | ★★★★★ | JSON APIs — requires `cachekit[json]` |
|
|
337
355
|
| **ArrowSerializer** | — | pandas DataFrames (columnar, exact round trip) |
|
|
338
356
|
| **+ Encryption** | ★★★★☆ | Any serializer above, AES-256-GCM encrypted: `@cache.secure(master_key=..., serializer=...)` |
|
|
339
357
|
|
|
@@ -383,15 +401,18 @@ assert calls == 1
|
|
|
383
401
|
### Integrity Checking
|
|
384
402
|
|
|
385
403
|
> [!IMPORTANT]
|
|
386
|
-
>
|
|
404
|
+
> Serializers detect corrupted entries with an xxHash3-64 checksum. It is on by default. `@cache.minimal` and `@cache.test` turn it off where the serializer allows it (`ArrowSerializer` always checks); `@cache.secure` refuses to turn it off.
|
|
405
|
+
|
|
406
|
+
Each checksum is an 8-byte digest, plus one pass over the payload on each write and read. What `enable_integrity_checking=False` changes depends on the serializer, and for `AutoSerializer` on the value:
|
|
387
407
|
|
|
388
|
-
|
|
408
|
+
| Serializer | Checking on (default) | Checking off |
|
|
409
|
+
|:-----------|:----------------------|:-------------|
|
|
410
|
+
| `StandardSerializer`, and `AutoSerializer` for values other than the two below | MessagePack in an LZ4 envelope that carries the checksum | Plain MessagePack: no checksum, no LZ4 |
|
|
411
|
+
| `AutoSerializer`, NumPy arrays | The checksum, then the raw array bytes (never compressed) | The raw array bytes |
|
|
412
|
+
| `AutoSerializer`, pandas DataFrames with pyarrow installed, and `ArrowSerializer` | The checksum, then the Arrow IPC data | No change: Arrow always checks |
|
|
413
|
+
| `OrjsonSerializer` | The checksum, then the JSON | Plain JSON |
|
|
389
414
|
|
|
390
|
-
|
|
391
|
-
|:----------|:----------------------------:|:-------------:|
|
|
392
|
-
| MessagePack (default) | 60-90% | 8 bytes |
|
|
393
|
-
| Arrow DataFrames | 35-49% | 8 bytes |
|
|
394
|
-
| JSON (orjson) | 37-68% | 8 bytes |
|
|
415
|
+
Where the switch drops the LZ4 envelope, an entry gets larger only when LZ4 saved more than the envelope's overhead of about 25 to 30 bytes; otherwise it stays the same size or gets smaller. Measure on your own payloads before you trade that.
|
|
395
416
|
|
|
396
417
|
### Security
|
|
397
418
|
|
|
@@ -428,7 +449,7 @@ make security-fast # Run fast checks (< 3 min)
|
|
|
428
449
|
| Tier | Time | Coverage |
|
|
429
450
|
|:-----|:----:|:---------|
|
|
430
451
|
| Fast | < 3 min | Vulnerability scanning, license checks, linting |
|
|
431
|
-
| Medium | < 15 min | Unsafe code analysis
|
|
452
|
+
| Medium | < 15 min | Unsafe code analysis (cargo-geiger) |
|
|
432
453
|
| Deep | < 2 hours | Formal verification, extended fuzzing, full sanitizers |
|
|
433
454
|
|
|
434
455
|
See [SECURITY.md][security-url] for vulnerability reporting and detailed documentation.
|
|
@@ -470,11 +491,14 @@ exposition setup.
|
|
|
470
491
|
<details>
|
|
471
492
|
<summary><strong>Thread Safety Details</strong></summary>
|
|
472
493
|
|
|
473
|
-
**Free-threaded CPython (3.14t):** the core suites run green on
|
|
474
|
-
free-threaded 3.14 with the GIL verified disabled (CI job
|
|
494
|
+
**Free-threaded CPython (3.15t, 3.14t):** the core suites run green on
|
|
495
|
+
free-threaded 3.14 and 3.15 with the GIL verified disabled (CI job
|
|
475
496
|
`test-freethreaded`), and the Rust extension declares free-threaded safety
|
|
476
|
-
(`gil_used = false`).
|
|
477
|
-
|
|
497
|
+
(`gil_used = false`). **From the release after 0.24.1, 3.15t has a wheel**:
|
|
498
|
+
the 3.15+ wheel is `abi3t`, so it installs on 3.15t without a Rust toolchain
|
|
499
|
+
(pip 26.1+ or uv 0.11.3+). **3.14t is tested
|
|
500
|
+
but has no wheel** (it builds from source). Free-threaded builds are not
|
|
501
|
+
officially supported yet — blocked upstream on
|
|
478
502
|
orjson (no free-threaded wheels) and hiredis (re-enables the GIL on import;
|
|
479
503
|
cachekit loads redis-py only for its Redis backend, and keeps hiredis out there,
|
|
480
504
|
so redis-py uses its pure-Python parser). See
|
|
@@ -483,7 +507,7 @@ full concurrency audit: [docs/free-threading.md](docs/free-threading.md).
|
|
|
483
507
|
|
|
484
508
|
**Per-Function Statistics:**
|
|
485
509
|
- Statistics tracked per function identity (`module.qualname`), shared across all calls and across re-decorations of the same function
|
|
486
|
-
- Thread-safe
|
|
510
|
+
- Thread-safe: every count is exact (L1 hits on an atomic counter, everything else under an RLock), and all methods are safe for concurrent access
|
|
487
511
|
- Fork-safe: a forked child starts with zeroed counters and its own session ID
|
|
488
512
|
|
|
489
513
|
```python
|
|
@@ -532,6 +556,7 @@ info = expensive_func.cache_info()
|
|
|
532
556
|
| [Reference Caching][reference-caching-url] | `@cache.local()` for non-serializable objects |
|
|
533
557
|
| [Rust Serialization][rust-serialization-url] | ByteStorage layer: LZ4, xxHash3, AES-256-GCM |
|
|
534
558
|
| [SSRF Protection][ssrf-url] | URL allowlisting for the CachekitIO backend |
|
|
559
|
+
| [Write-Behind][write-behind-url] | Opt-in `write_behind=True`: a miss returns before its L2 write lands |
|
|
535
560
|
|
|
536
561
|
---
|
|
537
562
|
|
|
@@ -585,7 +610,7 @@ See [CONTRIBUTING.md][contributing-url] for full development guidelines.
|
|
|
585
610
|
|
|
586
611
|
| Component | Version |
|
|
587
612
|
|:----------|:--------|
|
|
588
|
-
| Python | 3.
|
|
613
|
+
| Python | 3.11+ |
|
|
589
614
|
|
|
590
615
|
---
|
|
591
616
|
|
|
@@ -623,6 +648,7 @@ MIT License - see [LICENSE][license-file-url] for details.
|
|
|
623
648
|
[reference-caching-url]: docs/features/reference-caching.md
|
|
624
649
|
[rust-serialization-url]: docs/features/rust-serialization.md
|
|
625
650
|
[ssrf-url]: docs/features/ssrf-protection.md
|
|
651
|
+
[write-behind-url]: docs/features/write-behind.md
|
|
626
652
|
[contributing-url]: CONTRIBUTING.md
|
|
627
653
|
[license-file-url]: LICENSE
|
|
628
654
|
[github-url]: https://github.com/cachekit-io/cachekit-py
|
|
@@ -243,9 +243,9 @@ def test_cached_function():
|
|
|
243
243
|
│ │ Breaker │ │ Timeouts │ │ Locking │ │
|
|
244
244
|
│ └─────────────┘ └─────────────┘ └─────────────────────┘ │
|
|
245
245
|
├─────────────────────────────────────────────────────────────┤
|
|
246
|
-
│ L1 Cache (In-Memory) │ L2 Cache (Pluggable Backend)
|
|
247
|
-
│
|
|
248
|
-
│ │ Memcached
|
|
246
|
+
│ L1 Cache (In-Memory) │ L2 Cache (Pluggable Backend) │
|
|
247
|
+
│ in-process │ Redis / CachekitIO / File / │
|
|
248
|
+
│ │ Memcached: one backend round trip │
|
|
249
249
|
├─────────────────────────────────────────────────────────────┤
|
|
250
250
|
│ Rust Core (PyO3) │
|
|
251
251
|
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────────────┐ │
|
|
@@ -260,12 +260,31 @@ def test_cached_function():
|
|
|
260
260
|
|
|
261
261
|
---
|
|
262
262
|
|
|
263
|
+
## Performance
|
|
264
|
+
|
|
265
|
+
What a call costs inside your process, from the wall-clock guards in `tests/performance/` run on a GitHub-hosted `ubuntu-latest` runner (AMD EPYC 7763, 4 vCPUs) with CPython 3.14.7. Each figure is the mean of five run medians with its 95% band.
|
|
266
|
+
|
|
267
|
+
| Path | Time per call |
|
|
268
|
+
|:-----|--------------:|
|
|
269
|
+
| `@cache(backend=None)` L1 hit, 100-user nested dict (23.5 KB as MessagePack) | 0.906 ± 0.007 µs |
|
|
270
|
+
| `@cache(backend=None)` L1 hit, 10K-row DataFrame | 0.91 ± 0.01 µs |
|
|
271
|
+
| L1 hit with an L2 backend configured, same dict | 310 ± 20 µs |
|
|
272
|
+
| Redis L2 hit with L1 disabled, same dict, Redis in a container on the same machine | 551 ± 18 µs |
|
|
273
|
+
|
|
274
|
+
- With no backend, L1 keeps the returned object itself, whatever the payload's size, and a repeat call with a few short scalar arguments finds its cache key in a per-function memo instead of building it again ([which calls](https://github.com/cachekit-io/cachekit-py/blob/main/docs/performance.md#decorator--l1-hit-hot-path)). Any other call builds its key every time, as does every call to a function with a backend.
|
|
275
|
+
- With an L2 backend, L1 holds the serialized bytes and every hit deserializes them: for this dict, about 340 times the L1-only hit. Encryption adds a decrypt to each such hit; on this run that added 10 ± 21 µs, inside the noise.
|
|
276
|
+
- An L2 hit adds the backend's round trip. A Redis on another machine adds its network latency to the last row.
|
|
277
|
+
|
|
278
|
+
Hosted runners come with other CPU models too: in a run of an earlier commit, an EPYC 9V45 runner took about half as long on every row, and other machines give other figures. The [Performance Guide](https://github.com/cachekit-io/cachekit-py/blob/main/docs/performance.md#github-hosted-runner) names the guard behind each figure and how to run it, and the repository's `Bench` workflow repeats the run.
|
|
279
|
+
|
|
280
|
+
---
|
|
281
|
+
|
|
263
282
|
## Features
|
|
264
283
|
|
|
265
284
|
### Production Hardened
|
|
266
285
|
|
|
267
286
|
- Circuit breaker with graceful degradation
|
|
268
|
-
- Connection pooling with thread affinity
|
|
287
|
+
- Connection pooling with thread affinity
|
|
269
288
|
- CachekitIO keeps idle connections pooled until the server closes them, with TCP keepalive probes, so a request after a pause skips a new TLS handshake
|
|
270
289
|
- Distributed locking prevents cache stampedes
|
|
271
290
|
- Pluggable backend abstraction (Redis, CachekitIO, File, Memcached, custom)
|
|
@@ -279,7 +298,7 @@ def test_cached_function():
|
|
|
279
298
|
| Serializer | Speed | Use Case |
|
|
280
299
|
|:-----------|:-----:|:---------|
|
|
281
300
|
| **StandardSerializer** | ★★★★☆ | General Python types; not NumPy arrays or pandas objects |
|
|
282
|
-
| **OrjsonSerializer** | ★★★★★ | JSON APIs
|
|
301
|
+
| **OrjsonSerializer** | ★★★★★ | JSON APIs — requires `cachekit[json]` |
|
|
283
302
|
| **ArrowSerializer** | — | pandas DataFrames (columnar, exact round trip) |
|
|
284
303
|
| **+ Encryption** | ★★★★☆ | Any serializer above, AES-256-GCM encrypted: `@cache.secure(master_key=..., serializer=...)` |
|
|
285
304
|
|
|
@@ -329,15 +348,18 @@ assert calls == 1
|
|
|
329
348
|
### Integrity Checking
|
|
330
349
|
|
|
331
350
|
> [!IMPORTANT]
|
|
332
|
-
>
|
|
351
|
+
> Serializers detect corrupted entries with an xxHash3-64 checksum. It is on by default. `@cache.minimal` and `@cache.test` turn it off where the serializer allows it (`ArrowSerializer` always checks); `@cache.secure` refuses to turn it off.
|
|
352
|
+
|
|
353
|
+
Each checksum is an 8-byte digest, plus one pass over the payload on each write and read. What `enable_integrity_checking=False` changes depends on the serializer, and for `AutoSerializer` on the value:
|
|
333
354
|
|
|
334
|
-
|
|
355
|
+
| Serializer | Checking on (default) | Checking off |
|
|
356
|
+
|:-----------|:----------------------|:-------------|
|
|
357
|
+
| `StandardSerializer`, and `AutoSerializer` for values other than the two below | MessagePack in an LZ4 envelope that carries the checksum | Plain MessagePack: no checksum, no LZ4 |
|
|
358
|
+
| `AutoSerializer`, NumPy arrays | The checksum, then the raw array bytes (never compressed) | The raw array bytes |
|
|
359
|
+
| `AutoSerializer`, pandas DataFrames with pyarrow installed, and `ArrowSerializer` | The checksum, then the Arrow IPC data | No change: Arrow always checks |
|
|
360
|
+
| `OrjsonSerializer` | The checksum, then the JSON | Plain JSON |
|
|
335
361
|
|
|
336
|
-
|
|
337
|
-
|:----------|:----------------------------:|:-------------:|
|
|
338
|
-
| MessagePack (default) | 60-90% | 8 bytes |
|
|
339
|
-
| Arrow DataFrames | 35-49% | 8 bytes |
|
|
340
|
-
| JSON (orjson) | 37-68% | 8 bytes |
|
|
362
|
+
Where the switch drops the LZ4 envelope, an entry gets larger only when LZ4 saved more than the envelope's overhead of about 25 to 30 bytes; otherwise it stays the same size or gets smaller. Measure on your own payloads before you trade that.
|
|
341
363
|
|
|
342
364
|
### Security
|
|
343
365
|
|
|
@@ -374,7 +396,7 @@ make security-fast # Run fast checks (< 3 min)
|
|
|
374
396
|
| Tier | Time | Coverage |
|
|
375
397
|
|:-----|:----:|:---------|
|
|
376
398
|
| Fast | < 3 min | Vulnerability scanning, license checks, linting |
|
|
377
|
-
| Medium | < 15 min | Unsafe code analysis
|
|
399
|
+
| Medium | < 15 min | Unsafe code analysis (cargo-geiger) |
|
|
378
400
|
| Deep | < 2 hours | Formal verification, extended fuzzing, full sanitizers |
|
|
379
401
|
|
|
380
402
|
See [SECURITY.md][security-url] for vulnerability reporting and detailed documentation.
|
|
@@ -416,11 +438,14 @@ exposition setup.
|
|
|
416
438
|
<details>
|
|
417
439
|
<summary><strong>Thread Safety Details</strong></summary>
|
|
418
440
|
|
|
419
|
-
**Free-threaded CPython (3.14t):** the core suites run green on
|
|
420
|
-
free-threaded 3.14 with the GIL verified disabled (CI job
|
|
441
|
+
**Free-threaded CPython (3.15t, 3.14t):** the core suites run green on
|
|
442
|
+
free-threaded 3.14 and 3.15 with the GIL verified disabled (CI job
|
|
421
443
|
`test-freethreaded`), and the Rust extension declares free-threaded safety
|
|
422
|
-
(`gil_used = false`).
|
|
423
|
-
|
|
444
|
+
(`gil_used = false`). **From the release after 0.24.1, 3.15t has a wheel**:
|
|
445
|
+
the 3.15+ wheel is `abi3t`, so it installs on 3.15t without a Rust toolchain
|
|
446
|
+
(pip 26.1+ or uv 0.11.3+). **3.14t is tested
|
|
447
|
+
but has no wheel** (it builds from source). Free-threaded builds are not
|
|
448
|
+
officially supported yet — blocked upstream on
|
|
424
449
|
orjson (no free-threaded wheels) and hiredis (re-enables the GIL on import;
|
|
425
450
|
cachekit loads redis-py only for its Redis backend, and keeps hiredis out there,
|
|
426
451
|
so redis-py uses its pure-Python parser). See
|
|
@@ -429,7 +454,7 @@ full concurrency audit: [docs/free-threading.md](docs/free-threading.md).
|
|
|
429
454
|
|
|
430
455
|
**Per-Function Statistics:**
|
|
431
456
|
- Statistics tracked per function identity (`module.qualname`), shared across all calls and across re-decorations of the same function
|
|
432
|
-
- Thread-safe
|
|
457
|
+
- Thread-safe: every count is exact (L1 hits on an atomic counter, everything else under an RLock), and all methods are safe for concurrent access
|
|
433
458
|
- Fork-safe: a forked child starts with zeroed counters and its own session ID
|
|
434
459
|
|
|
435
460
|
```python
|
|
@@ -478,6 +503,7 @@ info = expensive_func.cache_info()
|
|
|
478
503
|
| [Reference Caching][reference-caching-url] | `@cache.local()` for non-serializable objects |
|
|
479
504
|
| [Rust Serialization][rust-serialization-url] | ByteStorage layer: LZ4, xxHash3, AES-256-GCM |
|
|
480
505
|
| [SSRF Protection][ssrf-url] | URL allowlisting for the CachekitIO backend |
|
|
506
|
+
| [Write-Behind][write-behind-url] | Opt-in `write_behind=True`: a miss returns before its L2 write lands |
|
|
481
507
|
|
|
482
508
|
---
|
|
483
509
|
|
|
@@ -531,7 +557,7 @@ See [CONTRIBUTING.md][contributing-url] for full development guidelines.
|
|
|
531
557
|
|
|
532
558
|
| Component | Version |
|
|
533
559
|
|:----------|:--------|
|
|
534
|
-
| Python | 3.
|
|
560
|
+
| Python | 3.11+ |
|
|
535
561
|
|
|
536
562
|
---
|
|
537
563
|
|
|
@@ -569,6 +595,7 @@ MIT License - see [LICENSE][license-file-url] for details.
|
|
|
569
595
|
[reference-caching-url]: docs/features/reference-caching.md
|
|
570
596
|
[rust-serialization-url]: docs/features/rust-serialization.md
|
|
571
597
|
[ssrf-url]: docs/features/ssrf-protection.md
|
|
598
|
+
[write-behind-url]: docs/features/write-behind.md
|
|
572
599
|
[contributing-url]: CONTRIBUTING.md
|
|
573
600
|
[license-file-url]: LICENSE
|
|
574
601
|
[github-url]: https://github.com/cachekit-io/cachekit-py
|