exonware-xwsystem 0.0.1.411__py3-none-any.whl → 0.1.0.3__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 +2 -1
- exonware/conf.py +2 -2
- exonware/xwsystem/__init__.py +115 -43
- exonware/xwsystem/base.py +30 -0
- exonware/xwsystem/caching/__init__.py +39 -13
- exonware/xwsystem/caching/base.py +24 -6
- exonware/xwsystem/caching/bloom_cache.py +2 -2
- exonware/xwsystem/caching/cache_manager.py +2 -1
- exonware/xwsystem/caching/conditional.py +2 -2
- exonware/xwsystem/caching/contracts.py +85 -139
- exonware/xwsystem/caching/decorators.py +6 -19
- exonware/xwsystem/caching/defs.py +2 -1
- exonware/xwsystem/caching/disk_cache.py +2 -1
- exonware/xwsystem/caching/distributed.py +2 -1
- exonware/xwsystem/caching/errors.py +2 -1
- exonware/xwsystem/caching/events.py +110 -27
- exonware/xwsystem/caching/eviction_strategies.py +2 -2
- exonware/xwsystem/caching/external_caching_python.py +701 -0
- exonware/xwsystem/caching/facade.py +253 -0
- exonware/xwsystem/caching/factory.py +300 -0
- exonware/xwsystem/caching/fluent.py +14 -12
- exonware/xwsystem/caching/integrity.py +21 -6
- exonware/xwsystem/caching/lfu_cache.py +2 -1
- exonware/xwsystem/caching/lfu_optimized.py +18 -6
- exonware/xwsystem/caching/lru_cache.py +7 -4
- exonware/xwsystem/caching/memory_bounded.py +2 -2
- exonware/xwsystem/caching/metrics_exporter.py +2 -2
- exonware/xwsystem/caching/observable_cache.py +2 -2
- exonware/xwsystem/caching/pluggable_cache.py +2 -2
- exonware/xwsystem/caching/rate_limiter.py +2 -2
- exonware/xwsystem/caching/read_through.py +2 -2
- exonware/xwsystem/caching/secure_cache.py +81 -28
- exonware/xwsystem/caching/serializable.py +9 -7
- exonware/xwsystem/caching/stats.py +2 -2
- exonware/xwsystem/caching/tagging.py +2 -2
- exonware/xwsystem/caching/ttl_cache.py +4 -3
- exonware/xwsystem/caching/two_tier_cache.py +6 -3
- exonware/xwsystem/caching/utils.py +30 -12
- exonware/xwsystem/caching/validation.py +2 -2
- exonware/xwsystem/caching/warming.py +6 -3
- exonware/xwsystem/caching/write_behind.py +15 -6
- exonware/xwsystem/config/__init__.py +11 -17
- exonware/xwsystem/config/base.py +5 -5
- exonware/xwsystem/config/contracts.py +93 -153
- exonware/xwsystem/config/defaults.py +3 -2
- exonware/xwsystem/config/defs.py +3 -2
- exonware/xwsystem/config/errors.py +2 -5
- exonware/xwsystem/config/logging.py +12 -8
- exonware/xwsystem/config/logging_setup.py +3 -2
- exonware/xwsystem/config/performance.py +73 -391
- exonware/xwsystem/config/performance_modes.py +9 -8
- exonware/xwsystem/config/version_manager.py +1 -0
- exonware/xwsystem/config.py +27 -0
- exonware/xwsystem/console/__init__.py +53 -0
- exonware/xwsystem/console/base.py +133 -0
- exonware/xwsystem/console/cli/__init__.py +61 -0
- exonware/xwsystem/{cli → console/cli}/args.py +27 -24
- exonware/xwsystem/{cli → console/cli}/base.py +18 -87
- exonware/xwsystem/{cli → console/cli}/colors.py +15 -13
- exonware/xwsystem/console/cli/console.py +98 -0
- exonware/xwsystem/{cli → console/cli}/contracts.py +51 -69
- exonware/xwsystem/console/cli/defs.py +87 -0
- exonware/xwsystem/console/cli/encoding.py +69 -0
- exonware/xwsystem/{cli → console/cli}/errors.py +8 -3
- exonware/xwsystem/console/cli/event_logger.py +166 -0
- exonware/xwsystem/{cli → console/cli}/progress.py +25 -21
- exonware/xwsystem/{cli → console/cli}/prompts.py +3 -2
- exonware/xwsystem/{cli → console/cli}/tables.py +27 -24
- exonware/xwsystem/console/contracts.py +113 -0
- exonware/xwsystem/console/defs.py +154 -0
- exonware/xwsystem/console/errors.py +34 -0
- exonware/xwsystem/console/event_logger.py +385 -0
- exonware/xwsystem/console/writer.py +132 -0
- exonware/xwsystem/contracts.py +28 -0
- exonware/xwsystem/data_structures/__init__.py +23 -0
- exonware/xwsystem/data_structures/trie.py +34 -0
- exonware/xwsystem/data_structures/union_find.py +144 -0
- exonware/xwsystem/defs.py +17 -0
- exonware/xwsystem/errors.py +23 -0
- exonware/xwsystem/facade.py +62 -0
- exonware/xwsystem/http_client/__init__.py +22 -1
- exonware/xwsystem/http_client/advanced_client.py +8 -5
- exonware/xwsystem/http_client/base.py +3 -2
- exonware/xwsystem/http_client/client.py +7 -4
- exonware/xwsystem/http_client/contracts.py +42 -56
- exonware/xwsystem/http_client/defs.py +2 -1
- exonware/xwsystem/http_client/errors.py +2 -1
- exonware/xwsystem/http_client/facade.py +156 -0
- exonware/xwsystem/io/__init__.py +22 -3
- exonware/xwsystem/io/archive/__init__.py +8 -2
- exonware/xwsystem/io/archive/archive.py +1 -1
- exonware/xwsystem/io/archive/archive_files.py +4 -7
- exonware/xwsystem/io/archive/archivers.py +120 -10
- exonware/xwsystem/io/archive/base.py +4 -5
- exonware/xwsystem/io/archive/codec_integration.py +1 -2
- exonware/xwsystem/io/archive/compression.py +1 -2
- exonware/xwsystem/io/archive/facade.py +263 -0
- exonware/xwsystem/io/archive/formats/__init__.py +2 -3
- exonware/xwsystem/io/archive/formats/brotli_format.py +20 -7
- exonware/xwsystem/io/archive/formats/lz4_format.py +20 -7
- exonware/xwsystem/io/archive/formats/rar.py +11 -5
- exonware/xwsystem/io/archive/formats/sevenzip.py +12 -6
- exonware/xwsystem/io/archive/formats/squashfs_format.py +1 -2
- exonware/xwsystem/io/archive/formats/tar.py +52 -7
- exonware/xwsystem/io/archive/formats/wim_format.py +11 -5
- exonware/xwsystem/io/archive/formats/zip.py +1 -2
- exonware/xwsystem/io/archive/formats/zpaq_format.py +1 -2
- exonware/xwsystem/io/archive/formats/zstandard.py +20 -7
- exonware/xwsystem/io/base.py +119 -115
- exonware/xwsystem/io/codec/__init__.py +4 -2
- exonware/xwsystem/io/codec/base.py +19 -13
- exonware/xwsystem/io/codec/contracts.py +59 -2
- exonware/xwsystem/io/codec/registry.py +67 -21
- exonware/xwsystem/io/common/__init__.py +1 -1
- exonware/xwsystem/io/common/atomic.py +29 -16
- exonware/xwsystem/io/common/base.py +11 -10
- exonware/xwsystem/io/common/lock.py +6 -5
- exonware/xwsystem/io/common/path_manager.py +2 -1
- exonware/xwsystem/io/common/watcher.py +1 -2
- exonware/xwsystem/io/contracts.py +301 -433
- exonware/xwsystem/io/contracts_1.py +1180 -0
- exonware/xwsystem/io/data_operations.py +279 -14
- exonware/xwsystem/io/defs.py +4 -3
- exonware/xwsystem/io/errors.py +3 -2
- exonware/xwsystem/io/facade.py +87 -61
- exonware/xwsystem/io/file/__init__.py +1 -1
- exonware/xwsystem/io/file/base.py +8 -9
- exonware/xwsystem/io/file/conversion.py +2 -3
- exonware/xwsystem/io/file/file.py +61 -18
- exonware/xwsystem/io/file/paged_source.py +8 -8
- exonware/xwsystem/io/file/paging/__init__.py +1 -2
- exonware/xwsystem/io/file/paging/byte_paging.py +4 -5
- exonware/xwsystem/io/file/paging/line_paging.py +2 -3
- exonware/xwsystem/io/file/paging/record_paging.py +2 -3
- exonware/xwsystem/io/file/paging/registry.py +1 -2
- exonware/xwsystem/io/file/source.py +13 -17
- exonware/xwsystem/io/filesystem/__init__.py +1 -1
- exonware/xwsystem/io/filesystem/base.py +1 -2
- exonware/xwsystem/io/filesystem/local.py +3 -4
- exonware/xwsystem/io/folder/__init__.py +1 -1
- exonware/xwsystem/io/folder/base.py +1 -2
- exonware/xwsystem/io/folder/folder.py +16 -7
- exonware/xwsystem/io/indexing/__init__.py +14 -0
- exonware/xwsystem/io/indexing/facade.py +443 -0
- exonware/xwsystem/io/path_parser.py +98 -0
- exonware/xwsystem/io/serialization/__init__.py +21 -3
- exonware/xwsystem/io/serialization/auto_serializer.py +146 -20
- exonware/xwsystem/io/serialization/base.py +84 -34
- exonware/xwsystem/io/serialization/contracts.py +50 -73
- exonware/xwsystem/io/serialization/defs.py +2 -1
- exonware/xwsystem/io/serialization/errors.py +2 -1
- exonware/xwsystem/io/serialization/flyweight.py +154 -7
- exonware/xwsystem/io/serialization/format_detector.py +15 -14
- exonware/xwsystem/io/serialization/formats/__init__.py +8 -5
- exonware/xwsystem/io/serialization/formats/binary/bson.py +15 -6
- exonware/xwsystem/io/serialization/formats/binary/cbor.py +5 -5
- exonware/xwsystem/io/serialization/formats/binary/marshal.py +5 -5
- exonware/xwsystem/io/serialization/formats/binary/msgpack.py +5 -5
- exonware/xwsystem/io/serialization/formats/binary/pickle.py +5 -5
- exonware/xwsystem/io/serialization/formats/binary/plistlib.py +5 -5
- exonware/xwsystem/io/serialization/formats/database/dbm.py +7 -7
- exonware/xwsystem/io/serialization/formats/database/shelve.py +7 -7
- exonware/xwsystem/io/serialization/formats/database/sqlite3.py +7 -7
- exonware/xwsystem/io/serialization/formats/tabular/__init__.py +27 -0
- exonware/xwsystem/io/serialization/formats/tabular/base.py +89 -0
- exonware/xwsystem/io/serialization/formats/tabular/csv.py +319 -0
- exonware/xwsystem/io/serialization/formats/tabular/df.py +249 -0
- exonware/xwsystem/io/serialization/formats/tabular/excel.py +291 -0
- exonware/xwsystem/io/serialization/formats/tabular/googlesheets.py +374 -0
- exonware/xwsystem/io/serialization/formats/text/__init__.py +1 -1
- exonware/xwsystem/io/serialization/formats/text/append_only_log.py +199 -0
- exonware/xwsystem/io/serialization/formats/text/configparser.py +5 -5
- exonware/xwsystem/io/serialization/formats/text/csv.py +7 -5
- exonware/xwsystem/io/serialization/formats/text/formdata.py +5 -5
- exonware/xwsystem/io/serialization/formats/text/json.py +65 -33
- exonware/xwsystem/io/serialization/formats/text/json5.py +8 -4
- exonware/xwsystem/io/serialization/formats/text/jsonlines.py +113 -25
- exonware/xwsystem/io/serialization/formats/text/multipart.py +5 -5
- exonware/xwsystem/io/serialization/formats/text/toml.py +8 -6
- exonware/xwsystem/io/serialization/formats/text/xml.py +25 -20
- exonware/xwsystem/io/serialization/formats/text/yaml.py +8 -6
- exonware/xwsystem/io/serialization/parsers/__init__.py +16 -0
- exonware/xwsystem/io/serialization/parsers/base.py +60 -0
- exonware/xwsystem/io/serialization/parsers/hybrid_parser.py +62 -0
- exonware/xwsystem/io/serialization/parsers/msgspec_parser.py +48 -0
- exonware/xwsystem/io/serialization/parsers/orjson_direct_parser.py +54 -0
- exonware/xwsystem/io/serialization/parsers/orjson_parser.py +62 -0
- exonware/xwsystem/io/serialization/parsers/pysimdjson_parser.py +55 -0
- exonware/xwsystem/io/serialization/parsers/rapidjson_parser.py +53 -0
- exonware/xwsystem/io/serialization/parsers/registry.py +91 -0
- exonware/xwsystem/io/serialization/parsers/standard.py +44 -0
- exonware/xwsystem/io/serialization/parsers/ujson_parser.py +53 -0
- exonware/xwsystem/io/serialization/registry.py +4 -4
- exonware/xwsystem/io/serialization/serializer.py +168 -79
- exonware/xwsystem/io/serialization/universal_options.py +367 -0
- exonware/xwsystem/io/serialization/utils/__init__.py +1 -2
- exonware/xwsystem/io/serialization/utils/path_ops.py +5 -6
- exonware/xwsystem/io/source_reader.py +223 -0
- exonware/xwsystem/io/stream/__init__.py +1 -1
- exonware/xwsystem/io/stream/async_operations.py +61 -14
- exonware/xwsystem/io/stream/base.py +1 -2
- exonware/xwsystem/io/stream/codec_io.py +6 -7
- exonware/xwsystem/ipc/__init__.py +1 -0
- exonware/xwsystem/ipc/async_fabric.py +4 -4
- exonware/xwsystem/ipc/base.py +6 -5
- exonware/xwsystem/ipc/contracts.py +41 -66
- exonware/xwsystem/ipc/defs.py +2 -1
- exonware/xwsystem/ipc/errors.py +2 -1
- exonware/xwsystem/ipc/message_queue.py +5 -2
- exonware/xwsystem/ipc/pipes.py +70 -34
- exonware/xwsystem/ipc/process_manager.py +7 -5
- exonware/xwsystem/ipc/process_pool.py +6 -5
- exonware/xwsystem/ipc/shared_memory.py +64 -11
- exonware/xwsystem/monitoring/__init__.py +7 -0
- exonware/xwsystem/monitoring/base.py +11 -8
- exonware/xwsystem/monitoring/contracts.py +86 -144
- exonware/xwsystem/monitoring/defs.py +2 -1
- exonware/xwsystem/monitoring/error_recovery.py +16 -3
- exonware/xwsystem/monitoring/errors.py +2 -1
- exonware/xwsystem/monitoring/facade.py +183 -0
- exonware/xwsystem/monitoring/memory_monitor.py +1 -0
- exonware/xwsystem/monitoring/metrics.py +1 -0
- exonware/xwsystem/monitoring/performance_manager_generic.py +7 -7
- exonware/xwsystem/monitoring/performance_monitor.py +1 -0
- exonware/xwsystem/monitoring/performance_validator.py +1 -0
- exonware/xwsystem/monitoring/system_monitor.py +6 -5
- exonware/xwsystem/monitoring/tracing.py +18 -16
- exonware/xwsystem/monitoring/tracker.py +2 -1
- exonware/xwsystem/operations/__init__.py +5 -50
- exonware/xwsystem/operations/base.py +3 -44
- exonware/xwsystem/operations/contracts.py +25 -15
- exonware/xwsystem/operations/defs.py +1 -1
- exonware/xwsystem/operations/diff.py +5 -4
- exonware/xwsystem/operations/errors.py +1 -1
- exonware/xwsystem/operations/merge.py +6 -4
- exonware/xwsystem/operations/patch.py +5 -4
- exonware/xwsystem/patterns/__init__.py +1 -0
- exonware/xwsystem/patterns/base.py +2 -1
- exonware/xwsystem/patterns/context_manager.py +2 -1
- exonware/xwsystem/patterns/contracts.py +215 -256
- exonware/xwsystem/patterns/defs.py +2 -1
- exonware/xwsystem/patterns/dynamic_facade.py +1 -0
- exonware/xwsystem/patterns/errors.py +2 -4
- exonware/xwsystem/patterns/handler_factory.py +2 -3
- exonware/xwsystem/patterns/import_registry.py +1 -0
- exonware/xwsystem/patterns/object_pool.py +1 -0
- exonware/xwsystem/patterns/registry.py +4 -43
- exonware/xwsystem/plugins/__init__.py +2 -1
- exonware/xwsystem/plugins/base.py +6 -5
- exonware/xwsystem/plugins/contracts.py +94 -158
- exonware/xwsystem/plugins/defs.py +2 -1
- exonware/xwsystem/plugins/errors.py +2 -1
- exonware/xwsystem/py.typed +3 -0
- exonware/xwsystem/query/__init__.py +36 -0
- exonware/xwsystem/query/contracts.py +56 -0
- exonware/xwsystem/query/errors.py +22 -0
- exonware/xwsystem/query/registry.py +128 -0
- exonware/xwsystem/runtime/__init__.py +2 -1
- exonware/xwsystem/runtime/base.py +4 -3
- exonware/xwsystem/runtime/contracts.py +39 -60
- exonware/xwsystem/runtime/defs.py +2 -1
- exonware/xwsystem/runtime/env.py +11 -9
- exonware/xwsystem/runtime/errors.py +2 -1
- exonware/xwsystem/runtime/reflection.py +3 -2
- exonware/xwsystem/security/__init__.py +68 -11
- exonware/xwsystem/security/audit.py +167 -0
- exonware/xwsystem/security/base.py +121 -24
- exonware/xwsystem/security/contracts.py +91 -146
- exonware/xwsystem/security/crypto.py +17 -16
- exonware/xwsystem/security/defs.py +2 -1
- exonware/xwsystem/security/errors.py +2 -1
- exonware/xwsystem/security/facade.py +321 -0
- exonware/xwsystem/security/file_security.py +330 -0
- exonware/xwsystem/security/hazmat.py +11 -8
- exonware/xwsystem/security/monitor.py +372 -0
- exonware/xwsystem/security/path_validator.py +140 -18
- exonware/xwsystem/security/policy.py +357 -0
- exonware/xwsystem/security/resource_limits.py +1 -0
- exonware/xwsystem/security/validator.py +455 -0
- exonware/xwsystem/shared/__init__.py +14 -1
- exonware/xwsystem/shared/base.py +285 -2
- exonware/xwsystem/shared/contracts.py +415 -126
- exonware/xwsystem/shared/defs.py +2 -1
- exonware/xwsystem/shared/errors.py +2 -2
- exonware/xwsystem/shared/xwobject.py +316 -0
- exonware/xwsystem/structures/__init__.py +1 -0
- exonware/xwsystem/structures/base.py +3 -2
- exonware/xwsystem/structures/circular_detector.py +15 -14
- exonware/xwsystem/structures/contracts.py +53 -76
- exonware/xwsystem/structures/defs.py +2 -1
- exonware/xwsystem/structures/errors.py +2 -1
- exonware/xwsystem/structures/tree_walker.py +2 -1
- exonware/xwsystem/threading/__init__.py +21 -4
- exonware/xwsystem/threading/async_primitives.py +6 -5
- exonware/xwsystem/threading/base.py +3 -2
- exonware/xwsystem/threading/contracts.py +87 -143
- exonware/xwsystem/threading/defs.py +2 -1
- exonware/xwsystem/threading/errors.py +2 -1
- exonware/xwsystem/threading/facade.py +175 -0
- exonware/xwsystem/threading/locks.py +1 -0
- exonware/xwsystem/threading/safe_factory.py +1 -0
- exonware/xwsystem/utils/__init__.py +40 -0
- exonware/xwsystem/utils/base.py +22 -21
- exonware/xwsystem/utils/contracts.py +50 -73
- exonware/xwsystem/utils/dt/__init__.py +19 -3
- exonware/xwsystem/utils/dt/base.py +5 -4
- exonware/xwsystem/utils/dt/contracts.py +22 -29
- exonware/xwsystem/utils/dt/defs.py +2 -1
- exonware/xwsystem/utils/dt/errors.py +2 -5
- exonware/xwsystem/utils/dt/formatting.py +88 -2
- exonware/xwsystem/utils/dt/humanize.py +10 -9
- exonware/xwsystem/utils/dt/parsing.py +56 -5
- exonware/xwsystem/utils/dt/timezone_utils.py +2 -24
- exonware/xwsystem/utils/errors.py +2 -4
- exonware/xwsystem/utils/paths.py +1 -0
- exonware/xwsystem/utils/string.py +49 -0
- exonware/xwsystem/utils/test_runner.py +139 -480
- exonware/xwsystem/utils/utils_contracts.py +2 -1
- exonware/xwsystem/utils/web.py +110 -0
- exonware/xwsystem/validation/__init__.py +25 -1
- exonware/xwsystem/validation/base.py +6 -5
- exonware/xwsystem/validation/contracts.py +29 -41
- exonware/xwsystem/validation/data_validator.py +1 -0
- exonware/xwsystem/validation/declarative.py +11 -8
- exonware/xwsystem/validation/defs.py +2 -1
- exonware/xwsystem/validation/errors.py +2 -1
- exonware/xwsystem/validation/facade.py +198 -0
- exonware/xwsystem/validation/fluent_validator.py +22 -19
- exonware/xwsystem/validation/schema_discovery.py +210 -0
- exonware/xwsystem/validation/type_safety.py +2 -1
- exonware/xwsystem/version.py +4 -4
- {exonware_xwsystem-0.0.1.411.dist-info → exonware_xwsystem-0.1.0.3.dist-info}/METADATA +71 -4
- exonware_xwsystem-0.1.0.3.dist-info/RECORD +337 -0
- exonware/xwsystem/caching/USAGE_GUIDE.md +0 -779
- exonware/xwsystem/cli/__init__.py +0 -43
- exonware/xwsystem/cli/console.py +0 -113
- exonware/xwsystem/cli/defs.py +0 -134
- exonware/xwsystem/conf.py +0 -44
- exonware/xwsystem/security/auth.py +0 -484
- exonware_xwsystem-0.0.1.411.dist-info/RECORD +0 -274
- {exonware_xwsystem-0.0.1.411.dist-info → exonware_xwsystem-0.1.0.3.dist-info}/WHEEL +0 -0
- {exonware_xwsystem-0.0.1.411.dist-info → exonware_xwsystem-0.1.0.3.dist-info}/licenses/LICENSE +0 -0
|
@@ -1,8 +1,9 @@
|
|
|
1
|
+
#exonware/xwsystem/src/exonware/xwsystem/caching/lfu_cache.py
|
|
1
2
|
"""
|
|
2
3
|
Company: eXonware.com
|
|
3
4
|
Author: Eng. Muhammad AlShehri
|
|
4
5
|
Email: connect@exonware.com
|
|
5
|
-
Version: 0.0.
|
|
6
|
+
Version: 0.1.0.3
|
|
6
7
|
Generation Date: September 04, 2025
|
|
7
8
|
|
|
8
9
|
LFU (Least Frequently Used) Cache implementation with thread-safety and async support.
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
#!/usr/bin/env python3
|
|
2
|
+
#exonware/xwsystem/src/exonware/xwsystem/caching/lfu_optimized.py
|
|
2
3
|
#exonware/xwsystem/caching/lfu_optimized.py
|
|
3
4
|
"""
|
|
4
5
|
Company: eXonware.com
|
|
5
6
|
Author: Eng. Muhammad AlShehri
|
|
6
7
|
Email: connect@exonware.com
|
|
7
|
-
Version: 0.0.
|
|
8
|
+
Version: 0.1.0.3
|
|
8
9
|
Generation Date: 01-Nov-2025
|
|
9
10
|
|
|
10
11
|
Optimized O(1) LFU Cache implementation.
|
|
@@ -257,7 +258,7 @@ class OptimizedLFUCache(ACache):
|
|
|
257
258
|
- NEW: O(1) using min_freq bucket
|
|
258
259
|
"""
|
|
259
260
|
if self._min_freq not in self._freq_to_keys:
|
|
260
|
-
#
|
|
261
|
+
# Handle case where min_freq bucket is empty
|
|
261
262
|
if self._freq_to_keys:
|
|
262
263
|
self._min_freq = min(self._freq_to_keys.keys())
|
|
263
264
|
else:
|
|
@@ -320,13 +321,25 @@ class OptimizedLFUCache(ACache):
|
|
|
320
321
|
"""
|
|
321
322
|
with self._lock:
|
|
322
323
|
count = 0
|
|
324
|
+
errors = []
|
|
323
325
|
for key, value in items.items():
|
|
324
326
|
try:
|
|
325
327
|
self.put(key, value)
|
|
326
328
|
count += 1
|
|
327
|
-
except Exception:
|
|
328
|
-
#
|
|
329
|
-
|
|
329
|
+
except Exception as e:
|
|
330
|
+
# Log error but continue with other items for batch resilience
|
|
331
|
+
# This follows GUIDE_TEST.md by handling errors explicitly
|
|
332
|
+
errors.append((key, str(e)))
|
|
333
|
+
|
|
334
|
+
# Log any errors that occurred during batch operation
|
|
335
|
+
if errors:
|
|
336
|
+
# Use existing logger (imported at module level)
|
|
337
|
+
logger.warning(
|
|
338
|
+
f"put_many: {len(errors)} items failed out of {len(items)}. "
|
|
339
|
+
f"Successfully cached {count} items. "
|
|
340
|
+
f"Errors: {errors[:5]}" # Show first 5 errors
|
|
341
|
+
)
|
|
342
|
+
|
|
330
343
|
return count
|
|
331
344
|
|
|
332
345
|
def delete_many(self, keys: list[Hashable]) -> int:
|
|
@@ -550,4 +563,3 @@ __all__ = [
|
|
|
550
563
|
'OptimizedLFUCache',
|
|
551
564
|
'AsyncOptimizedLFUCache',
|
|
552
565
|
]
|
|
553
|
-
|
|
@@ -1,18 +1,21 @@
|
|
|
1
|
+
#exonware/xwsystem/src/exonware/xwsystem/caching/lru_cache.py
|
|
1
2
|
"""
|
|
2
3
|
Company: eXonware.com
|
|
3
4
|
Author: Eng. Muhammad AlShehri
|
|
4
5
|
Email: connect@exonware.com
|
|
5
|
-
Version: 0.0.
|
|
6
|
+
Version: 0.1.0.3
|
|
6
7
|
Generation Date: September 04, 2025
|
|
7
8
|
|
|
8
9
|
LRU (Least Recently Used) Cache implementation with thread-safety and async support.
|
|
9
10
|
"""
|
|
10
11
|
|
|
12
|
+
from __future__ import annotations
|
|
13
|
+
|
|
11
14
|
import asyncio
|
|
12
15
|
import threading
|
|
13
16
|
import time
|
|
14
17
|
from collections import OrderedDict
|
|
15
|
-
from typing import Any, Optional,
|
|
18
|
+
from typing import Any, Optional, Callable, Hashable
|
|
16
19
|
|
|
17
20
|
from ..config.logging_setup import get_logger
|
|
18
21
|
from .base import ACache
|
|
@@ -26,8 +29,8 @@ class CacheNode:
|
|
|
26
29
|
def __init__(self, key: Hashable, value: Any):
|
|
27
30
|
self.key = key
|
|
28
31
|
self.value = value
|
|
29
|
-
self.prev: Optional[
|
|
30
|
-
self.next: Optional[
|
|
32
|
+
self.prev: Optional[CacheNode] = None
|
|
33
|
+
self.next: Optional[CacheNode] = None
|
|
31
34
|
self.access_time = time.time()
|
|
32
35
|
|
|
33
36
|
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
#!/usr/bin/env python3
|
|
2
|
+
#exonware/xwsystem/src/exonware/xwsystem/caching/memory_bounded.py
|
|
2
3
|
#exonware/xwsystem/caching/memory_bounded.py
|
|
3
4
|
"""
|
|
4
5
|
Company: eXonware.com
|
|
5
6
|
Author: Eng. Muhammad AlShehri
|
|
6
7
|
Email: connect@exonware.com
|
|
7
|
-
Version: 0.0.
|
|
8
|
+
Version: 0.1.0.3
|
|
8
9
|
Generation Date: 01-Nov-2025
|
|
9
10
|
|
|
10
11
|
Memory-bounded cache implementations.
|
|
@@ -286,4 +287,3 @@ __all__ = [
|
|
|
286
287
|
'MemoryBoundedLRUCache',
|
|
287
288
|
'MemoryBoundedLFUCache',
|
|
288
289
|
]
|
|
289
|
-
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
#!/usr/bin/env python3
|
|
2
|
+
#exonware/xwsystem/src/exonware/xwsystem/caching/metrics_exporter.py
|
|
2
3
|
"""
|
|
3
4
|
Company: eXonware.com
|
|
4
5
|
Author: Eng. Muhammad AlShehri
|
|
5
6
|
Email: connect@exonware.com
|
|
6
|
-
Version: 0.0.
|
|
7
|
+
Version: 0.1.0.3
|
|
7
8
|
Generation Date: 01-Nov-2025
|
|
8
9
|
|
|
9
10
|
Metrics exporters for cache monitoring.
|
|
@@ -194,4 +195,3 @@ __all__ = [
|
|
|
194
195
|
'PrometheusExporter',
|
|
195
196
|
'StatsCollector',
|
|
196
197
|
]
|
|
197
|
-
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
#!/usr/bin/env python3
|
|
2
|
+
#exonware/xwsystem/src/exonware/xwsystem/caching/observable_cache.py
|
|
2
3
|
#exonware/xwsystem/caching/observable_cache.py
|
|
3
4
|
"""
|
|
4
5
|
Company: eXonware.com
|
|
5
6
|
Author: Eng. Muhammad AlShehri
|
|
6
7
|
Email: connect@exonware.com
|
|
7
|
-
Version: 0.0.
|
|
8
|
+
Version: 0.1.0.3
|
|
8
9
|
Generation Date: 01-Nov-2025
|
|
9
10
|
|
|
10
11
|
Observable cache implementations with event emission.
|
|
@@ -148,4 +149,3 @@ __all__ = [
|
|
|
148
149
|
'ObservableLRUCache',
|
|
149
150
|
'ObservableLFUCache',
|
|
150
151
|
]
|
|
151
|
-
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
#!/usr/bin/env python3
|
|
2
|
+
#exonware/xwsystem/src/exonware/xwsystem/caching/pluggable_cache.py
|
|
2
3
|
#exonware/xwsystem/caching/pluggable_cache.py
|
|
3
4
|
"""
|
|
4
5
|
Company: eXonware.com
|
|
5
6
|
Author: Eng. Muhammad AlShehri
|
|
6
7
|
Email: connect@exonware.com
|
|
7
|
-
Version: 0.0.
|
|
8
|
+
Version: 0.1.0.3
|
|
8
9
|
Generation Date: 01-Nov-2025
|
|
9
10
|
|
|
10
11
|
Pluggable cache with runtime-switchable eviction strategies.
|
|
@@ -230,4 +231,3 @@ class PluggableCache(ACache):
|
|
|
230
231
|
__all__ = [
|
|
231
232
|
'PluggableCache',
|
|
232
233
|
]
|
|
233
|
-
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
#!/usr/bin/env python3
|
|
2
|
+
#exonware/xwsystem/src/exonware/xwsystem/caching/rate_limiter.py
|
|
2
3
|
#exonware/xwsystem/caching/rate_limiter.py
|
|
3
4
|
"""
|
|
4
5
|
Company: eXonware.com
|
|
5
6
|
Author: Eng. Muhammad AlShehri
|
|
6
7
|
Email: connect@exonware.com
|
|
7
|
-
Version: 0.0.
|
|
8
|
+
Version: 0.1.0.3
|
|
8
9
|
Generation Date: 01-Nov-2025
|
|
9
10
|
|
|
10
11
|
Rate limiting for caching module - Security Priority #1.
|
|
@@ -249,4 +250,3 @@ __all__ = [
|
|
|
249
250
|
'RateLimiter',
|
|
250
251
|
'FixedWindowRateLimiter',
|
|
251
252
|
]
|
|
252
|
-
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
#!/usr/bin/env python3
|
|
2
|
+
#exonware/xwsystem/src/exonware/xwsystem/caching/read_through.py
|
|
2
3
|
"""
|
|
3
4
|
Company: eXonware.com
|
|
4
5
|
Author: Eng. Muhammad AlShehri
|
|
5
6
|
Email: connect@exonware.com
|
|
6
|
-
Version: 0.0.
|
|
7
|
+
Version: 0.1.0.3
|
|
7
8
|
Generation Date: 01-Nov-2025
|
|
8
9
|
|
|
9
10
|
Read-through and Write-through cache implementations.
|
|
@@ -248,4 +249,3 @@ __all__ = [
|
|
|
248
249
|
'WriteThroughCache',
|
|
249
250
|
'ReadWriteThroughCache',
|
|
250
251
|
]
|
|
251
|
-
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
#!/usr/bin/env python3
|
|
2
|
+
#exonware/xwsystem/src/exonware/xwsystem/caching/secure_cache.py
|
|
2
3
|
#exonware/xwsystem/caching/secure_cache.py
|
|
3
4
|
"""
|
|
4
5
|
Company: eXonware.com
|
|
5
6
|
Author: Eng. Muhammad AlShehri
|
|
6
7
|
Email: connect@exonware.com
|
|
7
|
-
Version: 0.0.
|
|
8
|
+
Version: 0.1.0.3
|
|
8
9
|
Generation Date: 01-Nov-2025
|
|
9
10
|
|
|
10
11
|
Secure cache implementations with validation, integrity checks, and rate limiting.
|
|
@@ -70,20 +71,44 @@ class SecureLRUCache(LRUCache):
|
|
|
70
71
|
self.max_value_size_mb = max_value_size_mb
|
|
71
72
|
|
|
72
73
|
# Security components
|
|
74
|
+
# Only create rate limiter if explicitly enabled
|
|
75
|
+
# This ensures rate limiting is truly disabled when enable_rate_limit=False
|
|
73
76
|
if self.enable_rate_limit:
|
|
74
77
|
self.rate_limiter = RateLimiter(max_ops_per_second=max_ops_per_second)
|
|
78
|
+
else:
|
|
79
|
+
# Explicitly ensure rate_limiter doesn't exist when disabled
|
|
80
|
+
# This prevents any accidental access
|
|
81
|
+
if hasattr(self, 'rate_limiter'):
|
|
82
|
+
delattr(self, 'rate_limiter')
|
|
75
83
|
|
|
76
84
|
# Track integrity violations
|
|
77
85
|
self._integrity_violations = 0
|
|
78
86
|
|
|
79
87
|
def _check_rate_limit(self) -> None:
|
|
80
|
-
"""
|
|
81
|
-
if
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
88
|
+
"""
|
|
89
|
+
Check rate limit if enabled.
|
|
90
|
+
|
|
91
|
+
Raises:
|
|
92
|
+
CacheRateLimitError: If rate limit is exceeded
|
|
93
|
+
|
|
94
|
+
Note:
|
|
95
|
+
This method follows GUIDE_TEST.md by explicitly raising
|
|
96
|
+
errors rather than silently ignoring them. Rate limiting
|
|
97
|
+
is a security feature (Priority #1) and violations are
|
|
98
|
+
reported.
|
|
99
|
+
"""
|
|
100
|
+
# Triple-check: only check rate limit if explicitly enabled
|
|
101
|
+
# and rate limiter exists (defensive programming)
|
|
102
|
+
# This ensures rate limiting is truly disabled when enable_rate_limit=False
|
|
103
|
+
if not self.enable_rate_limit:
|
|
104
|
+
return # Early return if rate limiting is disabled
|
|
105
|
+
|
|
106
|
+
if not hasattr(self, 'rate_limiter'):
|
|
107
|
+
return # Early return if rate limiter doesn't exist
|
|
108
|
+
|
|
109
|
+
# Rate limiter will raise CacheRateLimitError if limit exceeded
|
|
110
|
+
# We let it propagate to caller for proper error handling
|
|
111
|
+
self.rate_limiter.acquire()
|
|
87
112
|
|
|
88
113
|
def put(self, key: Hashable, value: Any) -> None:
|
|
89
114
|
"""
|
|
@@ -97,8 +122,10 @@ class SecureLRUCache(LRUCache):
|
|
|
97
122
|
CacheValidationError: If validation fails
|
|
98
123
|
CacheRateLimitError: If rate limit exceeded
|
|
99
124
|
"""
|
|
100
|
-
# Rate limiting
|
|
101
|
-
|
|
125
|
+
# Rate limiting - only check if explicitly enabled
|
|
126
|
+
# This ensures rate limiting is truly disabled when enable_rate_limit=False
|
|
127
|
+
if self.enable_rate_limit:
|
|
128
|
+
self._check_rate_limit()
|
|
102
129
|
|
|
103
130
|
# Validate key
|
|
104
131
|
validate_cache_key(key, max_size=self.max_key_size)
|
|
@@ -132,27 +159,54 @@ class SecureLRUCache(LRUCache):
|
|
|
132
159
|
Raises:
|
|
133
160
|
CacheIntegrityError: If integrity check fails
|
|
134
161
|
"""
|
|
135
|
-
# Rate limiting
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
result = super().get(key, default)
|
|
162
|
+
# Rate limiting - only check if explicitly enabled
|
|
163
|
+
# This ensures rate limiting is truly disabled when enable_rate_limit=False
|
|
164
|
+
if self.enable_rate_limit:
|
|
165
|
+
self._check_rate_limit()
|
|
140
166
|
|
|
141
|
-
if
|
|
142
|
-
|
|
167
|
+
# Check if key exists in cache first to handle None values correctly
|
|
168
|
+
# The parent's get() method treats None as "not found", so we need to
|
|
169
|
+
# check existence directly to distinguish between "key not found" and "value is None"
|
|
170
|
+
with self._lock:
|
|
171
|
+
if key not in self._cache:
|
|
172
|
+
return default
|
|
173
|
+
|
|
174
|
+
# Key exists - get the node to access the value
|
|
175
|
+
node = self._cache[key]
|
|
176
|
+
|
|
177
|
+
# Check TTL if enabled
|
|
178
|
+
if self.ttl and time.time() - node.access_time > self.ttl:
|
|
179
|
+
self._remove_node(node)
|
|
180
|
+
del self._cache[key]
|
|
181
|
+
return default
|
|
182
|
+
|
|
183
|
+
# Move to head (most recently used) - use parent's method
|
|
184
|
+
self._move_to_head(node)
|
|
185
|
+
node.access_time = time.time()
|
|
186
|
+
self._hits += 1
|
|
187
|
+
|
|
188
|
+
# Get the actual value from the node
|
|
189
|
+
result = node.value
|
|
143
190
|
|
|
144
191
|
# Verify integrity if enabled
|
|
145
|
-
if self.enable_integrity
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
192
|
+
if self.enable_integrity:
|
|
193
|
+
# If result is a CacheEntry, verify and extract value
|
|
194
|
+
if isinstance(result, CacheEntry):
|
|
195
|
+
try:
|
|
196
|
+
verify_entry_integrity(result)
|
|
197
|
+
result.access_count += 1
|
|
198
|
+
return result.value
|
|
199
|
+
except CacheIntegrityError as e:
|
|
200
|
+
# Log violation and remove corrupted entry
|
|
201
|
+
self._integrity_violations += 1
|
|
202
|
+
self.delete(key)
|
|
203
|
+
raise e
|
|
204
|
+
else:
|
|
205
|
+
# If integrity is enabled but result is not a CacheEntry,
|
|
206
|
+
# this might be a legacy entry or corruption - return as-is
|
|
207
|
+
return result
|
|
155
208
|
|
|
209
|
+
# Integrity disabled - return value directly (including None)
|
|
156
210
|
return result
|
|
157
211
|
|
|
158
212
|
def get_security_stats(self) -> dict:
|
|
@@ -297,4 +351,3 @@ __all__ = [
|
|
|
297
351
|
'SecureLFUCache',
|
|
298
352
|
'SecureTTLCache',
|
|
299
353
|
]
|
|
300
|
-
|
|
@@ -1,19 +1,22 @@
|
|
|
1
1
|
#!/usr/bin/env python3
|
|
2
|
+
#exonware/xwsystem/src/exonware/xwsystem/caching/serializable.py
|
|
2
3
|
"""
|
|
3
4
|
Company: eXonware.com
|
|
4
5
|
Author: Eng. Muhammad AlShehri
|
|
5
6
|
Email: connect@exonware.com
|
|
6
|
-
Version: 0.0.
|
|
7
|
+
Version: 0.1.0.3
|
|
7
8
|
Generation Date: 01-Nov-2025
|
|
8
9
|
|
|
9
10
|
Cache serialization utilities.
|
|
10
11
|
Usability Priority #2 - Persist and restore cache state.
|
|
11
12
|
"""
|
|
12
13
|
|
|
14
|
+
from __future__ import annotations
|
|
15
|
+
|
|
13
16
|
import pickle
|
|
14
17
|
import json
|
|
15
18
|
from pathlib import Path
|
|
16
|
-
from typing import Any
|
|
19
|
+
from typing import Any
|
|
17
20
|
from .lru_cache import LRUCache
|
|
18
21
|
from .lfu_optimized import OptimizedLFUCache
|
|
19
22
|
from ..config.logging_setup import get_logger
|
|
@@ -40,7 +43,7 @@ class SerializableCache(LRUCache):
|
|
|
40
43
|
assert cache2.get('key1') == 'value1'
|
|
41
44
|
"""
|
|
42
45
|
|
|
43
|
-
def save_to_file(self, file_path:
|
|
46
|
+
def save_to_file(self, file_path: str | Path, format: str = 'pickle') -> bool:
|
|
44
47
|
"""
|
|
45
48
|
Save cache to file.
|
|
46
49
|
|
|
@@ -80,7 +83,7 @@ class SerializableCache(LRUCache):
|
|
|
80
83
|
return False
|
|
81
84
|
|
|
82
85
|
@classmethod
|
|
83
|
-
def load_from_file(cls, file_path:
|
|
86
|
+
def load_from_file(cls, file_path: str | Path, format: str = 'pickle') -> SerializableCache:
|
|
84
87
|
"""
|
|
85
88
|
Load cache from file.
|
|
86
89
|
|
|
@@ -121,7 +124,7 @@ class SerializableCache(LRUCache):
|
|
|
121
124
|
logger.error(f"Failed to load cache from {file_path}: {e}")
|
|
122
125
|
raise
|
|
123
126
|
|
|
124
|
-
def backup(self, backup_path:
|
|
127
|
+
def backup(self, backup_path: str | Path) -> bool:
|
|
125
128
|
"""
|
|
126
129
|
Create backup of cache.
|
|
127
130
|
|
|
@@ -133,7 +136,7 @@ class SerializableCache(LRUCache):
|
|
|
133
136
|
"""
|
|
134
137
|
return self.save_to_file(backup_path, format='pickle')
|
|
135
138
|
|
|
136
|
-
def restore(self, backup_path:
|
|
139
|
+
def restore(self, backup_path: str | Path) -> bool:
|
|
137
140
|
"""
|
|
138
141
|
Restore cache from backup.
|
|
139
142
|
|
|
@@ -164,4 +167,3 @@ class SerializableCache(LRUCache):
|
|
|
164
167
|
__all__ = [
|
|
165
168
|
'SerializableCache',
|
|
166
169
|
]
|
|
167
|
-
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
#!/usr/bin/env python3
|
|
2
|
+
#exonware/xwsystem/src/exonware/xwsystem/caching/stats.py
|
|
2
3
|
#exonware/xwsystem/caching/stats.py
|
|
3
4
|
"""
|
|
4
5
|
Company: eXonware.com
|
|
5
6
|
Author: Eng. Muhammad AlShehri
|
|
6
7
|
Email: connect@exonware.com
|
|
7
|
-
Version: 0.0.
|
|
8
|
+
Version: 0.1.0.3
|
|
8
9
|
Generation Date: 01-Nov-2025
|
|
9
10
|
|
|
10
11
|
Statistics formatting utilities for caching module.
|
|
@@ -184,4 +185,3 @@ __all__ = [
|
|
|
184
185
|
'format_cache_stats_table',
|
|
185
186
|
'get_stats_summary',
|
|
186
187
|
]
|
|
187
|
-
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
#!/usr/bin/env python3
|
|
2
|
+
#exonware/xwsystem/src/exonware/xwsystem/caching/tagging.py
|
|
2
3
|
"""
|
|
3
4
|
Company: eXonware.com
|
|
4
5
|
Author: Eng. Muhammad AlShehri
|
|
5
6
|
Email: connect@exonware.com
|
|
6
|
-
Version: 0.0.
|
|
7
|
+
Version: 0.1.0.3
|
|
7
8
|
Generation Date: 01-Nov-2025
|
|
8
9
|
|
|
9
10
|
Tag-based cache invalidation.
|
|
@@ -199,4 +200,3 @@ class TaggedCache(LRUCache):
|
|
|
199
200
|
__all__ = [
|
|
200
201
|
'TaggedCache',
|
|
201
202
|
]
|
|
202
|
-
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
#exonware/xwsystem/src/exonware/xwsystem/caching/ttl_cache.py
|
|
1
2
|
"""
|
|
2
3
|
TTL (Time To Live) Cache Implementation
|
|
3
4
|
======================================
|
|
@@ -7,14 +8,14 @@ Production-grade TTL caching for XSystem.
|
|
|
7
8
|
Company: eXonware.com
|
|
8
9
|
Author: Eng. Muhammad AlShehri
|
|
9
10
|
Email: connect@exonware.com
|
|
10
|
-
Version: 0.0.
|
|
11
|
+
Version: 0.1.0.3
|
|
11
12
|
Generated: 2025-01-27
|
|
12
13
|
"""
|
|
13
14
|
|
|
14
15
|
import asyncio
|
|
15
16
|
import time
|
|
16
17
|
import threading
|
|
17
|
-
from typing import Any, Optional
|
|
18
|
+
from typing import Any, Optional
|
|
18
19
|
from dataclasses import dataclass
|
|
19
20
|
import logging
|
|
20
21
|
from .base import ACache
|
|
@@ -196,7 +197,7 @@ class TTLCache(ACache):
|
|
|
196
197
|
def set(self, key: str, value: Any, ttl: Optional[int] = None) -> None:
|
|
197
198
|
"""
|
|
198
199
|
Set value in cache (abstract method implementation).
|
|
199
|
-
Delegates to put()
|
|
200
|
+
Delegates to put().
|
|
200
201
|
|
|
201
202
|
Args:
|
|
202
203
|
key: Key to store
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
#!/usr/bin/env python3
|
|
2
|
+
#exonware/xwsystem/src/exonware/xwsystem/caching/two_tier_cache.py
|
|
2
3
|
"""
|
|
3
4
|
Company: eXonware.com
|
|
4
5
|
Author: Eng. Muhammad AlShehri
|
|
5
6
|
Email: connect@exonware.com
|
|
6
|
-
Version: 0.0.
|
|
7
|
+
Version: 0.1.0.3
|
|
7
8
|
Generation Date: October 26, 2025
|
|
8
9
|
|
|
9
10
|
Two-tier cache implementation combining memory and disk caching.
|
|
@@ -54,8 +55,10 @@ class TwoTierCache(ICache):
|
|
|
54
55
|
self.namespace = namespace
|
|
55
56
|
|
|
56
57
|
# Initialize tiers
|
|
57
|
-
#
|
|
58
|
-
|
|
58
|
+
# Use flexible create_cache() to allow configuration via environment/settings
|
|
59
|
+
# Defaults to FunctoolsLRUCache (fastest Python cache)
|
|
60
|
+
from .factory import create_cache
|
|
61
|
+
self.memory_cache = create_cache(capacity=memory_size, namespace=namespace, name=f"{namespace}-TwoTier-Memory")
|
|
59
62
|
self.disk_cache = DiskCache(
|
|
60
63
|
namespace=namespace,
|
|
61
64
|
cache_dir=disk_cache_dir,
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
#!/usr/bin/env python3
|
|
2
|
+
#exonware/xwsystem/src/exonware/xwsystem/caching/utils.py
|
|
2
3
|
#exonware/xwsystem/caching/utils.py
|
|
3
4
|
"""
|
|
4
5
|
Company: eXonware.com
|
|
5
6
|
Author: Eng. Muhammad AlShehri
|
|
6
7
|
Email: connect@exonware.com
|
|
7
|
-
Version: 0.0.
|
|
8
|
+
Version: 0.1.0.3
|
|
8
9
|
Generation Date: 01-Nov-2025
|
|
9
10
|
|
|
10
11
|
Common utility functions for caching module.
|
|
@@ -33,13 +34,17 @@ def estimate_object_size(obj: Any) -> int:
|
|
|
33
34
|
try:
|
|
34
35
|
return sys.getsizeof(obj)
|
|
35
36
|
except (TypeError, AttributeError):
|
|
36
|
-
# For objects that don't support getsizeof
|
|
37
|
+
# For objects that don't support getsizeof (e.g., some C extensions)
|
|
37
38
|
try:
|
|
38
|
-
# Try pickling as fallback
|
|
39
|
+
# Try pickling as fallback to estimate serialized size
|
|
39
40
|
return len(pickle.dumps(obj, protocol=pickle.HIGHEST_PROTOCOL))
|
|
40
|
-
except
|
|
41
|
-
#
|
|
42
|
-
|
|
41
|
+
except (pickle.PicklingError, TypeError, AttributeError) as e:
|
|
42
|
+
# Object cannot be pickled - return conservative estimate
|
|
43
|
+
# This is acceptable per GUIDE_TEST.md as this is a utility function
|
|
44
|
+
# Provides fallback rather than failing
|
|
45
|
+
# The alternative would be to raise an exception, but that would
|
|
46
|
+
# break cache operations for objects that can't be sized
|
|
47
|
+
return 1024 # 1KB default conservative estimate
|
|
43
48
|
|
|
44
49
|
|
|
45
50
|
def compute_checksum(value: Any, algorithm: str = 'sha256') -> str:
|
|
@@ -135,11 +140,25 @@ def default_key_builder(func: Callable, args: tuple, kwargs: dict) -> str:
|
|
|
135
140
|
kwargs_str = str(sorted(kwargs.items()))
|
|
136
141
|
key = f"{func_name}:{args_str}:{kwargs_str}"
|
|
137
142
|
return key
|
|
138
|
-
except
|
|
139
|
-
# Fallback: use hash
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
+
except (TypeError, ValueError) as e:
|
|
144
|
+
# Fallback: use hash for non-stringable arguments
|
|
145
|
+
# This is acceptable per GUIDE_TEST.md as this is a utility function
|
|
146
|
+
# Provides fallback mechanism for edge cases
|
|
147
|
+
# The alternative would be to raise, but that would break caching
|
|
148
|
+
# for functions with complex argument types
|
|
149
|
+
try:
|
|
150
|
+
args_hash = hash(args)
|
|
151
|
+
kwargs_hash = hash(tuple(sorted(kwargs.items())))
|
|
152
|
+
return f"{func_name}:{args_hash}:{kwargs_hash}"
|
|
153
|
+
except (TypeError, ValueError):
|
|
154
|
+
# If even hashing fails, use a deterministic fallback
|
|
155
|
+
# This handles truly unhashable types (e.g., lists, dicts)
|
|
156
|
+
import hashlib
|
|
157
|
+
args_repr = repr(args).encode('utf-8')
|
|
158
|
+
kwargs_repr = repr(kwargs).encode('utf-8')
|
|
159
|
+
combined = args_repr + kwargs_repr
|
|
160
|
+
hash_val = hashlib.md5(combined).hexdigest()
|
|
161
|
+
return f"{func_name}:{hash_val}"
|
|
143
162
|
|
|
144
163
|
|
|
145
164
|
def validate_capacity(capacity: int, min_capacity: int = 1, max_capacity: int = 1000000) -> None:
|
|
@@ -212,4 +231,3 @@ __all__ = [
|
|
|
212
231
|
'validate_capacity',
|
|
213
232
|
'validate_ttl',
|
|
214
233
|
]
|
|
215
|
-
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
#!/usr/bin/env python3
|
|
2
|
+
#exonware/xwsystem/src/exonware/xwsystem/caching/validation.py
|
|
2
3
|
#exonware/xwsystem/caching/validation.py
|
|
3
4
|
"""
|
|
4
5
|
Company: eXonware.com
|
|
5
6
|
Author: Eng. Muhammad AlShehri
|
|
6
7
|
Email: connect@exonware.com
|
|
7
|
-
Version: 0.0.
|
|
8
|
+
Version: 0.1.0.3
|
|
8
9
|
Generation Date: 01-Nov-2025
|
|
9
10
|
|
|
10
11
|
Input validation for caching module - Security Priority #1.
|
|
@@ -230,4 +231,3 @@ __all__ = [
|
|
|
230
231
|
'DEFAULT_MAX_VALUE_SIZE_MB',
|
|
231
232
|
'DEFAULT_MAX_VALUE_SIZE',
|
|
232
233
|
]
|
|
233
|
-
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
#!/usr/bin/env python3
|
|
2
|
+
#exonware/xwsystem/src/exonware/xwsystem/caching/warming.py
|
|
2
3
|
#exonware/xwsystem/caching/warming.py
|
|
3
4
|
"""
|
|
4
5
|
Company: eXonware.com
|
|
5
6
|
Author: Eng. Muhammad AlShehri
|
|
6
7
|
Email: connect@exonware.com
|
|
7
|
-
Version: 0.0.
|
|
8
|
+
Version: 0.1.0.3
|
|
8
9
|
Generation Date: 01-Nov-2025
|
|
9
10
|
|
|
10
11
|
Cache warming utilities for preloading data.
|
|
@@ -64,9 +65,12 @@ class PreloadWarmingStrategy(AWarmingStrategy):
|
|
|
64
65
|
|
|
65
66
|
elapsed = time.time() - start_time
|
|
66
67
|
|
|
68
|
+
# Avoid division by zero if operation completes instantly
|
|
69
|
+
keys_per_sec = len(keys) / elapsed if elapsed > 0 else float('inf')
|
|
70
|
+
|
|
67
71
|
logger.info(
|
|
68
72
|
f"Cache warming complete: {success_count}/{len(keys)} loaded "
|
|
69
|
-
f"in {elapsed:.2f}s ({
|
|
73
|
+
f"in {elapsed:.2f}s ({keys_per_sec:.0f} keys/sec)"
|
|
70
74
|
)
|
|
71
75
|
|
|
72
76
|
if failures:
|
|
@@ -239,4 +243,3 @@ __all__ = [
|
|
|
239
243
|
'warm_cache',
|
|
240
244
|
'warm_cache_async',
|
|
241
245
|
]
|
|
242
|
-
|