cachekit 0.20.0__tar.gz → 0.22.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.20.0 → cachekit-0.22.0}/Cargo.lock +106 -52
- {cachekit-0.20.0 → cachekit-0.22.0}/Cargo.toml +2 -21
- {cachekit-0.20.0 → cachekit-0.22.0}/PKG-INFO +28 -17
- {cachekit-0.20.0 → cachekit-0.22.0}/README.md +24 -11
- {cachekit-0.20.0 → cachekit-0.22.0}/pyproject.toml +16 -25
- {cachekit-0.20.0 → cachekit-0.22.0}/rust/Cargo.toml +4 -4
- {cachekit-0.20.0 → cachekit-0.22.0}/rust/Makefile +4 -7
- {cachekit-0.20.0 → cachekit-0.22.0}/rust/README.md +24 -11
- {cachekit-0.20.0 → cachekit-0.22.0}/rust/src/lib.rs +4 -5
- {cachekit-0.20.0 → cachekit-0.22.0}/rust/src/python_bindings.rs +0 -44
- {cachekit-0.20.0 → cachekit-0.22.0}/src/cachekit/__init__.py +8 -12
- {cachekit-0.20.0 → cachekit-0.22.0}/src/cachekit/backends/__init__.py +14 -3
- cachekit-0.22.0/src/cachekit/backends/_uninterrupted.py +38 -0
- {cachekit-0.20.0 → cachekit-0.22.0}/src/cachekit/backends/base.py +3 -1
- {cachekit-0.20.0 → cachekit-0.22.0}/src/cachekit/backends/base_config.py +2 -1
- {cachekit-0.20.0 → cachekit-0.22.0}/src/cachekit/backends/cachekitio/backend.py +462 -229
- cachekit-0.22.0/src/cachekit/backends/cachekitio/client.py +279 -0
- {cachekit-0.20.0 → cachekit-0.22.0}/src/cachekit/backends/cachekitio/config.py +6 -9
- {cachekit-0.20.0 → cachekit-0.22.0}/src/cachekit/backends/cachekitio/error_handler.py +44 -26
- {cachekit-0.20.0 → cachekit-0.22.0}/src/cachekit/backends/errors.py +19 -18
- {cachekit-0.20.0 → cachekit-0.22.0}/src/cachekit/backends/file/__init__.py +1 -1
- {cachekit-0.20.0 → cachekit-0.22.0}/src/cachekit/backends/file/backend.py +35 -12
- {cachekit-0.20.0 → cachekit-0.22.0}/src/cachekit/backends/file/config.py +2 -2
- {cachekit-0.20.0 → cachekit-0.22.0}/src/cachekit/backends/memcached/__init__.py +2 -1
- {cachekit-0.20.0 → cachekit-0.22.0}/src/cachekit/backends/memcached/backend.py +137 -27
- {cachekit-0.20.0 → cachekit-0.22.0}/src/cachekit/backends/memcached/config.py +6 -3
- {cachekit-0.20.0 → cachekit-0.22.0}/src/cachekit/backends/memcached/error_handler.py +26 -2
- {cachekit-0.20.0 → cachekit-0.22.0}/src/cachekit/backends/provider.py +37 -24
- cachekit-0.22.0/src/cachekit/backends/redis/__init__.py +17 -0
- {cachekit-0.20.0 → cachekit-0.22.0}/src/cachekit/backends/redis/backend.py +25 -3
- {cachekit-0.20.0 → cachekit-0.22.0}/src/cachekit/backends/redis/client.py +43 -11
- {cachekit-0.20.0 → cachekit-0.22.0}/src/cachekit/backends/redis/config.py +16 -8
- {cachekit-0.20.0 → cachekit-0.22.0}/src/cachekit/backends/redis/error_handler.py +9 -9
- {cachekit-0.20.0 → cachekit-0.22.0}/src/cachekit/backends/redis/provider.py +74 -30
- {cachekit-0.20.0 → cachekit-0.22.0}/src/cachekit/cache_handler.py +270 -108
- {cachekit-0.20.0 → cachekit-0.22.0}/src/cachekit/config/decorator.py +124 -85
- {cachekit-0.20.0 → cachekit-0.22.0}/src/cachekit/config/nested.py +34 -21
- {cachekit-0.20.0 → cachekit-0.22.0}/src/cachekit/config/settings.py +13 -19
- {cachekit-0.20.0 → cachekit-0.22.0}/src/cachekit/config/singleton.py +8 -6
- {cachekit-0.20.0 → cachekit-0.22.0}/src/cachekit/config/validation.py +100 -32
- {cachekit-0.20.0 → cachekit-0.22.0}/src/cachekit/decorators/intent.py +19 -5
- {cachekit-0.20.0 → cachekit-0.22.0}/src/cachekit/decorators/orchestrator.py +25 -4
- {cachekit-0.20.0 → cachekit-0.22.0}/src/cachekit/decorators/wrapper.py +995 -547
- {cachekit-0.20.0 → cachekit-0.22.0}/src/cachekit/hash_utils.py +63 -4
- {cachekit-0.20.0 → cachekit-0.22.0}/src/cachekit/health.py +6 -1
- cachekit-0.22.0/src/cachekit/hiredis_compat.py +98 -0
- {cachekit-0.20.0 → cachekit-0.22.0}/src/cachekit/interop.py +51 -5
- cachekit-0.22.0/src/cachekit/invalidation.py +483 -0
- {cachekit-0.20.0 → cachekit-0.22.0}/src/cachekit/key_generator.py +22 -1
- {cachekit-0.20.0 → cachekit-0.22.0}/src/cachekit/l1_cache.py +248 -106
- {cachekit-0.20.0 → cachekit-0.22.0}/src/cachekit/object_cache.py +200 -87
- {cachekit-0.20.0 → cachekit-0.22.0}/src/cachekit/reliability/__init__.py +1 -11
- {cachekit-0.20.0 → cachekit-0.22.0}/src/cachekit/reliability/async_metrics.py +344 -148
- {cachekit-0.20.0 → cachekit-0.22.0}/src/cachekit/reliability/circuit_breaker.py +162 -31
- {cachekit-0.20.0 → cachekit-0.22.0}/src/cachekit/serializers/__init__.py +4 -2
- {cachekit-0.20.0 → cachekit-0.22.0}/src/cachekit/serializers/arrow_serializer.py +41 -22
- {cachekit-0.20.0 → cachekit-0.22.0}/src/cachekit/serializers/auto_serializer.py +105 -39
- {cachekit-0.20.0 → cachekit-0.22.0}/src/cachekit/serializers/encryption_wrapper.py +82 -30
- cachekit-0.22.0/src/cachekit/serializers/wrapper.py +270 -0
- cachekit-0.20.0/src/cachekit/backends/cachekitio/client.py +0 -187
- cachekit-0.20.0/src/cachekit/backends/redis/__init__.py +0 -12
- cachekit-0.20.0/src/cachekit/hiredis_compat.py +0 -98
- cachekit-0.20.0/src/cachekit/reliability/profiles.py +0 -236
- cachekit-0.20.0/src/cachekit/serializers/wrapper.py +0 -169
- {cachekit-0.20.0 → cachekit-0.22.0}/LICENSE +0 -0
- {cachekit-0.20.0 → cachekit-0.22.0}/rust/TEST_EXPANSION_SUMMARY.md +0 -0
- {cachekit-0.20.0 → cachekit-0.22.0}/rust/src/msgpack_bounds.rs +0 -0
- {cachekit-0.20.0 → cachekit-0.22.0}/rust/tsan_suppressions.txt +0 -0
- {cachekit-0.20.0 → cachekit-0.22.0}/src/cachekit/backends/cachekitio/__init__.py +0 -0
- {cachekit-0.20.0 → cachekit-0.22.0}/src/cachekit/backends/cachekitio/session.py +0 -0
- {cachekit-0.20.0 → cachekit-0.22.0}/src/cachekit/config/__init__.py +0 -0
- {cachekit-0.20.0 → cachekit-0.22.0}/src/cachekit/decorators/__init__.py +0 -0
- {cachekit-0.20.0 → cachekit-0.22.0}/src/cachekit/decorators/local_wrapper.py +0 -0
- {cachekit-0.20.0 → cachekit-0.22.0}/src/cachekit/decorators/main.py +0 -0
- {cachekit-0.20.0 → cachekit-0.22.0}/src/cachekit/decorators/session.py +0 -0
- {cachekit-0.20.0 → cachekit-0.22.0}/src/cachekit/decorators/stats_context.py +0 -0
- {cachekit-0.20.0 → cachekit-0.22.0}/src/cachekit/decorators/tenant_context.py +0 -0
- {cachekit-0.20.0 → cachekit-0.22.0}/src/cachekit/decorators/utils/__init__.py +0 -0
- {cachekit-0.20.0 → cachekit-0.22.0}/src/cachekit/di.py +0 -0
- {cachekit-0.20.0 → cachekit-0.22.0}/src/cachekit/imports.py +0 -0
- {cachekit-0.20.0 → cachekit-0.22.0}/src/cachekit/logging.py +0 -0
- {cachekit-0.20.0 → cachekit-0.22.0}/src/cachekit/monitoring/__init__.py +0 -0
- {cachekit-0.20.0 → cachekit-0.22.0}/src/cachekit/monitoring/pool_monitor.py +0 -0
- {cachekit-0.20.0 → cachekit-0.22.0}/src/cachekit/monitoring/protocols.py +0 -0
- {cachekit-0.20.0 → cachekit-0.22.0}/src/cachekit/py.typed +0 -0
- {cachekit-0.20.0 → cachekit-0.22.0}/src/cachekit/reliability/error_classification.py +0 -0
- {cachekit-0.20.0 → cachekit-0.22.0}/src/cachekit/reliability/load_control.py +0 -0
- {cachekit-0.20.0 → cachekit-0.22.0}/src/cachekit/reliability/metrics_collection.py +0 -0
- {cachekit-0.20.0 → cachekit-0.22.0}/src/cachekit/serializers/base.py +0 -0
- {cachekit-0.20.0 → cachekit-0.22.0}/src/cachekit/serializers/interop_serializer.py +0 -0
- {cachekit-0.20.0 → cachekit-0.22.0}/src/cachekit/serializers/orjson_serializer.py +0 -0
- {cachekit-0.20.0 → cachekit-0.22.0}/src/cachekit/serializers/standard_serializer.py +0 -0
|
@@ -85,6 +85,15 @@ dependencies = [
|
|
|
85
85
|
"equator",
|
|
86
86
|
]
|
|
87
87
|
|
|
88
|
+
[[package]]
|
|
89
|
+
name = "alloca"
|
|
90
|
+
version = "0.4.0"
|
|
91
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
92
|
+
checksum = "e5a7d05ea6aea7e9e64d25b9156ba2fee3fdd659e34e41063cd2fc7cd020d7f4"
|
|
93
|
+
dependencies = [
|
|
94
|
+
"cc",
|
|
95
|
+
]
|
|
96
|
+
|
|
88
97
|
[[package]]
|
|
89
98
|
name = "anes"
|
|
90
99
|
version = "0.1.6"
|
|
@@ -127,7 +136,7 @@ version = "1.1.5"
|
|
|
127
136
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
128
137
|
checksum = "40c48f72fd53cd289104fc64099abca73db4166ad86ea0b4341abe65af83dadc"
|
|
129
138
|
dependencies = [
|
|
130
|
-
"windows-sys 0.
|
|
139
|
+
"windows-sys 0.60.2",
|
|
131
140
|
]
|
|
132
141
|
|
|
133
142
|
[[package]]
|
|
@@ -138,7 +147,7 @@ checksum = "291e6a250ff86cd4a820112fb8898808a366d8f9f58ce16d1f538353ad55747d"
|
|
|
138
147
|
dependencies = [
|
|
139
148
|
"anstyle",
|
|
140
149
|
"once_cell_polyfill",
|
|
141
|
-
"windows-sys 0.
|
|
150
|
+
"windows-sys 0.60.2",
|
|
142
151
|
]
|
|
143
152
|
|
|
144
153
|
[[package]]
|
|
@@ -271,10 +280,10 @@ dependencies = [
|
|
|
271
280
|
|
|
272
281
|
[[package]]
|
|
273
282
|
name = "cachekit-rs"
|
|
274
|
-
version = "0.
|
|
283
|
+
version = "0.22.0"
|
|
275
284
|
dependencies = [
|
|
276
285
|
"cachekit-core",
|
|
277
|
-
"criterion",
|
|
286
|
+
"criterion 0.8.2",
|
|
278
287
|
"ctor",
|
|
279
288
|
"divan",
|
|
280
289
|
"fastrand",
|
|
@@ -431,9 +440,9 @@ dependencies = [
|
|
|
431
440
|
"cast",
|
|
432
441
|
"ciborium",
|
|
433
442
|
"clap",
|
|
434
|
-
"criterion-plot",
|
|
443
|
+
"criterion-plot 0.5.0",
|
|
435
444
|
"is-terminal",
|
|
436
|
-
"itertools",
|
|
445
|
+
"itertools 0.10.5",
|
|
437
446
|
"num-traits",
|
|
438
447
|
"once_cell",
|
|
439
448
|
"oorandom",
|
|
@@ -447,6 +456,31 @@ dependencies = [
|
|
|
447
456
|
"walkdir",
|
|
448
457
|
]
|
|
449
458
|
|
|
459
|
+
[[package]]
|
|
460
|
+
name = "criterion"
|
|
461
|
+
version = "0.8.2"
|
|
462
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
463
|
+
checksum = "950046b2aa2492f9a536f5f4f9a3de7b9e2476e575e05bd6c333371add4d98f3"
|
|
464
|
+
dependencies = [
|
|
465
|
+
"alloca",
|
|
466
|
+
"anes",
|
|
467
|
+
"cast",
|
|
468
|
+
"ciborium",
|
|
469
|
+
"clap",
|
|
470
|
+
"criterion-plot 0.8.2",
|
|
471
|
+
"itertools 0.13.0",
|
|
472
|
+
"num-traits",
|
|
473
|
+
"oorandom",
|
|
474
|
+
"page_size",
|
|
475
|
+
"plotters",
|
|
476
|
+
"rayon",
|
|
477
|
+
"regex",
|
|
478
|
+
"serde",
|
|
479
|
+
"serde_json",
|
|
480
|
+
"tinytemplate",
|
|
481
|
+
"walkdir",
|
|
482
|
+
]
|
|
483
|
+
|
|
450
484
|
[[package]]
|
|
451
485
|
name = "criterion-plot"
|
|
452
486
|
version = "0.5.0"
|
|
@@ -454,7 +488,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
|
454
488
|
checksum = "6b50826342786a51a89e2da3a28f1c32b06e387201bc2d19791f622c673706b1"
|
|
455
489
|
dependencies = [
|
|
456
490
|
"cast",
|
|
457
|
-
"itertools",
|
|
491
|
+
"itertools 0.10.5",
|
|
492
|
+
]
|
|
493
|
+
|
|
494
|
+
[[package]]
|
|
495
|
+
name = "criterion-plot"
|
|
496
|
+
version = "0.8.2"
|
|
497
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
498
|
+
checksum = "d8d80a2f4f5b554395e47b5d8305bc3d27813bacb73493eb1001e8f76dae29ea"
|
|
499
|
+
dependencies = [
|
|
500
|
+
"cast",
|
|
501
|
+
"itertools 0.13.0",
|
|
458
502
|
]
|
|
459
503
|
|
|
460
504
|
[[package]]
|
|
@@ -501,20 +545,14 @@ dependencies = [
|
|
|
501
545
|
|
|
502
546
|
[[package]]
|
|
503
547
|
name = "ctor"
|
|
504
|
-
version = "0.
|
|
548
|
+
version = "0.13.1"
|
|
505
549
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
506
|
-
checksum = "
|
|
550
|
+
checksum = "3429e8f8e3ce0ffe475c411850f70468c70d7a87d2ac3d15dd44703fb885aede"
|
|
507
551
|
dependencies = [
|
|
508
|
-
"
|
|
509
|
-
"
|
|
552
|
+
"link-section",
|
|
553
|
+
"linktime-proc-macro",
|
|
510
554
|
]
|
|
511
555
|
|
|
512
|
-
[[package]]
|
|
513
|
-
name = "ctor-proc-macro"
|
|
514
|
-
version = "0.0.6"
|
|
515
|
-
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
516
|
-
checksum = "e2931af7e13dc045d8e9d26afccc6fa115d64e115c9c84b1166288b46f6782c2"
|
|
517
|
-
|
|
518
556
|
[[package]]
|
|
519
557
|
name = "ctr"
|
|
520
558
|
version = "0.9.2"
|
|
@@ -590,21 +628,6 @@ dependencies = [
|
|
|
590
628
|
"syn",
|
|
591
629
|
]
|
|
592
630
|
|
|
593
|
-
[[package]]
|
|
594
|
-
name = "dtor"
|
|
595
|
-
version = "0.0.6"
|
|
596
|
-
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
597
|
-
checksum = "97cbdf2ad6846025e8e25df05171abfb30e3ababa12ee0a0e44b9bbe570633a8"
|
|
598
|
-
dependencies = [
|
|
599
|
-
"dtor-proc-macro",
|
|
600
|
-
]
|
|
601
|
-
|
|
602
|
-
[[package]]
|
|
603
|
-
name = "dtor-proc-macro"
|
|
604
|
-
version = "0.0.5"
|
|
605
|
-
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
606
|
-
checksum = "7454e41ff9012c00d53cf7f475c5e3afa3b91b7c90568495495e8d9bf47a1055"
|
|
607
|
-
|
|
608
631
|
[[package]]
|
|
609
632
|
name = "either"
|
|
610
633
|
version = "1.15.0"
|
|
@@ -644,14 +667,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
|
644
667
|
checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb"
|
|
645
668
|
dependencies = [
|
|
646
669
|
"libc",
|
|
647
|
-
"windows-sys 0.
|
|
670
|
+
"windows-sys 0.52.0",
|
|
648
671
|
]
|
|
649
672
|
|
|
650
673
|
[[package]]
|
|
651
674
|
name = "fastrand"
|
|
652
|
-
version = "2.
|
|
675
|
+
version = "2.5.0"
|
|
653
676
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
654
|
-
checksum = "
|
|
677
|
+
checksum = "da7c62ceae207dd37ea5b845da6a0696c799f85e97da1ab5b7910be3c1c80223"
|
|
655
678
|
|
|
656
679
|
[[package]]
|
|
657
680
|
name = "find-msvc-tools"
|
|
@@ -786,9 +809,9 @@ dependencies = [
|
|
|
786
809
|
|
|
787
810
|
[[package]]
|
|
788
811
|
name = "iai-callgrind"
|
|
789
|
-
version = "0.
|
|
812
|
+
version = "0.16.1"
|
|
790
813
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
791
|
-
checksum = "
|
|
814
|
+
checksum = "0b1e4910d3a9137442723dfb772c32dc10674c4181ca078d2fd227cd5dce9db0"
|
|
792
815
|
dependencies = [
|
|
793
816
|
"bincode",
|
|
794
817
|
"derive_more",
|
|
@@ -798,9 +821,9 @@ dependencies = [
|
|
|
798
821
|
|
|
799
822
|
[[package]]
|
|
800
823
|
name = "iai-callgrind-macros"
|
|
801
|
-
version = "0.
|
|
824
|
+
version = "0.6.1"
|
|
802
825
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
803
|
-
checksum = "
|
|
826
|
+
checksum = "4d03775318d3f9f01b39ac6612b01464006dc397a654a89dd57df2fd34fb68c3"
|
|
804
827
|
dependencies = [
|
|
805
828
|
"derive_more",
|
|
806
829
|
"proc-macro-error2",
|
|
@@ -813,9 +836,9 @@ dependencies = [
|
|
|
813
836
|
|
|
814
837
|
[[package]]
|
|
815
838
|
name = "iai-callgrind-runner"
|
|
816
|
-
version = "0.
|
|
839
|
+
version = "0.16.1"
|
|
817
840
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
818
|
-
checksum = "
|
|
841
|
+
checksum = "b74c9743c00c3bca4aaffc69c87cae56837796cd362438daf354a3f785788c68"
|
|
819
842
|
dependencies = [
|
|
820
843
|
"serde",
|
|
821
844
|
]
|
|
@@ -865,7 +888,7 @@ checksum = "3640c1c38b8e4e43584d8df18be5fc6b0aa314ce6ebf51b53313d4306cca8e46"
|
|
|
865
888
|
dependencies = [
|
|
866
889
|
"hermit-abi",
|
|
867
890
|
"libc",
|
|
868
|
-
"windows-sys 0.
|
|
891
|
+
"windows-sys 0.52.0",
|
|
869
892
|
]
|
|
870
893
|
|
|
871
894
|
[[package]]
|
|
@@ -883,6 +906,15 @@ dependencies = [
|
|
|
883
906
|
"either",
|
|
884
907
|
]
|
|
885
908
|
|
|
909
|
+
[[package]]
|
|
910
|
+
name = "itertools"
|
|
911
|
+
version = "0.13.0"
|
|
912
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
913
|
+
checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186"
|
|
914
|
+
dependencies = [
|
|
915
|
+
"either",
|
|
916
|
+
]
|
|
917
|
+
|
|
886
918
|
[[package]]
|
|
887
919
|
name = "itoa"
|
|
888
920
|
version = "1.0.17"
|
|
@@ -911,6 +943,18 @@ version = "0.2.183"
|
|
|
911
943
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
912
944
|
checksum = "b5b646652bf6661599e1da8901b3b9522896f01e736bad5f723fe7a3a27f899d"
|
|
913
945
|
|
|
946
|
+
[[package]]
|
|
947
|
+
name = "link-section"
|
|
948
|
+
version = "0.13.1"
|
|
949
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
950
|
+
checksum = "ea2c24837c4fd5ab6a31d64133eae954f5199247523cf29586117e85245c0dd3"
|
|
951
|
+
|
|
952
|
+
[[package]]
|
|
953
|
+
name = "linktime-proc-macro"
|
|
954
|
+
version = "0.1.0"
|
|
955
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
956
|
+
checksum = "a44cd706ff0d503ee32b2071166510ca27e281228de10cd3aa8d35ff94560f81"
|
|
957
|
+
|
|
914
958
|
[[package]]
|
|
915
959
|
name = "linux-raw-sys"
|
|
916
960
|
version = "0.4.15"
|
|
@@ -1034,6 +1078,16 @@ version = "0.3.1"
|
|
|
1034
1078
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
1035
1079
|
checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381"
|
|
1036
1080
|
|
|
1081
|
+
[[package]]
|
|
1082
|
+
name = "page_size"
|
|
1083
|
+
version = "0.6.0"
|
|
1084
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
1085
|
+
checksum = "30d5b2194ed13191c1999ae0704b7839fb18384fa22e49b57eeaa97d79ce40da"
|
|
1086
|
+
dependencies = [
|
|
1087
|
+
"libc",
|
|
1088
|
+
"winapi",
|
|
1089
|
+
]
|
|
1090
|
+
|
|
1037
1091
|
[[package]]
|
|
1038
1092
|
name = "plotters"
|
|
1039
1093
|
version = "0.3.7"
|
|
@@ -1089,7 +1143,7 @@ dependencies = [
|
|
|
1089
1143
|
"aligned-vec",
|
|
1090
1144
|
"backtrace",
|
|
1091
1145
|
"cfg-if",
|
|
1092
|
-
"criterion",
|
|
1146
|
+
"criterion 0.5.1",
|
|
1093
1147
|
"findshlibs",
|
|
1094
1148
|
"inferno",
|
|
1095
1149
|
"libc",
|
|
@@ -1147,9 +1201,9 @@ dependencies = [
|
|
|
1147
1201
|
|
|
1148
1202
|
[[package]]
|
|
1149
1203
|
name = "proptest"
|
|
1150
|
-
version = "1.
|
|
1204
|
+
version = "1.11.0"
|
|
1151
1205
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
1152
|
-
checksum = "
|
|
1206
|
+
checksum = "4b45fcc2344c680f5025fe57779faef368840d0bd1f42f216291f0dc4ace4744"
|
|
1153
1207
|
dependencies = [
|
|
1154
1208
|
"bit-set",
|
|
1155
1209
|
"bit-vec",
|
|
@@ -1484,7 +1538,7 @@ dependencies = [
|
|
|
1484
1538
|
"errno",
|
|
1485
1539
|
"libc",
|
|
1486
1540
|
"linux-raw-sys 0.12.1",
|
|
1487
|
-
"windows-sys 0.
|
|
1541
|
+
"windows-sys 0.52.0",
|
|
1488
1542
|
]
|
|
1489
1543
|
|
|
1490
1544
|
[[package]]
|
|
@@ -1694,7 +1748,7 @@ dependencies = [
|
|
|
1694
1748
|
"getrandom 0.3.4",
|
|
1695
1749
|
"once_cell",
|
|
1696
1750
|
"rustix 1.1.4",
|
|
1697
|
-
"windows-sys 0.
|
|
1751
|
+
"windows-sys 0.52.0",
|
|
1698
1752
|
]
|
|
1699
1753
|
|
|
1700
1754
|
[[package]]
|
|
@@ -1981,7 +2035,7 @@ version = "0.1.11"
|
|
|
1981
2035
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
1982
2036
|
checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22"
|
|
1983
2037
|
dependencies = [
|
|
1984
|
-
"windows-sys 0.
|
|
2038
|
+
"windows-sys 0.52.0",
|
|
1985
2039
|
]
|
|
1986
2040
|
|
|
1987
2041
|
[[package]]
|
|
@@ -2201,18 +2255,18 @@ dependencies = [
|
|
|
2201
2255
|
|
|
2202
2256
|
[[package]]
|
|
2203
2257
|
name = "zeroize"
|
|
2204
|
-
version = "1.
|
|
2258
|
+
version = "1.9.0"
|
|
2205
2259
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
2206
|
-
checksum = "
|
|
2260
|
+
checksum = "e13c156562582aa81c60cb29407084cdb54c4164760106ab78e6c5b0858cf64e"
|
|
2207
2261
|
dependencies = [
|
|
2208
2262
|
"zeroize_derive",
|
|
2209
2263
|
]
|
|
2210
2264
|
|
|
2211
2265
|
[[package]]
|
|
2212
2266
|
name = "zeroize_derive"
|
|
2213
|
-
version = "1.
|
|
2267
|
+
version = "1.5.0"
|
|
2214
2268
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
2215
|
-
checksum = "
|
|
2269
|
+
checksum = "3c50655cbb0fe3fc43170059e702f1ce5e19b84cec58dc87b037a09935c2f328"
|
|
2216
2270
|
dependencies = [
|
|
2217
2271
|
"proc-macro2",
|
|
2218
2272
|
"quote",
|
|
@@ -8,11 +8,11 @@ pyo3 = { version = "0.29", features = ["extension-module"] }
|
|
|
8
8
|
serde = { version = "1.0", features = ["derive"] }
|
|
9
9
|
serde_json = "1.0"
|
|
10
10
|
bincode = "1.3"
|
|
11
|
-
numpy = "0.
|
|
11
|
+
numpy = "0.29"
|
|
12
12
|
|
|
13
13
|
# Performance dependencies
|
|
14
14
|
rayon = "1.8"
|
|
15
|
-
simd-json = "0.
|
|
15
|
+
simd-json = "0.18"
|
|
16
16
|
lz4 = "1.24"
|
|
17
17
|
memmap2 = "0.9"
|
|
18
18
|
|
|
@@ -41,22 +41,3 @@ opt-level = 1
|
|
|
41
41
|
opt-level = 3
|
|
42
42
|
debug = true
|
|
43
43
|
lto = "fat"
|
|
44
|
-
|
|
45
|
-
# Profile-Guided Optimization - Generate profile data
|
|
46
|
-
[profile.release-pgo-generate]
|
|
47
|
-
inherits = "release"
|
|
48
|
-
# PGO instrumentation adds overhead, disable some optimizations
|
|
49
|
-
lto = false
|
|
50
|
-
# Keep debug info for profiling
|
|
51
|
-
debug = true
|
|
52
|
-
|
|
53
|
-
# Profile-Guided Optimization - Use profile data
|
|
54
|
-
[profile.release-pgo-use]
|
|
55
|
-
inherits = "release"
|
|
56
|
-
# Full LTO with profile data for maximum optimization
|
|
57
|
-
lto = "fat"
|
|
58
|
-
# Strip symbols for smaller binary
|
|
59
|
-
strip = true
|
|
60
|
-
# Maximum optimization with profile data
|
|
61
|
-
opt-level = 3
|
|
62
|
-
codegen-units = 1
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: cachekit
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.22.0
|
|
4
4
|
Classifier: Development Status :: 4 - Beta
|
|
5
5
|
Classifier: Intended Audience :: Developers
|
|
6
6
|
Classifier: License :: OSI Approved :: MIT License
|
|
@@ -20,17 +20,15 @@ Classifier: Topic :: System :: Monitoring
|
|
|
20
20
|
Classifier: Topic :: Security :: Cryptography
|
|
21
21
|
Classifier: Framework :: AsyncIO
|
|
22
22
|
Classifier: Typing :: Typed
|
|
23
|
-
Requires-Dist: redis[hiredis]>=4.
|
|
23
|
+
Requires-Dist: redis[hiredis]>=4.6.0
|
|
24
24
|
Requires-Dist: pydantic>=2.0.0
|
|
25
|
-
Requires-Dist: pydantic-settings>=2.
|
|
25
|
+
Requires-Dist: pydantic-settings>=2.13.0
|
|
26
26
|
Requires-Dist: prometheus-client>=0.22.1
|
|
27
27
|
Requires-Dist: psutil>=7.0.0
|
|
28
28
|
Requires-Dist: blake3>=1.0.5
|
|
29
29
|
Requires-Dist: msgpack>=1.2.1
|
|
30
30
|
Requires-Dist: xxhash>=3.5.0
|
|
31
|
-
Requires-Dist:
|
|
32
|
-
Requires-Dist: anyio>=4.14.2
|
|
33
|
-
Requires-Dist: h2>=4.4.1
|
|
31
|
+
Requires-Dist: urllib3>=2.8.0
|
|
34
32
|
Requires-Dist: numpy>=2.0.2 ; extra == 'data'
|
|
35
33
|
Requires-Dist: pandas>=1.3.0 ; extra == 'data'
|
|
36
34
|
Requires-Dist: pyarrow>=21.0.0 ; extra == 'data'
|
|
@@ -214,6 +212,10 @@ def get_user_profile(user_id: int):
|
|
|
214
212
|
return db.fetch_user(user_id)
|
|
215
213
|
```
|
|
216
214
|
|
|
215
|
+
Setting `CACHEKIT_MASTER_KEY` instead of passing `master_key=` means every preset except
|
|
216
|
+
`@cache.secure` and `@cache.local` must state its intent (`encryption=False` for plaintext), or it raises
|
|
217
|
+
`ConfigurationError` at decoration: the key is a key source, never an on switch.
|
|
218
|
+
|
|
217
219
|
| Feature | `@cache.minimal` | `@cache.dev` | `@cache.test` | `@cache.production` | `@cache.secure` |
|
|
218
220
|
|:--------|:----------------:|:------------:|:-------------:|:-------------------:|:---------------:|
|
|
219
221
|
| Default TTL | 300 s | 300 s | 300 s | 600 s | 600 s |
|
|
@@ -222,16 +224,19 @@ def get_user_profile(user_id: int):
|
|
|
222
224
|
| Integrity Checking | - | ✅ | - | ✅ | ✅ 🔒 |
|
|
223
225
|
| Encryption | - | - | - | - | ✅ Required |
|
|
224
226
|
| L1 SWR (L1-only mode) | - | ✅ | - | ✅ | - |
|
|
225
|
-
|
|
|
226
|
-
| Prometheus Metrics | - | - | - | ✅ | ✅ |
|
|
227
|
+
| Prometheus Metrics | - | -¹ | - | ✅ | ✅ |
|
|
227
228
|
| Tracing | - | ✅ | - | ✅ | ✅ |
|
|
228
229
|
| Structured Logging | - | ✅ | - | ✅ | ✅ |
|
|
229
230
|
| **Use Case** | High throughput | Local debugging | Deterministic tests | Production reliability | Compliance/security |
|
|
230
231
|
|
|
232
|
+
> ¹ `@cache.dev` exports no Prometheus metrics except `circuit_breaker_state`, which is recorded for every function whose circuit breaker is enabled.
|
|
233
|
+
>
|
|
231
234
|
> 🔒 `@cache.secure` forces `integrity_checking=True` — passing `integrity_checking=False` raises `ConfigurationError` at decoration, including as an override next to `config=DecoratorConfig.secure(...)`. `@cache.secure` also rejects `config=`; the RORO form is `@cache(config=DecoratorConfig.secure(...))`.
|
|
232
235
|
>
|
|
233
236
|
> **Default TTL** follows the cross-SDK [intent-preset spec](https://github.com/cachekit-io/protocol/blob/main/spec/intent-presets.md#default-ttl) (`@cache.io` 3600 s) — the same numbers as cachekit-rs and cachekit-ts. `ttl=` overrides it; `ttl=None` is the explicit never-expire opt-in ([details](docs/configuration.md#intent-presets)).
|
|
234
237
|
>
|
|
238
|
+
> **Cross-process L1 eviction** is not a preset feature: every preset's `invalidate_cache()` deletes from L1 and L2 alike, and evicting other processes' L1 copies is one process-wide opt-in, `CACHEKIT_INVALIDATION_LISTENER_ENABLED` ([L1 invalidation](docs/features/l1-invalidation.md#cross-process-l1-eviction)).
|
|
239
|
+
>
|
|
235
240
|
> **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)).
|
|
236
241
|
>
|
|
237
242
|
> **`@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.
|
|
@@ -242,7 +247,7 @@ def get_user_profile(user_id: int):
|
|
|
242
247
|
See the comparison table above for the exact feature set of each preset.
|
|
243
248
|
|
|
244
249
|
```python
|
|
245
|
-
# Development: verbose logging, integrity checks on, Prometheus off
|
|
250
|
+
# Development: verbose logging, integrity checks on, Prometheus off except circuit_breaker_state
|
|
246
251
|
@cache.dev
|
|
247
252
|
def debug_expensive_call():
|
|
248
253
|
return complex_computation()
|
|
@@ -292,6 +297,7 @@ def test_cached_function():
|
|
|
292
297
|
|
|
293
298
|
- Circuit breaker with graceful degradation
|
|
294
299
|
- Connection pooling with thread affinity (+28% throughput)
|
|
300
|
+
- 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
|
|
295
301
|
- Distributed locking prevents cache stampedes
|
|
296
302
|
- Pluggable backend abstraction (Redis, CachekitIO, File, Memcached, custom)
|
|
297
303
|
- Untrusted-decode bounds: nesting depth and header-declared allocation are capped on every cache read (a forged entry is a bounded cache miss), verified against the protocol's shared [`decode-bounds.json`](https://github.com/cachekit-io/protocol/blob/2736a81f2f853cf08c5563c0fe7c8361331fa3ad/test-vectors/decode-bounds.json) vectors
|
|
@@ -306,7 +312,7 @@ def test_cached_function():
|
|
|
306
312
|
| **StandardSerializer** | ★★★★☆ | General Python types, NumPy, Pandas |
|
|
307
313
|
| **OrjsonSerializer** | ★★★★★ | JSON APIs (2-5x faster than stdlib) — requires `cachekit[json]` |
|
|
308
314
|
| **ArrowSerializer** | ★★★★★ | Large DataFrames (6-23x faster for 10K+ rows) |
|
|
309
|
-
| **
|
|
315
|
+
| **+ Encryption** | ★★★★☆ | Any serializer above, AES-256-GCM encrypted: `@cache.secure(master_key=..., serializer=...)` |
|
|
310
316
|
|
|
311
317
|
<details>
|
|
312
318
|
<summary><strong>Serializer Examples</strong></summary>
|
|
@@ -445,7 +451,9 @@ free-threaded 3.14 with the GIL verified disabled (CI job
|
|
|
445
451
|
`test-freethreaded`), and the Rust extension declares free-threaded safety
|
|
446
452
|
(`gil_used = false`). Free-threaded wheels are **not yet published** and
|
|
447
453
|
free-threaded builds are not officially supported — blocked upstream on
|
|
448
|
-
orjson (no free-threaded wheels) and hiredis (re-enables the GIL on import
|
|
454
|
+
orjson (no free-threaded wheels) and hiredis (re-enables the GIL on import;
|
|
455
|
+
cachekit loads redis-py only for its Redis backend, and keeps hiredis out there,
|
|
456
|
+
so redis-py uses its pure-Python parser). See
|
|
449
457
|
[measured performance results](docs/free-threading.md#measured-performance) and the
|
|
450
458
|
full concurrency audit: [docs/free-threading.md](docs/free-threading.md).
|
|
451
459
|
|
|
@@ -496,7 +504,7 @@ info = expensive_func.cache_info()
|
|
|
496
504
|
| [Prometheus Metrics][prometheus-url] | Built-in observability |
|
|
497
505
|
| [Zero-Knowledge Encryption][encryption-url] | Client-side security |
|
|
498
506
|
| [Interop Mode][interop-url] | Cross-SDK cache sharing with cachekit-ts/rs |
|
|
499
|
-
| [L1 Invalidation & SWR][l1-invalidation-url] | Invalidation scope (incl. cross-process whole-function on tenant-scoped Redis from the environment or `RedisBackendProvider`), stale-while-revalidate |
|
|
507
|
+
| [L1 Invalidation & SWR][l1-invalidation-url] | Invalidation scope (incl. cross-process whole-function on tenant-scoped Redis from the environment or `RedisBackendProvider`), opt-in cross-process L1 eviction, stale-while-revalidate |
|
|
500
508
|
| [Reference Caching][reference-caching-url] | `@cache.local()` for non-serializable objects |
|
|
501
509
|
| [Rust Serialization][rust-serialization-url] | ByteStorage layer: LZ4, xxHash3, AES-256-GCM |
|
|
502
510
|
| [SSRF Protection][ssrf-url] | URL allowlisting for the CachekitIO backend |
|
|
@@ -508,16 +516,22 @@ info = expensive_func.cache_info()
|
|
|
508
516
|
### Environment Variables
|
|
509
517
|
|
|
510
518
|
```bash
|
|
519
|
+
# Backend selection: set exactly ONE of CACHEKIT_REDIS_URL, CACHEKIT_API_KEY,
|
|
520
|
+
# CACHEKIT_MEMCACHED_SERVERS, CACHEKIT_FILE_CACHE_DIR. Two or more is a ConfigurationError at
|
|
521
|
+
# first call, and decorators relying on env auto-detection run uncached (docs/backends/README.md).
|
|
522
|
+
# REDIS_URL is only a fallback and never conflicts.
|
|
523
|
+
|
|
511
524
|
# Redis Connection (priority: CACHEKIT_REDIS_URL > REDIS_URL)
|
|
512
525
|
CACHEKIT_REDIS_URL="redis://localhost:6379" # Primary (preferred)
|
|
513
526
|
REDIS_URL="redis://localhost:6379" # Fallback
|
|
514
527
|
|
|
515
528
|
# CachekitIO SaaS Backend (closed beta — request access at cachekit.io)
|
|
516
|
-
|
|
529
|
+
# For @cache.io() next to Redis, pass api_key= from your secret store instead.
|
|
530
|
+
# CACHEKIT_API_KEY="your-api-key" # pragma: allowlist secret
|
|
517
531
|
CACHEKIT_API_URL="https://api.cachekit.io" # Default SaaS endpoint
|
|
518
532
|
|
|
519
533
|
# Memcached Backend (optional: pip install cachekit[memcached])
|
|
520
|
-
CACHEKIT_MEMCACHED_SERVERS='["mc1:11211", "mc2:11211"]' # Default: 127.0.0.1:11211
|
|
534
|
+
# CACHEKIT_MEMCACHED_SERVERS='["mc1:11211", "mc2:11211"]' # Default: 127.0.0.1:11211
|
|
521
535
|
CACHEKIT_MEMCACHED_CONNECT_TIMEOUT=2.0 # Default: 2.0 seconds
|
|
522
536
|
CACHEKIT_MEMCACHED_TIMEOUT=1.0 # Default: 1.0 seconds
|
|
523
537
|
CACHEKIT_MEMCACHED_KEY_PREFIX="myapp:" # Default: "" (none)
|
|
@@ -527,9 +541,6 @@ CACHEKIT_MAX_VALUE_SIZE=104857600
|
|
|
527
541
|
CACHEKIT_ARROW_COMPRESSION=zstd
|
|
528
542
|
```
|
|
529
543
|
|
|
530
|
-
> [!NOTE]
|
|
531
|
-
> If both `CACHEKIT_REDIS_URL` and `REDIS_URL` are set, `CACHEKIT_REDIS_URL` takes precedence.
|
|
532
|
-
|
|
533
544
|
---
|
|
534
545
|
|
|
535
546
|
## Development
|
|
@@ -158,6 +158,10 @@ def get_user_profile(user_id: int):
|
|
|
158
158
|
return db.fetch_user(user_id)
|
|
159
159
|
```
|
|
160
160
|
|
|
161
|
+
Setting `CACHEKIT_MASTER_KEY` instead of passing `master_key=` means every preset except
|
|
162
|
+
`@cache.secure` and `@cache.local` must state its intent (`encryption=False` for plaintext), or it raises
|
|
163
|
+
`ConfigurationError` at decoration: the key is a key source, never an on switch.
|
|
164
|
+
|
|
161
165
|
| Feature | `@cache.minimal` | `@cache.dev` | `@cache.test` | `@cache.production` | `@cache.secure` |
|
|
162
166
|
|:--------|:----------------:|:------------:|:-------------:|:-------------------:|:---------------:|
|
|
163
167
|
| Default TTL | 300 s | 300 s | 300 s | 600 s | 600 s |
|
|
@@ -166,16 +170,19 @@ def get_user_profile(user_id: int):
|
|
|
166
170
|
| Integrity Checking | - | ✅ | - | ✅ | ✅ 🔒 |
|
|
167
171
|
| Encryption | - | - | - | - | ✅ Required |
|
|
168
172
|
| L1 SWR (L1-only mode) | - | ✅ | - | ✅ | - |
|
|
169
|
-
|
|
|
170
|
-
| Prometheus Metrics | - | - | - | ✅ | ✅ |
|
|
173
|
+
| Prometheus Metrics | - | -¹ | - | ✅ | ✅ |
|
|
171
174
|
| Tracing | - | ✅ | - | ✅ | ✅ |
|
|
172
175
|
| Structured Logging | - | ✅ | - | ✅ | ✅ |
|
|
173
176
|
| **Use Case** | High throughput | Local debugging | Deterministic tests | Production reliability | Compliance/security |
|
|
174
177
|
|
|
178
|
+
> ¹ `@cache.dev` exports no Prometheus metrics except `circuit_breaker_state`, which is recorded for every function whose circuit breaker is enabled.
|
|
179
|
+
>
|
|
175
180
|
> 🔒 `@cache.secure` forces `integrity_checking=True` — passing `integrity_checking=False` raises `ConfigurationError` at decoration, including as an override next to `config=DecoratorConfig.secure(...)`. `@cache.secure` also rejects `config=`; the RORO form is `@cache(config=DecoratorConfig.secure(...))`.
|
|
176
181
|
>
|
|
177
182
|
> **Default TTL** follows the cross-SDK [intent-preset spec](https://github.com/cachekit-io/protocol/blob/main/spec/intent-presets.md#default-ttl) (`@cache.io` 3600 s) — the same numbers as cachekit-rs and cachekit-ts. `ttl=` overrides it; `ttl=None` is the explicit never-expire opt-in ([details](docs/configuration.md#intent-presets)).
|
|
178
183
|
>
|
|
184
|
+
> **Cross-process L1 eviction** is not a preset feature: every preset's `invalidate_cache()` deletes from L1 and L2 alike, and evicting other processes' L1 copies is one process-wide opt-in, `CACHEKIT_INVALIDATION_LISTENER_ENABLED` ([L1 invalidation](docs/features/l1-invalidation.md#cross-process-l1-eviction)).
|
|
185
|
+
>
|
|
179
186
|
> **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)).
|
|
180
187
|
>
|
|
181
188
|
> **`@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.
|
|
@@ -186,7 +193,7 @@ def get_user_profile(user_id: int):
|
|
|
186
193
|
See the comparison table above for the exact feature set of each preset.
|
|
187
194
|
|
|
188
195
|
```python
|
|
189
|
-
# Development: verbose logging, integrity checks on, Prometheus off
|
|
196
|
+
# Development: verbose logging, integrity checks on, Prometheus off except circuit_breaker_state
|
|
190
197
|
@cache.dev
|
|
191
198
|
def debug_expensive_call():
|
|
192
199
|
return complex_computation()
|
|
@@ -236,6 +243,7 @@ def test_cached_function():
|
|
|
236
243
|
|
|
237
244
|
- Circuit breaker with graceful degradation
|
|
238
245
|
- Connection pooling with thread affinity (+28% throughput)
|
|
246
|
+
- 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
|
|
239
247
|
- Distributed locking prevents cache stampedes
|
|
240
248
|
- Pluggable backend abstraction (Redis, CachekitIO, File, Memcached, custom)
|
|
241
249
|
- Untrusted-decode bounds: nesting depth and header-declared allocation are capped on every cache read (a forged entry is a bounded cache miss), verified against the protocol's shared [`decode-bounds.json`](https://github.com/cachekit-io/protocol/blob/2736a81f2f853cf08c5563c0fe7c8361331fa3ad/test-vectors/decode-bounds.json) vectors
|
|
@@ -250,7 +258,7 @@ def test_cached_function():
|
|
|
250
258
|
| **StandardSerializer** | ★★★★☆ | General Python types, NumPy, Pandas |
|
|
251
259
|
| **OrjsonSerializer** | ★★★★★ | JSON APIs (2-5x faster than stdlib) — requires `cachekit[json]` |
|
|
252
260
|
| **ArrowSerializer** | ★★★★★ | Large DataFrames (6-23x faster for 10K+ rows) |
|
|
253
|
-
| **
|
|
261
|
+
| **+ Encryption** | ★★★★☆ | Any serializer above, AES-256-GCM encrypted: `@cache.secure(master_key=..., serializer=...)` |
|
|
254
262
|
|
|
255
263
|
<details>
|
|
256
264
|
<summary><strong>Serializer Examples</strong></summary>
|
|
@@ -389,7 +397,9 @@ free-threaded 3.14 with the GIL verified disabled (CI job
|
|
|
389
397
|
`test-freethreaded`), and the Rust extension declares free-threaded safety
|
|
390
398
|
(`gil_used = false`). Free-threaded wheels are **not yet published** and
|
|
391
399
|
free-threaded builds are not officially supported — blocked upstream on
|
|
392
|
-
orjson (no free-threaded wheels) and hiredis (re-enables the GIL on import
|
|
400
|
+
orjson (no free-threaded wheels) and hiredis (re-enables the GIL on import;
|
|
401
|
+
cachekit loads redis-py only for its Redis backend, and keeps hiredis out there,
|
|
402
|
+
so redis-py uses its pure-Python parser). See
|
|
393
403
|
[measured performance results](docs/free-threading.md#measured-performance) and the
|
|
394
404
|
full concurrency audit: [docs/free-threading.md](docs/free-threading.md).
|
|
395
405
|
|
|
@@ -440,7 +450,7 @@ info = expensive_func.cache_info()
|
|
|
440
450
|
| [Prometheus Metrics][prometheus-url] | Built-in observability |
|
|
441
451
|
| [Zero-Knowledge Encryption][encryption-url] | Client-side security |
|
|
442
452
|
| [Interop Mode][interop-url] | Cross-SDK cache sharing with cachekit-ts/rs |
|
|
443
|
-
| [L1 Invalidation & SWR][l1-invalidation-url] | Invalidation scope (incl. cross-process whole-function on tenant-scoped Redis from the environment or `RedisBackendProvider`), stale-while-revalidate |
|
|
453
|
+
| [L1 Invalidation & SWR][l1-invalidation-url] | Invalidation scope (incl. cross-process whole-function on tenant-scoped Redis from the environment or `RedisBackendProvider`), opt-in cross-process L1 eviction, stale-while-revalidate |
|
|
444
454
|
| [Reference Caching][reference-caching-url] | `@cache.local()` for non-serializable objects |
|
|
445
455
|
| [Rust Serialization][rust-serialization-url] | ByteStorage layer: LZ4, xxHash3, AES-256-GCM |
|
|
446
456
|
| [SSRF Protection][ssrf-url] | URL allowlisting for the CachekitIO backend |
|
|
@@ -452,16 +462,22 @@ info = expensive_func.cache_info()
|
|
|
452
462
|
### Environment Variables
|
|
453
463
|
|
|
454
464
|
```bash
|
|
465
|
+
# Backend selection: set exactly ONE of CACHEKIT_REDIS_URL, CACHEKIT_API_KEY,
|
|
466
|
+
# CACHEKIT_MEMCACHED_SERVERS, CACHEKIT_FILE_CACHE_DIR. Two or more is a ConfigurationError at
|
|
467
|
+
# first call, and decorators relying on env auto-detection run uncached (docs/backends/README.md).
|
|
468
|
+
# REDIS_URL is only a fallback and never conflicts.
|
|
469
|
+
|
|
455
470
|
# Redis Connection (priority: CACHEKIT_REDIS_URL > REDIS_URL)
|
|
456
471
|
CACHEKIT_REDIS_URL="redis://localhost:6379" # Primary (preferred)
|
|
457
472
|
REDIS_URL="redis://localhost:6379" # Fallback
|
|
458
473
|
|
|
459
474
|
# CachekitIO SaaS Backend (closed beta — request access at cachekit.io)
|
|
460
|
-
|
|
475
|
+
# For @cache.io() next to Redis, pass api_key= from your secret store instead.
|
|
476
|
+
# CACHEKIT_API_KEY="your-api-key" # pragma: allowlist secret
|
|
461
477
|
CACHEKIT_API_URL="https://api.cachekit.io" # Default SaaS endpoint
|
|
462
478
|
|
|
463
479
|
# Memcached Backend (optional: pip install cachekit[memcached])
|
|
464
|
-
CACHEKIT_MEMCACHED_SERVERS='["mc1:11211", "mc2:11211"]' # Default: 127.0.0.1:11211
|
|
480
|
+
# CACHEKIT_MEMCACHED_SERVERS='["mc1:11211", "mc2:11211"]' # Default: 127.0.0.1:11211
|
|
465
481
|
CACHEKIT_MEMCACHED_CONNECT_TIMEOUT=2.0 # Default: 2.0 seconds
|
|
466
482
|
CACHEKIT_MEMCACHED_TIMEOUT=1.0 # Default: 1.0 seconds
|
|
467
483
|
CACHEKIT_MEMCACHED_KEY_PREFIX="myapp:" # Default: "" (none)
|
|
@@ -471,9 +487,6 @@ CACHEKIT_MAX_VALUE_SIZE=104857600
|
|
|
471
487
|
CACHEKIT_ARROW_COMPRESSION=zstd
|
|
472
488
|
```
|
|
473
489
|
|
|
474
|
-
> [!NOTE]
|
|
475
|
-
> If both `CACHEKIT_REDIS_URL` and `REDIS_URL` are set, `CACHEKIT_REDIS_URL` takes precedence.
|
|
476
|
-
|
|
477
490
|
---
|
|
478
491
|
|
|
479
492
|
## Development
|