exonware-xwsystem 0.0.1.410__py3-none-any.whl → 0.1.0.1__py3-none-any.whl
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.
- exonware/__init__.py +1 -1
- exonware/conf.py +1 -1
- exonware/xwsystem/__init__.py +2 -2
- exonware/xwsystem/caching/__init__.py +1 -1
- exonware/xwsystem/caching/base.py +2 -2
- exonware/xwsystem/caching/bloom_cache.py +2 -2
- exonware/xwsystem/caching/cache_manager.py +1 -1
- exonware/xwsystem/caching/conditional.py +2 -2
- exonware/xwsystem/caching/contracts.py +1 -1
- exonware/xwsystem/caching/decorators.py +2 -2
- exonware/xwsystem/caching/defs.py +1 -1
- exonware/xwsystem/caching/disk_cache.py +1 -1
- exonware/xwsystem/caching/distributed.py +1 -1
- exonware/xwsystem/caching/errors.py +1 -1
- exonware/xwsystem/caching/events.py +2 -2
- exonware/xwsystem/caching/eviction_strategies.py +1 -1
- exonware/xwsystem/caching/fluent.py +1 -1
- exonware/xwsystem/caching/integrity.py +1 -1
- exonware/xwsystem/caching/lfu_cache.py +2 -2
- exonware/xwsystem/caching/lfu_optimized.py +3 -3
- exonware/xwsystem/caching/lru_cache.py +2 -2
- exonware/xwsystem/caching/memory_bounded.py +2 -2
- exonware/xwsystem/caching/metrics_exporter.py +2 -2
- exonware/xwsystem/caching/observable_cache.py +1 -1
- exonware/xwsystem/caching/pluggable_cache.py +2 -2
- exonware/xwsystem/caching/rate_limiter.py +1 -1
- exonware/xwsystem/caching/read_through.py +2 -2
- exonware/xwsystem/caching/secure_cache.py +1 -1
- exonware/xwsystem/caching/serializable.py +2 -2
- exonware/xwsystem/caching/stats.py +1 -1
- exonware/xwsystem/caching/tagging.py +2 -2
- exonware/xwsystem/caching/ttl_cache.py +1 -1
- exonware/xwsystem/caching/two_tier_cache.py +1 -1
- exonware/xwsystem/caching/utils.py +1 -1
- exonware/xwsystem/caching/validation.py +1 -1
- exonware/xwsystem/caching/warming.py +2 -2
- exonware/xwsystem/caching/write_behind.py +2 -2
- exonware/xwsystem/cli/__init__.py +1 -1
- exonware/xwsystem/cli/args.py +1 -1
- exonware/xwsystem/cli/base.py +1 -1
- exonware/xwsystem/cli/colors.py +1 -1
- exonware/xwsystem/cli/console.py +1 -1
- exonware/xwsystem/cli/contracts.py +1 -1
- exonware/xwsystem/cli/defs.py +1 -1
- exonware/xwsystem/cli/errors.py +1 -1
- exonware/xwsystem/cli/progress.py +1 -1
- exonware/xwsystem/cli/prompts.py +1 -1
- exonware/xwsystem/cli/tables.py +1 -1
- exonware/xwsystem/config/__init__.py +1 -1
- exonware/xwsystem/config/base.py +2 -2
- exonware/xwsystem/config/contracts.py +1 -1
- exonware/xwsystem/config/defaults.py +1 -1
- exonware/xwsystem/config/defs.py +1 -1
- exonware/xwsystem/config/errors.py +2 -2
- exonware/xwsystem/config/logging.py +1 -1
- exonware/xwsystem/config/logging_setup.py +2 -2
- exonware/xwsystem/config/performance.py +115 -388
- exonware/xwsystem/http_client/__init__.py +1 -1
- exonware/xwsystem/http_client/advanced_client.py +2 -2
- exonware/xwsystem/http_client/base.py +2 -2
- exonware/xwsystem/http_client/client.py +2 -2
- exonware/xwsystem/http_client/contracts.py +1 -1
- exonware/xwsystem/http_client/defs.py +1 -1
- exonware/xwsystem/http_client/errors.py +2 -2
- exonware/xwsystem/io/__init__.py +1 -1
- exonware/xwsystem/io/archive/__init__.py +1 -1
- exonware/xwsystem/io/archive/archive.py +1 -1
- exonware/xwsystem/io/archive/archive_files.py +1 -1
- exonware/xwsystem/io/archive/archivers.py +2 -2
- exonware/xwsystem/io/archive/base.py +6 -6
- exonware/xwsystem/io/archive/codec_integration.py +1 -1
- exonware/xwsystem/io/archive/compression.py +1 -1
- exonware/xwsystem/io/archive/formats/__init__.py +1 -1
- exonware/xwsystem/io/archive/formats/brotli_format.py +6 -3
- exonware/xwsystem/io/archive/formats/lz4_format.py +6 -3
- exonware/xwsystem/io/archive/formats/rar.py +6 -3
- exonware/xwsystem/io/archive/formats/sevenzip.py +6 -3
- exonware/xwsystem/io/archive/formats/squashfs_format.py +1 -1
- exonware/xwsystem/io/archive/formats/tar.py +1 -1
- exonware/xwsystem/io/archive/formats/wim_format.py +6 -3
- exonware/xwsystem/io/archive/formats/zip.py +1 -1
- exonware/xwsystem/io/archive/formats/zpaq_format.py +1 -1
- exonware/xwsystem/io/archive/formats/zstandard.py +6 -3
- exonware/xwsystem/io/base.py +1 -1
- exonware/xwsystem/io/codec/__init__.py +1 -1
- exonware/xwsystem/io/codec/base.py +6 -6
- exonware/xwsystem/io/codec/contracts.py +1 -1
- exonware/xwsystem/io/codec/registry.py +5 -5
- exonware/xwsystem/io/common/__init__.py +1 -1
- exonware/xwsystem/io/common/base.py +1 -1
- exonware/xwsystem/io/common/lock.py +1 -1
- exonware/xwsystem/io/common/watcher.py +1 -1
- exonware/xwsystem/io/contracts.py +1 -1
- exonware/xwsystem/io/data_operations.py +746 -0
- exonware/xwsystem/io/defs.py +1 -1
- exonware/xwsystem/io/errors.py +1 -1
- exonware/xwsystem/io/facade.py +2 -2
- exonware/xwsystem/io/file/__init__.py +1 -1
- exonware/xwsystem/io/file/base.py +1 -1
- exonware/xwsystem/io/file/conversion.py +1 -1
- exonware/xwsystem/io/file/file.py +8 -6
- exonware/xwsystem/io/file/paged_source.py +8 -1
- exonware/xwsystem/io/file/paging/__init__.py +1 -1
- exonware/xwsystem/io/file/paging/byte_paging.py +1 -1
- exonware/xwsystem/io/file/paging/line_paging.py +1 -1
- exonware/xwsystem/io/file/paging/record_paging.py +1 -1
- exonware/xwsystem/io/file/paging/registry.py +4 -4
- exonware/xwsystem/io/file/source.py +20 -9
- exonware/xwsystem/io/filesystem/__init__.py +1 -1
- exonware/xwsystem/io/filesystem/base.py +1 -1
- exonware/xwsystem/io/filesystem/local.py +9 -1
- exonware/xwsystem/io/folder/__init__.py +1 -1
- exonware/xwsystem/io/folder/base.py +1 -1
- exonware/xwsystem/io/folder/folder.py +2 -2
- exonware/xwsystem/io/serialization/__init__.py +1 -1
- exonware/xwsystem/io/serialization/auto_serializer.py +52 -39
- exonware/xwsystem/io/serialization/base.py +165 -1
- exonware/xwsystem/io/serialization/contracts.py +88 -1
- exonware/xwsystem/io/serialization/defs.py +1 -1
- exonware/xwsystem/io/serialization/errors.py +1 -1
- exonware/xwsystem/io/serialization/flyweight.py +10 -10
- exonware/xwsystem/io/serialization/format_detector.py +8 -5
- exonware/xwsystem/io/serialization/formats/__init__.py +1 -1
- exonware/xwsystem/io/serialization/formats/binary/bson.py +1 -1
- exonware/xwsystem/io/serialization/formats/binary/cbor.py +1 -1
- exonware/xwsystem/io/serialization/formats/binary/marshal.py +1 -1
- exonware/xwsystem/io/serialization/formats/binary/msgpack.py +1 -1
- exonware/xwsystem/io/serialization/formats/binary/pickle.py +1 -1
- exonware/xwsystem/io/serialization/formats/binary/plistlib.py +1 -1
- exonware/xwsystem/io/serialization/formats/database/dbm.py +53 -1
- exonware/xwsystem/io/serialization/formats/database/shelve.py +48 -1
- exonware/xwsystem/io/serialization/formats/database/sqlite3.py +85 -1
- exonware/xwsystem/io/serialization/formats/text/append_only_log.py +201 -0
- exonware/xwsystem/io/serialization/formats/text/configparser.py +1 -1
- exonware/xwsystem/io/serialization/formats/text/csv.py +1 -1
- exonware/xwsystem/io/serialization/formats/text/formdata.py +1 -1
- exonware/xwsystem/io/serialization/formats/text/json.py +43 -20
- exonware/xwsystem/io/serialization/formats/text/json5.py +7 -5
- exonware/xwsystem/io/serialization/formats/text/jsonlines.py +316 -22
- exonware/xwsystem/io/serialization/formats/text/multipart.py +1 -1
- exonware/xwsystem/io/serialization/formats/text/toml.py +19 -3
- exonware/xwsystem/io/serialization/formats/text/xml.py +8 -1
- exonware/xwsystem/io/serialization/formats/text/yaml.py +52 -2
- exonware/xwsystem/io/serialization/parsers/__init__.py +15 -0
- exonware/xwsystem/io/serialization/parsers/base.py +59 -0
- exonware/xwsystem/io/serialization/parsers/hybrid_parser.py +61 -0
- exonware/xwsystem/io/serialization/parsers/msgspec_parser.py +45 -0
- exonware/xwsystem/io/serialization/parsers/orjson_direct_parser.py +53 -0
- exonware/xwsystem/io/serialization/parsers/orjson_parser.py +59 -0
- exonware/xwsystem/io/serialization/parsers/pysimdjson_parser.py +51 -0
- exonware/xwsystem/io/serialization/parsers/rapidjson_parser.py +50 -0
- exonware/xwsystem/io/serialization/parsers/registry.py +90 -0
- exonware/xwsystem/io/serialization/parsers/standard.py +43 -0
- exonware/xwsystem/io/serialization/parsers/ujson_parser.py +50 -0
- exonware/xwsystem/io/serialization/registry.py +1 -1
- exonware/xwsystem/io/serialization/serializer.py +175 -3
- exonware/xwsystem/io/serialization/utils/__init__.py +1 -1
- exonware/xwsystem/io/serialization/utils/path_ops.py +1 -1
- exonware/xwsystem/io/stream/__init__.py +1 -1
- exonware/xwsystem/io/stream/async_operations.py +1 -1
- exonware/xwsystem/io/stream/base.py +1 -1
- exonware/xwsystem/io/stream/codec_io.py +1 -1
- exonware/xwsystem/ipc/async_fabric.py +1 -2
- exonware/xwsystem/ipc/base.py +2 -2
- exonware/xwsystem/ipc/contracts.py +2 -2
- exonware/xwsystem/ipc/defs.py +1 -1
- exonware/xwsystem/ipc/errors.py +2 -2
- exonware/xwsystem/ipc/pipes.py +2 -2
- exonware/xwsystem/ipc/shared_memory.py +2 -2
- exonware/xwsystem/monitoring/base.py +2 -2
- exonware/xwsystem/monitoring/contracts.py +1 -1
- exonware/xwsystem/monitoring/defs.py +1 -1
- exonware/xwsystem/monitoring/error_recovery.py +2 -2
- exonware/xwsystem/monitoring/errors.py +2 -2
- exonware/xwsystem/monitoring/memory_monitor.py +1 -1
- exonware/xwsystem/monitoring/performance_manager_generic.py +2 -2
- exonware/xwsystem/monitoring/performance_validator.py +1 -1
- exonware/xwsystem/monitoring/system_monitor.py +2 -2
- exonware/xwsystem/monitoring/tracing.py +2 -2
- exonware/xwsystem/monitoring/tracker.py +1 -1
- exonware/xwsystem/operations/__init__.py +1 -1
- exonware/xwsystem/operations/base.py +1 -1
- exonware/xwsystem/operations/defs.py +1 -1
- exonware/xwsystem/operations/diff.py +1 -1
- exonware/xwsystem/operations/merge.py +1 -1
- exonware/xwsystem/operations/patch.py +1 -1
- exonware/xwsystem/patterns/base.py +2 -2
- exonware/xwsystem/patterns/context_manager.py +2 -2
- exonware/xwsystem/patterns/contracts.py +9 -9
- exonware/xwsystem/patterns/defs.py +1 -1
- exonware/xwsystem/patterns/dynamic_facade.py +8 -8
- exonware/xwsystem/patterns/errors.py +5 -5
- exonware/xwsystem/patterns/handler_factory.py +6 -6
- exonware/xwsystem/patterns/object_pool.py +7 -7
- exonware/xwsystem/patterns/registry.py +3 -3
- exonware/xwsystem/plugins/__init__.py +1 -1
- exonware/xwsystem/plugins/base.py +5 -5
- exonware/xwsystem/plugins/contracts.py +5 -5
- exonware/xwsystem/plugins/defs.py +1 -1
- exonware/xwsystem/plugins/errors.py +4 -4
- exonware/xwsystem/runtime/__init__.py +1 -1
- exonware/xwsystem/runtime/base.py +6 -6
- exonware/xwsystem/runtime/contracts.py +6 -6
- exonware/xwsystem/runtime/defs.py +1 -1
- exonware/xwsystem/runtime/env.py +2 -2
- exonware/xwsystem/runtime/errors.py +1 -1
- exonware/xwsystem/runtime/reflection.py +8 -8
- exonware/xwsystem/security/auth.py +1 -1
- exonware/xwsystem/security/base.py +2 -2
- exonware/xwsystem/security/contracts.py +1 -1
- exonware/xwsystem/security/crypto.py +2 -2
- exonware/xwsystem/security/defs.py +1 -1
- exonware/xwsystem/security/errors.py +2 -2
- exonware/xwsystem/security/hazmat.py +2 -2
- exonware/xwsystem/shared/__init__.py +1 -1
- exonware/xwsystem/shared/base.py +1 -1
- exonware/xwsystem/shared/contracts.py +1 -1
- exonware/xwsystem/shared/defs.py +1 -1
- exonware/xwsystem/shared/errors.py +1 -1
- exonware/xwsystem/structures/__init__.py +1 -1
- exonware/xwsystem/structures/base.py +2 -2
- exonware/xwsystem/structures/contracts.py +1 -1
- exonware/xwsystem/structures/defs.py +1 -1
- exonware/xwsystem/structures/errors.py +2 -2
- exonware/xwsystem/threading/async_primitives.py +2 -2
- exonware/xwsystem/threading/base.py +2 -2
- exonware/xwsystem/threading/contracts.py +1 -1
- exonware/xwsystem/threading/defs.py +1 -1
- exonware/xwsystem/threading/errors.py +2 -2
- exonware/xwsystem/threading/safe_factory.py +6 -6
- exonware/xwsystem/utils/base.py +2 -2
- exonware/xwsystem/utils/contracts.py +1 -1
- exonware/xwsystem/utils/dt/__init__.py +1 -1
- exonware/xwsystem/utils/dt/base.py +2 -2
- exonware/xwsystem/utils/dt/contracts.py +1 -1
- exonware/xwsystem/utils/dt/defs.py +1 -1
- exonware/xwsystem/utils/dt/errors.py +2 -2
- exonware/xwsystem/utils/dt/formatting.py +1 -1
- exonware/xwsystem/utils/dt/humanize.py +2 -2
- exonware/xwsystem/utils/dt/parsing.py +1 -1
- exonware/xwsystem/utils/dt/timezone_utils.py +1 -1
- exonware/xwsystem/utils/errors.py +2 -2
- exonware/xwsystem/utils/utils_contracts.py +1 -1
- exonware/xwsystem/validation/__init__.py +1 -1
- exonware/xwsystem/validation/base.py +15 -15
- exonware/xwsystem/validation/contracts.py +1 -1
- exonware/xwsystem/validation/data_validator.py +10 -0
- exonware/xwsystem/validation/declarative.py +9 -9
- exonware/xwsystem/validation/defs.py +1 -1
- exonware/xwsystem/validation/errors.py +2 -2
- exonware/xwsystem/validation/fluent_validator.py +4 -4
- exonware/xwsystem/version.py +4 -4
- {exonware_xwsystem-0.0.1.410.dist-info → exonware_xwsystem-0.1.0.1.dist-info}/METADATA +3 -3
- exonware_xwsystem-0.1.0.1.dist-info/RECORD +284 -0
- exonware/xwsystem/caching/USAGE_GUIDE.md +0 -779
- exonware/xwsystem/utils/test_runner.py +0 -526
- exonware_xwsystem-0.0.1.410.dist-info/RECORD +0 -273
- {exonware_xwsystem-0.0.1.410.dist-info → exonware_xwsystem-0.1.0.1.dist-info}/WHEEL +0 -0
- {exonware_xwsystem-0.0.1.410.dist-info → exonware_xwsystem-0.1.0.1.dist-info}/licenses/LICENSE +0 -0
|
@@ -1,779 +0,0 @@
|
|
|
1
|
-
# XWSystem Caching - Complete Usage Guide
|
|
2
|
-
|
|
3
|
-
**Company:** eXonware.com
|
|
4
|
-
**Author:** Eng. Muhammad AlShehri
|
|
5
|
-
**Version:** 0.0.1.388
|
|
6
|
-
**Date:** 01-Nov-2025
|
|
7
|
-
|
|
8
|
-
---
|
|
9
|
-
|
|
10
|
-
## 📚 Table of Contents
|
|
11
|
-
|
|
12
|
-
1. [Quick Start](#quick-start)
|
|
13
|
-
2. [Core Cache Types](#core-cache-types)
|
|
14
|
-
3. [Advanced Cache Types](#advanced-cache-types)
|
|
15
|
-
4. [Decorators](#decorators)
|
|
16
|
-
5. [Security Features](#security-features)
|
|
17
|
-
6. [Performance Optimization](#performance-optimization)
|
|
18
|
-
7. [Integration Patterns](#integration-patterns)
|
|
19
|
-
8. [Best Practices](#best-practices)
|
|
20
|
-
|
|
21
|
-
---
|
|
22
|
-
|
|
23
|
-
## Quick Start
|
|
24
|
-
|
|
25
|
-
### Installation
|
|
26
|
-
|
|
27
|
-
```python
|
|
28
|
-
# Already included in xwsystem
|
|
29
|
-
from exonware.xwsystem.caching import LRUCache
|
|
30
|
-
```
|
|
31
|
-
|
|
32
|
-
### Basic Usage
|
|
33
|
-
|
|
34
|
-
```python
|
|
35
|
-
# Create cache
|
|
36
|
-
cache = LRUCache(capacity=100)
|
|
37
|
-
|
|
38
|
-
# Store data
|
|
39
|
-
cache.put('user:123', {'name': 'Alice'})
|
|
40
|
-
|
|
41
|
-
# Retrieve data
|
|
42
|
-
user = cache.get('user:123')
|
|
43
|
-
|
|
44
|
-
# Dictionary-style access
|
|
45
|
-
cache['product:456'] = {'name': 'Widget'}
|
|
46
|
-
product = cache['product:456']
|
|
47
|
-
```
|
|
48
|
-
|
|
49
|
-
---
|
|
50
|
-
|
|
51
|
-
## Core Cache Types
|
|
52
|
-
|
|
53
|
-
### LRU Cache (Least Recently Used)
|
|
54
|
-
|
|
55
|
-
**Best For:** General-purpose caching
|
|
56
|
-
|
|
57
|
-
```python
|
|
58
|
-
from exonware.xwsystem.caching import LRUCache
|
|
59
|
-
|
|
60
|
-
cache = LRUCache(capacity=1000, ttl=300.0) # Optional TTL
|
|
61
|
-
cache.put('key', 'value')
|
|
62
|
-
value = cache.get('key')
|
|
63
|
-
```
|
|
64
|
-
|
|
65
|
-
**Features:**
|
|
66
|
-
- O(1) get/put operations
|
|
67
|
-
- Thread-safe
|
|
68
|
-
- Optional TTL support
|
|
69
|
-
- Statistics tracking
|
|
70
|
-
|
|
71
|
-
### LFU Cache (Least Frequently Used)
|
|
72
|
-
|
|
73
|
-
**Best For:** Data with varying access patterns
|
|
74
|
-
|
|
75
|
-
⚠️ **Note:** Use `OptimizedLFUCache` for better performance!
|
|
76
|
-
|
|
77
|
-
```python
|
|
78
|
-
from exonware.xwsystem.caching import OptimizedLFUCache
|
|
79
|
-
|
|
80
|
-
cache = OptimizedLFUCache(capacity=1000)
|
|
81
|
-
```
|
|
82
|
-
|
|
83
|
-
**Performance:**
|
|
84
|
-
- Optimized: O(1) eviction (100x+ faster)
|
|
85
|
-
- Standard: O(n) eviction (slow for large caches)
|
|
86
|
-
|
|
87
|
-
### TTL Cache (Time To Live)
|
|
88
|
-
|
|
89
|
-
**Best For:** Time-sensitive data (sessions, tokens)
|
|
90
|
-
|
|
91
|
-
```python
|
|
92
|
-
from exonware.xwsystem.caching import TTLCache
|
|
93
|
-
|
|
94
|
-
cache = TTLCache(capacity=1000, ttl=300.0, cleanup_interval=60.0)
|
|
95
|
-
cache.put('session:abc', session_data, ttl=600.0) # Per-entry TTL
|
|
96
|
-
```
|
|
97
|
-
|
|
98
|
-
---
|
|
99
|
-
|
|
100
|
-
## Advanced Cache Types
|
|
101
|
-
|
|
102
|
-
### ReadThroughCache
|
|
103
|
-
|
|
104
|
-
**Auto-loads from storage on cache miss**
|
|
105
|
-
|
|
106
|
-
```python
|
|
107
|
-
from exonware.xwsystem.caching import ReadThroughCache
|
|
108
|
-
|
|
109
|
-
def load_user(user_id):
|
|
110
|
-
return database.users.find_one({'id': user_id})
|
|
111
|
-
|
|
112
|
-
cache = ReadThroughCache(capacity=1000, loader=load_user)
|
|
113
|
-
|
|
114
|
-
# Automatically loads from DB if not cached
|
|
115
|
-
user = cache.get('user:123')
|
|
116
|
-
```
|
|
117
|
-
|
|
118
|
-
### WriteThroughCache
|
|
119
|
-
|
|
120
|
-
**Auto-persists to storage on cache write**
|
|
121
|
-
|
|
122
|
-
```python
|
|
123
|
-
from exonware.xwsystem.caching import WriteThroughCache
|
|
124
|
-
|
|
125
|
-
def save_user(key, value):
|
|
126
|
-
database.users.update({'id': key}, value)
|
|
127
|
-
|
|
128
|
-
cache = WriteThroughCache(capacity=1000, writer=save_user)
|
|
129
|
-
|
|
130
|
-
# Automatically saves to DB when caching
|
|
131
|
-
cache.put('user:123', user_data)
|
|
132
|
-
```
|
|
133
|
-
|
|
134
|
-
### TaggedCache
|
|
135
|
-
|
|
136
|
-
**Tag-based bulk invalidation**
|
|
137
|
-
|
|
138
|
-
```python
|
|
139
|
-
from exonware.xwsystem.caching import TaggedCache
|
|
140
|
-
|
|
141
|
-
cache = TaggedCache(capacity=1000)
|
|
142
|
-
|
|
143
|
-
# Tag entries
|
|
144
|
-
cache.put('user:1', data, tags=['user', 'active'])
|
|
145
|
-
cache.put('user:2', data, tags=['user', 'inactive'])
|
|
146
|
-
cache.put('admin:1', data, tags=['admin', 'active'])
|
|
147
|
-
|
|
148
|
-
# Bulk invalidation by tag
|
|
149
|
-
cache.invalidate_by_tag('user') # Clears all user entries
|
|
150
|
-
|
|
151
|
-
# Query by tag
|
|
152
|
-
user_keys = cache.get_keys_by_tag('user')
|
|
153
|
-
all_tags = cache.get_all_tags()
|
|
154
|
-
```
|
|
155
|
-
|
|
156
|
-
### WriteBehindCache
|
|
157
|
-
|
|
158
|
-
**Delayed persistence for high throughput**
|
|
159
|
-
|
|
160
|
-
```python
|
|
161
|
-
from exonware.xwsystem.caching import WriteBehindCache
|
|
162
|
-
|
|
163
|
-
def persist_to_db(key, value):
|
|
164
|
-
database.save(key, value)
|
|
165
|
-
|
|
166
|
-
cache = WriteBehindCache(
|
|
167
|
-
capacity=1000,
|
|
168
|
-
writer=persist_to_db,
|
|
169
|
-
flush_interval=5.0 # Flush every 5 seconds
|
|
170
|
-
)
|
|
171
|
-
|
|
172
|
-
# Writes cached immediately, persisted in background
|
|
173
|
-
cache.put('key', 'value')
|
|
174
|
-
|
|
175
|
-
# Force immediate flush
|
|
176
|
-
cache.flush()
|
|
177
|
-
```
|
|
178
|
-
|
|
179
|
-
### BloomFilterCache
|
|
180
|
-
|
|
181
|
-
**Fast negative lookups**
|
|
182
|
-
|
|
183
|
-
```python
|
|
184
|
-
from exonware.xwsystem.caching import BloomFilterCache
|
|
185
|
-
|
|
186
|
-
cache = BloomFilterCache(capacity=10000)
|
|
187
|
-
|
|
188
|
-
# Fast check without cache lookup
|
|
189
|
-
if not cache.might_contain('user:999'):
|
|
190
|
-
return None # Definitely not in cache
|
|
191
|
-
|
|
192
|
-
# Actual lookup
|
|
193
|
-
value = cache.get('user:999')
|
|
194
|
-
```
|
|
195
|
-
|
|
196
|
-
### SerializableCache
|
|
197
|
-
|
|
198
|
-
**Save/load cache state**
|
|
199
|
-
|
|
200
|
-
```python
|
|
201
|
-
from exonware.xwsystem.caching import SerializableCache
|
|
202
|
-
|
|
203
|
-
# Create and populate cache
|
|
204
|
-
cache = SerializableCache(capacity=1000)
|
|
205
|
-
cache.put('key1', 'value1')
|
|
206
|
-
cache.put('key2', 'value2')
|
|
207
|
-
|
|
208
|
-
# Save to disk
|
|
209
|
-
cache.save_to_file('cache_backup.pkl')
|
|
210
|
-
|
|
211
|
-
# Later... load from disk
|
|
212
|
-
cache2 = SerializableCache.load_from_file('cache_backup.pkl')
|
|
213
|
-
assert cache2.get('key1') == 'value1'
|
|
214
|
-
```
|
|
215
|
-
|
|
216
|
-
### ConditionalEvictionCache
|
|
217
|
-
|
|
218
|
-
**Custom eviction rules**
|
|
219
|
-
|
|
220
|
-
```python
|
|
221
|
-
from exonware.xwsystem.caching import ConditionalEvictionCache
|
|
222
|
-
|
|
223
|
-
# Protect entries starting with 'protected:'
|
|
224
|
-
def can_evict(key, value):
|
|
225
|
-
return not str(key).startswith('protected:')
|
|
226
|
-
|
|
227
|
-
cache = ConditionalEvictionCache(
|
|
228
|
-
capacity=100,
|
|
229
|
-
eviction_policy=can_evict
|
|
230
|
-
)
|
|
231
|
-
|
|
232
|
-
cache.put('protected:admin', admin_data) # Won't be evicted
|
|
233
|
-
cache.put('temp:data', temp_data) # Can be evicted
|
|
234
|
-
```
|
|
235
|
-
|
|
236
|
-
---
|
|
237
|
-
|
|
238
|
-
## Decorators
|
|
239
|
-
|
|
240
|
-
### @xwcached - Simple Function Caching
|
|
241
|
-
|
|
242
|
-
```python
|
|
243
|
-
from exonware.xwsystem.caching import xwcached
|
|
244
|
-
|
|
245
|
-
@xwcached(ttl=300)
|
|
246
|
-
def get_user_profile(user_id):
|
|
247
|
-
# Expensive database query
|
|
248
|
-
return db.query(f"SELECT * FROM users WHERE id = {user_id}")
|
|
249
|
-
|
|
250
|
-
# First call - queries database
|
|
251
|
-
profile = get_user_profile(123)
|
|
252
|
-
|
|
253
|
-
# Second call - uses cache
|
|
254
|
-
profile = get_user_profile(123) # Instant!
|
|
255
|
-
```
|
|
256
|
-
|
|
257
|
-
### @xwcached - Advanced with Hooks
|
|
258
|
-
|
|
259
|
-
```python
|
|
260
|
-
from exonware.xwsystem.caching import xwcached
|
|
261
|
-
|
|
262
|
-
hits = []
|
|
263
|
-
misses = []
|
|
264
|
-
|
|
265
|
-
@xwcached(
|
|
266
|
-
namespace="user_api",
|
|
267
|
-
condition=lambda args, kwargs: args[0] > 0, # Only cache positive IDs
|
|
268
|
-
on_hit=lambda k, v: hits.append(k),
|
|
269
|
-
on_miss=lambda k, v: misses.append(k),
|
|
270
|
-
key_builder=lambda f, a, kw: f"user:{a[0]}"
|
|
271
|
-
)
|
|
272
|
-
def get_user(user_id):
|
|
273
|
-
return database.get_user(user_id)
|
|
274
|
-
```
|
|
275
|
-
|
|
276
|
-
### @xw_async_cached - Async Functions
|
|
277
|
-
|
|
278
|
-
```python
|
|
279
|
-
from exonware.xwsystem.caching import xw_async_cached
|
|
280
|
-
|
|
281
|
-
@xw_async_cached(ttl=60)
|
|
282
|
-
async def fetch_api_data(endpoint):
|
|
283
|
-
async with httpx.AsyncClient() as client:
|
|
284
|
-
response = await client.get(endpoint)
|
|
285
|
-
return response.json()
|
|
286
|
-
|
|
287
|
-
# Automatic caching
|
|
288
|
-
data = await fetch_api_data("https://api.example.com/data")
|
|
289
|
-
```
|
|
290
|
-
|
|
291
|
-
---
|
|
292
|
-
|
|
293
|
-
## Security Features
|
|
294
|
-
|
|
295
|
-
### SecureLRUCache - Production Caching
|
|
296
|
-
|
|
297
|
-
```python
|
|
298
|
-
from exonware.xwsystem.caching import SecureLRUCache
|
|
299
|
-
|
|
300
|
-
cache = SecureLRUCache(
|
|
301
|
-
capacity=1000,
|
|
302
|
-
enable_integrity=True, # Checksum verification
|
|
303
|
-
enable_rate_limit=True, # DoS protection
|
|
304
|
-
max_ops_per_second=10000, # Rate limit
|
|
305
|
-
max_key_size=1024, # Max key size (1KB)
|
|
306
|
-
max_value_size_mb=10.0 # Max value size (10MB)
|
|
307
|
-
)
|
|
308
|
-
|
|
309
|
-
# Automatic validation
|
|
310
|
-
cache.put('api_response', large_data) # Validates size
|
|
311
|
-
value = cache.get('api_response') # Verifies integrity
|
|
312
|
-
|
|
313
|
-
# Security stats
|
|
314
|
-
stats = cache.get_security_stats()
|
|
315
|
-
print(f"Integrity violations: {stats['integrity_violations']}")
|
|
316
|
-
```
|
|
317
|
-
|
|
318
|
-
### Input Validation
|
|
319
|
-
|
|
320
|
-
```python
|
|
321
|
-
from exonware.xwsystem.caching import validate_cache_key, validate_cache_value
|
|
322
|
-
|
|
323
|
-
# Validate before caching
|
|
324
|
-
validate_cache_key(user_input_key)
|
|
325
|
-
validate_cache_value(user_data)
|
|
326
|
-
|
|
327
|
-
# Sanitize keys
|
|
328
|
-
from exonware.xwsystem.caching import sanitize_key
|
|
329
|
-
safe_key = sanitize_key(complex_object)
|
|
330
|
-
```
|
|
331
|
-
|
|
332
|
-
---
|
|
333
|
-
|
|
334
|
-
## Performance Optimization
|
|
335
|
-
|
|
336
|
-
### Memory-Bounded Caching
|
|
337
|
-
|
|
338
|
-
```python
|
|
339
|
-
from exonware.xwsystem.caching import MemoryBoundedLRUCache
|
|
340
|
-
|
|
341
|
-
# Cache limited by memory, not entry count
|
|
342
|
-
cache = MemoryBoundedLRUCache(
|
|
343
|
-
capacity=10000, # Fallback limit
|
|
344
|
-
memory_budget_mb=500.0 # Primary: 500MB
|
|
345
|
-
)
|
|
346
|
-
|
|
347
|
-
# Automatically evicts to stay under budget
|
|
348
|
-
cache.put('large_dataset', huge_dataframe)
|
|
349
|
-
```
|
|
350
|
-
|
|
351
|
-
### Batch Operations
|
|
352
|
-
|
|
353
|
-
```python
|
|
354
|
-
from exonware.xwsystem.caching import OptimizedLFUCache
|
|
355
|
-
|
|
356
|
-
cache = OptimizedLFUCache(capacity=1000)
|
|
357
|
-
|
|
358
|
-
# Efficient batch operations
|
|
359
|
-
items = {'key1': 'value1', 'key2': 'value2', 'key3': 'value3'}
|
|
360
|
-
cache.put_many(items)
|
|
361
|
-
|
|
362
|
-
keys = ['key1', 'key2', 'key3']
|
|
363
|
-
results = cache.get_many(keys)
|
|
364
|
-
|
|
365
|
-
cache.delete_many(['key1', 'key2'])
|
|
366
|
-
```
|
|
367
|
-
|
|
368
|
-
### Prometheus Metrics
|
|
369
|
-
|
|
370
|
-
```python
|
|
371
|
-
from exonware.xwsystem.caching import LRUCache, PrometheusExporter
|
|
372
|
-
|
|
373
|
-
cache = LRUCache(capacity=1000, name="user_cache")
|
|
374
|
-
exporter = PrometheusExporter(cache)
|
|
375
|
-
|
|
376
|
-
# Export metrics
|
|
377
|
-
metrics = exporter.export_metrics()
|
|
378
|
-
|
|
379
|
-
# Use with Flask/FastAPI
|
|
380
|
-
@app.get("/metrics")
|
|
381
|
-
def metrics_endpoint():
|
|
382
|
-
return Response(exporter.export_metrics(), media_type="text/plain")
|
|
383
|
-
```
|
|
384
|
-
|
|
385
|
-
---
|
|
386
|
-
|
|
387
|
-
## Integration Patterns
|
|
388
|
-
|
|
389
|
-
### Cache-Aside Pattern
|
|
390
|
-
|
|
391
|
-
```python
|
|
392
|
-
from exonware.xwsystem.caching import LRUCache
|
|
393
|
-
|
|
394
|
-
cache = LRUCache(capacity=1000)
|
|
395
|
-
|
|
396
|
-
def get_user(user_id):
|
|
397
|
-
# 1. Try cache
|
|
398
|
-
user = cache.get(f'user:{user_id}')
|
|
399
|
-
if user:
|
|
400
|
-
return user
|
|
401
|
-
|
|
402
|
-
# 2. Load from DB
|
|
403
|
-
user = db.users.find_one({'id': user_id})
|
|
404
|
-
|
|
405
|
-
# 3. Store in cache
|
|
406
|
-
if user:
|
|
407
|
-
cache.put(f'user:{user_id}', user)
|
|
408
|
-
|
|
409
|
-
return user
|
|
410
|
-
```
|
|
411
|
-
|
|
412
|
-
### Multi-Tier Caching
|
|
413
|
-
|
|
414
|
-
```python
|
|
415
|
-
from exonware.xwsystem.caching import LRUCache, TTLCache
|
|
416
|
-
|
|
417
|
-
# L1: Hot data (fast, small)
|
|
418
|
-
l1 = LRUCache(capacity=100)
|
|
419
|
-
|
|
420
|
-
# L2: Warm data (medium)
|
|
421
|
-
l2 = TTLCache(capacity=1000, ttl=3600)
|
|
422
|
-
|
|
423
|
-
def get_with_tiers(key):
|
|
424
|
-
value = l1.get(key)
|
|
425
|
-
if value: return value
|
|
426
|
-
|
|
427
|
-
value = l2.get(key)
|
|
428
|
-
if value:
|
|
429
|
-
l1.put(key, value) # Promote to L1
|
|
430
|
-
return value
|
|
431
|
-
|
|
432
|
-
value = expensive_load(key)
|
|
433
|
-
l2.put(key, value)
|
|
434
|
-
return value
|
|
435
|
-
```
|
|
436
|
-
|
|
437
|
-
### Async Patterns
|
|
438
|
-
|
|
439
|
-
```python
|
|
440
|
-
from exonware.xwsystem.caching import AsyncLRUCache
|
|
441
|
-
|
|
442
|
-
cache = AsyncLRUCache(capacity=500)
|
|
443
|
-
|
|
444
|
-
# Async context manager
|
|
445
|
-
async with AsyncLRUCache(100) as temp_cache:
|
|
446
|
-
await temp_cache.put('temp', data)
|
|
447
|
-
|
|
448
|
-
# Async iteration
|
|
449
|
-
async for key in cache:
|
|
450
|
-
value = await cache.get(key)
|
|
451
|
-
print(f"{key}: {value}")
|
|
452
|
-
|
|
453
|
-
async for key, value in cache.items_async():
|
|
454
|
-
print(f"{key}: {value}")
|
|
455
|
-
```
|
|
456
|
-
|
|
457
|
-
---
|
|
458
|
-
|
|
459
|
-
## Best Practices
|
|
460
|
-
|
|
461
|
-
### 1. Choose the Right Cache Type
|
|
462
|
-
|
|
463
|
-
| Use Case | Recommended Cache | Reason |
|
|
464
|
-
|----------|------------------|--------|
|
|
465
|
-
| API responses | TTLCache | Auto-expiration |
|
|
466
|
-
| Database queries | ReadThroughCache | Auto-loading |
|
|
467
|
-
| User sessions | TTLCache + Secure | Time-based + security |
|
|
468
|
-
| ML models | MemoryBoundedLRUCache | Control memory |
|
|
469
|
-
| Hot paths | OptimizedLFUCache | Frequency-based |
|
|
470
|
-
| High writes | WriteBehindCache | Better throughput |
|
|
471
|
-
| High misses | BloomFilterCache | Fast negative lookup |
|
|
472
|
-
|
|
473
|
-
### 2. Set Appropriate Capacity
|
|
474
|
-
|
|
475
|
-
```python
|
|
476
|
-
# Too small - frequent evictions
|
|
477
|
-
cache = LRUCache(capacity=10) # ❌ Bad
|
|
478
|
-
|
|
479
|
-
# Reasonable size
|
|
480
|
-
cache = LRUCache(capacity=1000) # ✅ Good
|
|
481
|
-
|
|
482
|
-
# Very large - use optimized version
|
|
483
|
-
cache = OptimizedLFUCache(capacity=100000) # ✅ Use optimized for large
|
|
484
|
-
```
|
|
485
|
-
|
|
486
|
-
### 3. Use Security Features in Production
|
|
487
|
-
|
|
488
|
-
```python
|
|
489
|
-
# Development
|
|
490
|
-
cache = LRUCache(capacity=100) # ✅ OK for dev
|
|
491
|
-
|
|
492
|
-
# Production
|
|
493
|
-
cache = SecureLRUCache( # ✅ Use secure in production
|
|
494
|
-
capacity=1000,
|
|
495
|
-
enable_integrity=True,
|
|
496
|
-
enable_rate_limit=True
|
|
497
|
-
)
|
|
498
|
-
```
|
|
499
|
-
|
|
500
|
-
### 4. Monitor Performance
|
|
501
|
-
|
|
502
|
-
```python
|
|
503
|
-
from exonware.xwsystem.caching import PrometheusExporter
|
|
504
|
-
|
|
505
|
-
cache = LRUCache(capacity=1000, name="my_cache")
|
|
506
|
-
exporter = PrometheusExporter(cache)
|
|
507
|
-
|
|
508
|
-
# Regular monitoring
|
|
509
|
-
stats = cache.get_stats()
|
|
510
|
-
if stats['hit_rate'] < 0.5:
|
|
511
|
-
print("Low hit rate - consider adjusting capacity or TTL")
|
|
512
|
-
```
|
|
513
|
-
|
|
514
|
-
### 5. Handle Errors Gracefully
|
|
515
|
-
|
|
516
|
-
```python
|
|
517
|
-
from exonware.xwsystem.caching import CacheError
|
|
518
|
-
|
|
519
|
-
try:
|
|
520
|
-
cache.put(large_key, large_value)
|
|
521
|
-
except CacheKeySizeError:
|
|
522
|
-
# Use hash of key instead
|
|
523
|
-
cache.put(hash(large_key), large_value)
|
|
524
|
-
except CacheValueSizeError:
|
|
525
|
-
# Store reference instead of full value
|
|
526
|
-
cache.put(key, {'ref': value_id})
|
|
527
|
-
```
|
|
528
|
-
|
|
529
|
-
---
|
|
530
|
-
|
|
531
|
-
## Common Use Cases
|
|
532
|
-
|
|
533
|
-
### Web API Caching
|
|
534
|
-
|
|
535
|
-
```python
|
|
536
|
-
from exonware.xwsystem.caching import TTLCache, xwcached
|
|
537
|
-
|
|
538
|
-
response_cache = TTLCache(capacity=5000, ttl=300)
|
|
539
|
-
|
|
540
|
-
@app.get("/users/{user_id}")
|
|
541
|
-
@xwcached(cache=response_cache, ttl=300)
|
|
542
|
-
def get_user_endpoint(user_id: int):
|
|
543
|
-
return db.users.get(user_id)
|
|
544
|
-
```
|
|
545
|
-
|
|
546
|
-
### Database Query Caching
|
|
547
|
-
|
|
548
|
-
```python
|
|
549
|
-
from exonware.xwsystem.caching import ReadThroughCache
|
|
550
|
-
|
|
551
|
-
query_cache = ReadThroughCache(
|
|
552
|
-
capacity=1000,
|
|
553
|
-
loader=lambda query_id: execute_query(query_id)
|
|
554
|
-
)
|
|
555
|
-
|
|
556
|
-
result = query_cache.get('complex_query_123') # Auto-executes if not cached
|
|
557
|
-
```
|
|
558
|
-
|
|
559
|
-
### Session Management
|
|
560
|
-
|
|
561
|
-
```python
|
|
562
|
-
from exonware.xwsystem.caching import SecureTTLCache
|
|
563
|
-
|
|
564
|
-
session_cache = SecureTTLCache(
|
|
565
|
-
capacity=10000,
|
|
566
|
-
ttl=1800.0, # 30 minutes
|
|
567
|
-
enable_rate_limit=True
|
|
568
|
-
)
|
|
569
|
-
|
|
570
|
-
session_cache.put(session_id, session_data)
|
|
571
|
-
```
|
|
572
|
-
|
|
573
|
-
### ML Model Caching
|
|
574
|
-
|
|
575
|
-
```python
|
|
576
|
-
from exonware.xwsystem.caching import MemoryBoundedLRUCache, xwcached
|
|
577
|
-
|
|
578
|
-
model_cache = MemoryBoundedLRUCache(
|
|
579
|
-
capacity=10,
|
|
580
|
-
memory_budget_mb=2000.0 # 2GB for models
|
|
581
|
-
)
|
|
582
|
-
|
|
583
|
-
@xwcached(cache=model_cache)
|
|
584
|
-
def load_model(model_name):
|
|
585
|
-
return torch.load(f"models/{model_name}.pth")
|
|
586
|
-
```
|
|
587
|
-
|
|
588
|
-
### Configuration Caching
|
|
589
|
-
|
|
590
|
-
```python
|
|
591
|
-
from exonware.xwsystem.caching import TTLCache, xwcached
|
|
592
|
-
|
|
593
|
-
config_cache = TTLCache(capacity=50, ttl=600)
|
|
594
|
-
|
|
595
|
-
@xwcached(cache=config_cache)
|
|
596
|
-
def load_config(config_name):
|
|
597
|
-
return yaml.safe_load(open(f"configs/{config_name}.yaml"))
|
|
598
|
-
```
|
|
599
|
-
|
|
600
|
-
---
|
|
601
|
-
|
|
602
|
-
## Performance Tips
|
|
603
|
-
|
|
604
|
-
### 1. Use Optimized Versions
|
|
605
|
-
|
|
606
|
-
```python
|
|
607
|
-
# ❌ Slow for large caches
|
|
608
|
-
cache = LFUCache(capacity=10000) # O(n) eviction
|
|
609
|
-
|
|
610
|
-
# ✅ Fast for any size
|
|
611
|
-
cache = OptimizedLFUCache(capacity=10000) # O(1) eviction
|
|
612
|
-
```
|
|
613
|
-
|
|
614
|
-
### 2. Batch Operations
|
|
615
|
-
|
|
616
|
-
```python
|
|
617
|
-
# ❌ Slow - multiple lock acquisitions
|
|
618
|
-
for key, value in items.items():
|
|
619
|
-
cache.put(key, value)
|
|
620
|
-
|
|
621
|
-
# ✅ Fast - single lock
|
|
622
|
-
cache.put_many(items)
|
|
623
|
-
```
|
|
624
|
-
|
|
625
|
-
### 3. Use Bloom Filters for High Miss Rates
|
|
626
|
-
|
|
627
|
-
```python
|
|
628
|
-
from exonware.xwsystem.caching import BloomFilterCache
|
|
629
|
-
|
|
630
|
-
cache = BloomFilterCache(capacity=10000)
|
|
631
|
-
|
|
632
|
-
# Fast rejection without locking
|
|
633
|
-
if not cache.might_contain(key):
|
|
634
|
-
return None # Skip expensive lookup
|
|
635
|
-
```
|
|
636
|
-
|
|
637
|
-
### 4. Async for Async Code
|
|
638
|
-
|
|
639
|
-
```python
|
|
640
|
-
# ❌ Don't use sync cache in async code
|
|
641
|
-
cache = LRUCache(capacity=100)
|
|
642
|
-
value = cache.get(key) # Blocks event loop
|
|
643
|
-
|
|
644
|
-
# ✅ Use async cache
|
|
645
|
-
cache = AsyncLRUCache(capacity=100)
|
|
646
|
-
value = await cache.get(key) # Non-blocking
|
|
647
|
-
```
|
|
648
|
-
|
|
649
|
-
---
|
|
650
|
-
|
|
651
|
-
## Monitoring & Observability
|
|
652
|
-
|
|
653
|
-
### Statistics Collection
|
|
654
|
-
|
|
655
|
-
```python
|
|
656
|
-
stats = cache.get_stats()
|
|
657
|
-
|
|
658
|
-
print(f"Hit Rate: {stats['hit_rate']:.2%}")
|
|
659
|
-
print(f"Size: {stats['size']}/{stats['capacity']}")
|
|
660
|
-
print(f"Evictions: {stats['evictions']}")
|
|
661
|
-
```
|
|
662
|
-
|
|
663
|
-
### Multi-Cache Monitoring
|
|
664
|
-
|
|
665
|
-
```python
|
|
666
|
-
from exonware.xwsystem.caching import StatsCollector
|
|
667
|
-
|
|
668
|
-
collector = StatsCollector()
|
|
669
|
-
collector.register('users', user_cache)
|
|
670
|
-
collector.register('products', product_cache)
|
|
671
|
-
collector.register('sessions', session_cache)
|
|
672
|
-
|
|
673
|
-
# Collect all stats
|
|
674
|
-
all_stats = collector.collect_all()
|
|
675
|
-
|
|
676
|
-
# Export for Prometheus
|
|
677
|
-
metrics = collector.export_prometheus()
|
|
678
|
-
```
|
|
679
|
-
|
|
680
|
-
---
|
|
681
|
-
|
|
682
|
-
## Migration Guide
|
|
683
|
-
|
|
684
|
-
### From functools.lru_cache
|
|
685
|
-
|
|
686
|
-
```python
|
|
687
|
-
# Before
|
|
688
|
-
from functools import lru_cache
|
|
689
|
-
|
|
690
|
-
@lru_cache(maxsize=128)
|
|
691
|
-
def my_function(x):
|
|
692
|
-
return x * 2
|
|
693
|
-
|
|
694
|
-
# After
|
|
695
|
-
from exonware.xwsystem.caching import xwcache
|
|
696
|
-
|
|
697
|
-
@xwcache
|
|
698
|
-
def my_function(x):
|
|
699
|
-
return x * 2
|
|
700
|
-
|
|
701
|
-
# Benefits: hooks, TTL, statistics, custom key builders
|
|
702
|
-
```
|
|
703
|
-
|
|
704
|
-
### From cachetools
|
|
705
|
-
|
|
706
|
-
```python
|
|
707
|
-
# Before
|
|
708
|
-
from cachetools import LRUCache, cached
|
|
709
|
-
|
|
710
|
-
cache = LRUCache(maxsize=100)
|
|
711
|
-
|
|
712
|
-
@cached(cache)
|
|
713
|
-
def my_function(x):
|
|
714
|
-
return x * 2
|
|
715
|
-
|
|
716
|
-
# After
|
|
717
|
-
from exonware.xwsystem.caching import LRUCache, xwcached
|
|
718
|
-
|
|
719
|
-
cache = LRUCache(capacity=100)
|
|
720
|
-
|
|
721
|
-
@xwcached(cache=cache)
|
|
722
|
-
def my_function(x):
|
|
723
|
-
return x * 2
|
|
724
|
-
|
|
725
|
-
# Benefits: security features, better stats, async support
|
|
726
|
-
```
|
|
727
|
-
|
|
728
|
-
---
|
|
729
|
-
|
|
730
|
-
## Error Handling
|
|
731
|
-
|
|
732
|
-
```python
|
|
733
|
-
from exonware.xwsystem.caching import (
|
|
734
|
-
CacheError,
|
|
735
|
-
CacheKeySizeError,
|
|
736
|
-
CacheValueSizeError,
|
|
737
|
-
CacheRateLimitError,
|
|
738
|
-
CacheIntegrityError,
|
|
739
|
-
)
|
|
740
|
-
|
|
741
|
-
try:
|
|
742
|
-
cache.put(key, value)
|
|
743
|
-
except CacheKeySizeError:
|
|
744
|
-
# Key too large
|
|
745
|
-
cache.put(hash(key), value)
|
|
746
|
-
except CacheValueSizeError:
|
|
747
|
-
# Value too large
|
|
748
|
-
cache.put(key, compress(value))
|
|
749
|
-
except CacheRateLimitError:
|
|
750
|
-
# Rate limit exceeded
|
|
751
|
-
time.sleep(0.1)
|
|
752
|
-
except CacheIntegrityError:
|
|
753
|
-
# Integrity check failed
|
|
754
|
-
cache.delete(key)
|
|
755
|
-
```
|
|
756
|
-
|
|
757
|
-
---
|
|
758
|
-
|
|
759
|
-
## See Also
|
|
760
|
-
|
|
761
|
-
- [Examples Directory](../../../examples/caching/)
|
|
762
|
-
- [Test Suite](../../../tests/)
|
|
763
|
-
- [API Reference](./contracts.py)
|
|
764
|
-
- [GUIDELINES_DEV.md](../../../docs/GUIDELINES_DEV.md)
|
|
765
|
-
- [GUIDELINES_TEST.md](../../../docs/GUIDELINES_TEST.md)
|
|
766
|
-
|
|
767
|
-
---
|
|
768
|
-
|
|
769
|
-
## Support
|
|
770
|
-
|
|
771
|
-
**Company:** eXonware.com
|
|
772
|
-
**Email:** connect@exonware.com
|
|
773
|
-
**Documentation:** https://exonware.com/docs/xwsystem/caching
|
|
774
|
-
|
|
775
|
-
---
|
|
776
|
-
|
|
777
|
-
**Last Updated:** 01-Nov-2025
|
|
778
|
-
**Version:** 0.0.1.388
|
|
779
|
-
|