Cache¶
Memoization decorator with TTL, LRU, and file-backed strategies. Auto-detects async functions.
TL;DR¶
from kstlib.cache import cache
@cache(ttl=300)
def expensive_computation(x: int) -> int:
return x ** 2
result = expensive_computation(5) # Computed
result = expensive_computation(5) # Cached
Key Features¶
Auto-detection: Works with both sync and async functions
Multiple strategies: TTL, LRU, and file-backed caching
Configuration-driven: Settings from
kstlib.conf.ymlor per-call overridesCache management:
cache_clear()andcache_info()on wrapped functions
Quick Start¶
from kstlib.cache import cache
# 1. TTL-based caching (expires after 60 seconds)
@cache(ttl=60)
def get_weather(city: str) -> dict:
return api.fetch_weather(city)
# 2. LRU caching (fixed-size, evicts oldest)
@cache(strategy="lru", maxsize=512)
def get_user(user_id: int) -> dict:
return db.fetch_user(user_id)
# 3. File-backed caching (persistent across restarts)
@cache(strategy="file", cache_dir="/tmp/cache")
def load_data(path: str) -> dict:
return parse_file(path)
How It Works¶
The @cache decorator wraps your function and stores results keyed by arguments.
Three strategies available:
Strategy |
Expiration |
Persistence |
Use Case |
|---|---|---|---|
|
Time-based |
Memory only |
API responses, volatile data |
|
Size-based |
Memory only |
Bounded memory, frequent lookups |
|
Optional mtime |
Disk |
Large data, survives restarts |
Async auto-detection: The decorator inspects whether your function is async and creates the appropriate wrapper automatically.
# Sync function -> sync wrapper
@cache(ttl=60)
def sync_fetch(x): ...
# Async function -> async wrapper (detected automatically)
@cache(ttl=60)
async def async_fetch(x): ...
Cache key generation: Arguments are hashed to create unique cache keys. For file-backed caching, the first positional argument can be used for mtime checks.
Configuration¶
In kstlib.conf.yml¶
cache:
default_strategy: ttl
ttl:
default_seconds: 600
max_entries: 2048
lru:
maxsize: 1024
file:
cache_dir: ~/.cache/kstlib
serializer: json # json | pickle | auto
Per-call overrides¶
@cache(
strategy="file",
cache_dir="/tmp/kst-cache",
serializer="auto",
)
def expensive_lookup(key: str) -> dict:
return fetch_remote(key)
Common Patterns¶
API response caching¶
@cache(ttl=300) # 5-minute cache
def get_exchange_rate(pair: str) -> float:
return api.fetch_rate(pair)
Database query caching¶
@cache(strategy="lru", maxsize=1024)
def get_user_profile(user_id: int) -> dict:
return db.query("SELECT * FROM users WHERE id = %s", user_id)
Config file with auto-invalidation¶
@cache(strategy="file", check_mtime=True)
def read_config(path: Path) -> dict:
return load_yaml(path) # Re-reads if file changes
Async trading data¶
@cache(strategy="lru", maxsize=256)
async def fetch_order_book(symbol: str) -> dict:
return await exchange.get_book(symbol)
Cache management¶
@cache(ttl=300)
def expensive_call(x: int) -> int:
return x ** 2
# Clear all cached entries
expensive_call.cache_clear()
# Get cache statistics
info = expensive_call.cache_info()
print(f"Hits: {info.hits}, Misses: {info.misses}")
Troubleshooting¶
Cache not invalidating¶
TTL strategy: Entries only expire on access. If ttl=60 and you access after 120s, it will recompute.
File strategy with mtime: Ensure check_mtime=True is set and the path argument is first.
# Correct - path is first argument
@cache(strategy="file", check_mtime=True)
def read_file(path: Path, encoding: str = "utf-8") -> str: ...
# Wrong - path is not first, mtime check won't work
@cache(strategy="file", check_mtime=True)
def read_file(encoding: str, path: Path) -> str: ...
Memory growing too large¶
Use LRU with a bounded maxsize:
@cache(strategy="lru", maxsize=512) # Max 512 entries
def bounded_cache(key: str) -> dict: ...
Pickle security warning¶
Warning
Only use pickle or auto serializer when the cache is read/written on the same trusted host. Never deserialize untrusted cache files.
For safer serialization:
@cache(strategy="file", serializer="json") # Safe but limited types
def safe_cache(key: str) -> dict: ...
File serializer compatibility¶
Serializer |
Pros |
Cons |
|---|---|---|
|
Safe, human-readable |
Limited types (no datetime, set, etc.) |
|
Any Python object |
Security risk with untrusted data |
|
Best of both |
Tries JSON first, falls back to pickle |
API Reference¶
Full autodoc: Cache Utilities
Function |
Description |
|---|---|
|
Decorator for memoization |
|
Clear all cached entries |
|
Get hit/miss statistics |