Advanced Python cache system with multi-tenant support, scope hierarchies, and configurable eviction policies
Project description
Cacheado
High-performance Python cache system with hierarchical scopes, pluggable storage backends, and intelligent eviction policies
Solves critical cache problems in enterprise applications: hierarchical data isolation (organization/user/tenant), flexible storage backends (In-Memory, Redis, MongoDB), intelligent memory management with LRU/TTL policies, and thread-safe operations with high performance.
โก Why Cacheado?
Flexible Architecture with pluggable storage providers
Zero configuration for common use cases
Production-ready with comprehensive eviction policies
Key Benefits
๐ Performance: Optimized for high-throughput operations with <1ms latency
๐ข Multi-Tenant: Hierarchical scope isolation (global โ organization โ user โ session)
๐ Pluggable Storage: In-Memory, Redis, MongoDB support out-of-the-box
โก Async/Sync: Full support for synchronous and asynchronous code
๐ง Smart Eviction: LRU, TTL, and max-items policies with rule composition
๐ Observability: Detailed metrics for hits, misses, evictions, and storage stats
๐ Quick Start
Installation
# Basic installation (in-memory only)
pip install cacheado
# With Redis support
pip install cacheado[redis]
# With MongoDB support
pip install cacheado[mongodb]
# With all backends
pip install cacheado[all]
# For development
pip install cacheado[dev]
Basic Usage (30 seconds to first result)
from cache import Cache
# Instant creation with default in-memory storage
cache = Cache()
# Simple cache with decorator
@cache.cache(ttl_seconds=300)
def expensive_calculation(x, y):
import time
time.sleep(2) # Simulates expensive operation
return x * y
# First call: 2 seconds
result = expensive_calculation(10, 20) # 200
# Second call: <1ms (cache hit!)
result = expensive_calculation(10, 20) # 200 (from cache)
Multi-Tenant Cache with Hierarchical Scopes
from cache import Cache
from utils.cache_scope_config import ScopeConfig, ScopeLevel
# Configure hierarchical scopes
scope_config = ScopeConfig([
ScopeLevel("organization", "org_id", [
ScopeLevel("user", "user_id")
])
])
cache = Cache(scope_config=scope_config)
# Cache isolated by organization and user
@cache.cache(ttl_seconds=600, scope="user")
def get_user_data(user_id, org_id=None):
return fetch_from_database(user_id)
# Data automatically isolated by scope
user_data_org1 = get_user_data("123", org_id="org1")
user_data_org2 = get_user_data("123", org_id="org2")
# Different caches, same user_id!
๐ Storage Backends
Note: In-Memory storage is included by default. For Redis or MongoDB, install the respective extras.
In-Memory Storage (Default)
from cache import Cache
from storages.in_memory import InMemory
cache = Cache(storage_provider=InMemory())
Redis Storage
# Install Redis support
pip install cacheado[redis]
from cache import Cache
from storages.redis import RedisStorage
redis_storage = RedisStorage(
connection_string="redis://localhost:6379",
db=0
)
cache = Cache(storage_provider=redis_storage)
MongoDB Storage
# Install MongoDB support
pip install cacheado[mongodb]
from cache import Cache
from storages.mongodb import MongoDBStorage
mongo_storage = MongoDBStorage(
connection_string="mongodb://localhost:27017",
db_name="cache_db",
collection_name="cache_collection"
)
cache = Cache(storage_provider=mongo_storage)
๐ง Intelligent Eviction Policies
LRU (Least Recently Used)
from cache import Cache
from storages.in_memory import InMemory
from storages.rules.lru_evict import LRUEvict
storage = InMemory()
lru_rule = LRUEvict(max_items=1000)
cache = Cache(storage_provider=storage, storage_rules=[lru_rule])
TTL (Time-To-Live)
from storages.rules.lifetime_evict import LifeTimeEvict
storage = InMemory()
ttl_rule = LifeTimeEvict()
cache = Cache(storage_provider=storage, storage_rules=[ttl_rule])
# Items expire automatically based on TTL
cache.set("key1", "value1", ttl_seconds=60)
Max Items (Hard Limit)
from storages.rules.max_items_evict import MaxItemsEvict
storage = InMemory()
max_items_rule = MaxItemsEvict(max_items=500)
cache = Cache(storage_provider=storage, storage_rules=[max_items_rule])
Combining Multiple Rules
# Combine LRU + TTL for optimal memory management
storage = InMemory()
lru_rule = LRUEvict(max_items=1000)
ttl_rule = LifeTimeEvict()
cache = Cache(
storage_provider=storage,
storage_rules=[lru_rule, ttl_rule]
)
๐ Observability
Real-Time Metrics
stats = cache.stats()
print(stats)
# {
# "hits": 1250,
# "misses": 180,
# "evictions": 45,
# "storage_type": "in_memory",
# "total_keys": 8934
# }
Cache Hit Rate Monitoring
# Monitor cache effectiveness
stats = cache.stats()
hit_rate = stats["hits"] / (stats["hits"] + stats["misses"]) * 100
print(f"Cache hit rate: {hit_rate:.2f}%")
๐ ๏ธ Advanced Use Cases
Asynchronous Cache
import asyncio
# Native support for async/await
@cache.cache(ttl_seconds=180, scope="global")
async def fetch_api_data(endpoint):
async with httpx.AsyncClient() as client:
response = await client.get(endpoint)
return response.json()
# Async programmatic operations
await cache.aset("key1", "value1", ttl_seconds=300)
value = await cache.aget("key1")
await cache.aevict("key1")
await cache.aclear()
Programmatic Cache Operations
# Direct cache operations
cache.set("user_settings", {"theme": "dark"}, ttl_seconds=3600,
scope="user", org_id="org_123", user_id="user_456")
settings = cache.get("user_settings",
scope="user", org_id="org_123", user_id="user_456")
# Evict specific key
cache.evict("user_settings", scope="user", org_id="org_123", user_id="user_456")
Scope-based Eviction
# Remove all data from an organization
count = cache.evict_by_scope("organization", org_id="org_123")
print(f"Evicted {count} items")
# Remove data from a specific user
count = cache.evict_by_scope("user", org_id="org_123", user_id="user_456")
Decorator with Scope Parameters
@cache.cache(ttl_seconds=300, scope="user")
def get_user_preferences(user_id, org_id=None):
# org_id is automatically extracted for scope resolution
return load_preferences(user_id)
# Scope parameters extracted from kwargs
prefs = get_user_preferences("user_123", org_id="org_456")
๐ง Advanced Configuration
Custom Scope Hierarchies
from utils.cache_scope_config import ScopeConfig, ScopeLevel
# Configure complex hierarchies
scope_config = ScopeConfig([
ScopeLevel("organization", "org_id", [
ScopeLevel("department", "dept_id", [
ScopeLevel("user", "user_id", [
ScopeLevel("session", "session_id")
])
])
])
])
cache = Cache(scope_config=scope_config)
# Use nested scopes
@cache.cache(ttl_seconds=600, scope="session")
def get_session_data(session_id, org_id=None, dept_id=None, user_id=None):
return fetch_session_data(session_id)
Custom Storage Provider
from protocols.storage_provider import IStorageProvider
class CustomStorage(IStorageProvider):
def get(self, key: str):
# Implement custom get logic
pass
def set(self, key: str, value: Any, ttl_seconds: float):
# Implement custom set logic
pass
# Implement other required methods...
cache = Cache(storage_provider=CustomStorage())
Custom Eviction Rules
from protocols.storage_rule import IStorageRule
from utils.cache_types import RuleSideEffect, StorageRuleAction
class CustomRule(IStorageRule):
def on_get(self, key: str):
# Custom logic on get
return None
def on_set(self, key: str, value: Any, ttl_seconds: float):
# Custom logic on set
return None
# Implement other required methods...
cache = Cache(storage_rules=[CustomRule()])
๐งช Testing
# Run all tests
make test
# Tests with coverage
make test-coverage
# Run specific test file
python -m pytest tests/test_cache.py -v
# Run with coverage report
python -m pytest --cov=. --cov-report=html --cov-report=term-missing
๐ Project Structure
cache/
โโโ cache.py # Main Cache class
โโโ protocols/ # Protocol definitions
โ โโโ storage_provider.py # Storage backend interface
โ โโโ storage_rule.py # Eviction rule interface
โโโ storages/ # Storage implementations
โ โโโ in_memory.py # In-memory storage
โ โโโ redis.py # Redis storage
โ โโโ mongodb.py # MongoDB storage
โ โโโ rule_aware_storage.py # Rule decorator
โ โโโ rules/ # Eviction policies
โ โโโ lifetime_evict.py # TTL-based eviction
โ โโโ lru_evict.py # LRU eviction
โ โโโ max_items_evict.py # Max items eviction
โโโ utils/ # Utilities
โ โโโ cache_types.py # Type definitions
โ โโโ cache_scope_config.py # Scope configuration
โโโ tests/ # Test suite
โโโ test_cache.py
โโโ test_in_memory.py
โโโ test_redis.py
โโโ test_mongodb.py
โโโ ...
๐ฏ Design Principles
1. Protocol-Based Architecture
Uses Python protocols for loose coupling and easy extensibility.
2. Dependency Injection
Storage providers and rules are injected, enabling flexible composition.
3. Separation of Concerns
- Cache: High-level API and decorator logic
- Storage: Data persistence and retrieval
- Rules: Eviction policies and side effects
- Scopes: Hierarchical key resolution
4. Thread-Safe Operations
All storage operations are atomic and thread-safe.
5. Async-First Design
Full support for async/await with non-blocking operations.
๐ License
This project is open source and available under the MIT license.
๐ค Contributing
-
Fork and Clone
git clone https://github.com/GeorgeOgeorge/cacheado.git cd cacheado
-
Install Dependencies
pip install -r requirements.txt pip install -r requirements-build.txt
-
Run Tests
make test-coverage -
Code Quality
make lint make format
-
Submit Pull Request
- Maintain test coverage >90%
- Follow code standards (Black + isort + flake8)
- Add tests for new features
- Update documentation
๐ Known Limitations
- Redis and MongoDB require external services
- Async operations use
asyncio.to_threadfor sync storage backends - Scope validation happens at runtime, not compile-time
๐ Useful Links
Built with โค๏ธ for high-performance Python applications
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file cacheado-1.4.2.tar.gz.
File metadata
- Download URL: cacheado-1.4.2.tar.gz
- Upload date:
- Size: 22.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
cf0e6e3786ecd5c55cdd815219659bfd8525850291c746bf01f731866936764d
|
|
| MD5 |
2d8ba66234df14a265a220661fd5f3dd
|
|
| BLAKE2b-256 |
81f5632d06f7bd6cc88981df782a76203576aa5cc0783f4681c10da3e7712a69
|
Provenance
The following attestation bundles were made for cacheado-1.4.2.tar.gz:
Publisher:
release.yml on GeorgeOgeorge/cacheado
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
cacheado-1.4.2.tar.gz -
Subject digest:
cf0e6e3786ecd5c55cdd815219659bfd8525850291c746bf01f731866936764d - Sigstore transparency entry: 767491288
- Sigstore integration time:
-
Permalink:
GeorgeOgeorge/cacheado@e3d3b86d42665ecc23598c7d2598fc982c689e62 -
Branch / Tag:
refs/heads/master - Owner: https://github.com/GeorgeOgeorge
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@e3d3b86d42665ecc23598c7d2598fc982c689e62 -
Trigger Event:
pull_request
-
Statement type:
File details
Details for the file cacheado-1.4.2-py3-none-any.whl.
File metadata
- Download URL: cacheado-1.4.2-py3-none-any.whl
- Upload date:
- Size: 23.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
8981c6ea4b1a2e01a0c303841836453d4b4079c3320f74ad6e2d2e8dbb1fea93
|
|
| MD5 |
5b807779e60edd61fcd794639098d37f
|
|
| BLAKE2b-256 |
d84273f6430045a22c4553c59eba23fe7e7f5a99391b534b10adaa22a295cd28
|
Provenance
The following attestation bundles were made for cacheado-1.4.2-py3-none-any.whl:
Publisher:
release.yml on GeorgeOgeorge/cacheado
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
cacheado-1.4.2-py3-none-any.whl -
Subject digest:
8981c6ea4b1a2e01a0c303841836453d4b4079c3320f74ad6e2d2e8dbb1fea93 - Sigstore transparency entry: 767491290
- Sigstore integration time:
-
Permalink:
GeorgeOgeorge/cacheado@e3d3b86d42665ecc23598c7d2598fc982c689e62 -
Branch / Tag:
refs/heads/master - Owner: https://github.com/GeorgeOgeorge
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@e3d3b86d42665ecc23598c7d2598fc982c689e62 -
Trigger Event:
pull_request
-
Statement type: