Self-hosted caching solution for Python applications
Project description
CacheFn Python SDK
Self-hosted caching solution for Python applications
CacheFn is a developer-first caching library that provides memory caching, function memoization, and tag-based invalidation with zero external dependencies.
Status
- Version: 0.1.0 (V0)
- Python: ✅ Complete (Memory storage)
- TypeScript SDK: ✅ Complete
Features
✅ Zero Dependencies - No Redis, Memcached, or external services required
✅ Memory Storage - In-memory cache with LRU eviction
✅ Type-Safe - Full type hints with Pydantic models
✅ Function Memoization - Cache expensive function results
✅ Tag-based Invalidation - Flexible cache invalidation strategies
✅ Analytics - Built-in hit/miss tracking and statistics
✅ Async First - Built for modern async Python applications
Installation
pip install cachefn
Or install from source:
cd cachefn/python
pip install -e .
Quick Start
Basic Usage
from cachefn import cache_fn
import asyncio
async def main():
# Create a cache instance
cache = cache_fn(
name="my-cache",
storage="memory",
max_size=1000,
default_ttl=60000, # 1 minute
)
# Set a value
await cache.set("user:123", {"name": "Alice", "age": 30})
# Get a value
user = await cache.get("user:123")
print(user) # {'name': 'Alice', 'age': 30}
# Set with TTL and tags
await cache.set(
"session:abc",
{"user_id": "123", "token": "xyz"},
ttl=3600000, # 1 hour
tags=["sessions", "user:123"],
)
# Invalidate by tag
await cache.invalidate_by_tag("sessions")
# Get stats
stats = await cache.get_stats()
print(f"Hit rate: {stats.hit_rate:.2f}%")
if __name__ == "__main__":
asyncio.run(main())
Function Memoization
from cachefn import memoize
import asyncio
@memoize(ttl=60000, max_size=500)
async def expensive_operation(user_id: str):
"""This function's results will be cached."""
# Simulate expensive operation
await asyncio.sleep(1)
return {"user_id": user_id, "data": "expensive result"}
async def main():
# First call - takes 1 second
result = await expensive_operation("123")
# Second call - instant (cached)
result = await expensive_operation("123")
# Clear cache for this function
await expensive_operation.clear()
if __name__ == "__main__":
asyncio.run(main())
Synchronous Memoization
from cachefn import memoize_sync
@memoize_sync(max_size=1000)
def fibonacci(n: int) -> int:
"""Memoized fibonacci function."""
if n <= 1:
return n
return fibonacci(n - 1) + fibonacci(n - 2)
# Fast computation due to memoization
print(fibonacci(100))
Cache-Aside Pattern
from cachefn import cache_fn
import asyncio
async def fetch_user_from_db(user_id: str):
"""Simulate database fetch."""
await asyncio.sleep(0.5)
return {"id": user_id, "name": "Alice"}
async def main():
cache = cache_fn(name="users", max_size=100)
# Get or fetch pattern
user = await cache.get_or_fetch(
f"user:{user_id}",
fetcher=lambda: fetch_user_from_db(user_id),
ttl=300000, # 5 minutes
tags=["users"],
)
if __name__ == "__main__":
asyncio.run(main())
API Reference
CacheFn Class
Constructor
cache_fn(
name: str,
storage: str = "memory",
max_size: Optional[int] = None,
default_ttl: Optional[int] = None,
namespace: Optional[str] = None,
) -> CacheFn
Core Methods
async get(key: str) -> Optional[Any]- Get a value from cacheasync set(key: str, value: Any, ttl: Optional[int] = None, tags: Optional[list[str]] = None) -> None- Set a valueasync has(key: str) -> bool- Check if key existsasync delete(key: str) -> bool- Delete a keyasync clear() -> None- Clear all entries
Batch Operations
async get_many(keys: list[str]) -> list[Optional[Any]]- Get multiple valuesasync set_many(entries: list[dict]) -> None- Set multiple valuesasync delete_many(keys: list[str]) -> None- Delete multiple keys
Utility Methods
async get_or_fetch(key, fetcher, ttl, tags) -> Any- Cache-aside patternasync keys(pattern: Optional[str]) -> list[str]- Get keys matching patternasync size() -> int- Get number of entriesasync entries(pattern, limit) -> list[dict]- Get entries
Invalidation
async invalidate(key: str) -> bool- Invalidate single keyasync invalidate_by_tag(tag: str) -> None- Invalidate by tagasync invalidate_by_tags(tags: list[str]) -> None- Invalidate by multiple tagsasync invalidate_by_pattern(pattern: str) -> None- Invalidate by glob pattern
Analytics
async get_stats() -> CacheStats- Get cache statisticson(event: str, handler: Callable) -> None- Register event handleroff(event: str, handler: Callable) -> None- Unregister event handler
Memoization
Async Memoization
@memoize(
ttl: Optional[int] = None,
max_size: Optional[int] = None,
storage: str = "memory",
tags: Optional[list[str]] = None,
key_generator: Optional[Callable] = None,
)
async def my_function(...):
...
Sync Memoization
@memoize_sync(
max_size: int = 1000,
key_generator: Optional[Callable] = None,
)
def my_function(...):
...
Events
CacheFn emits events for monitoring:
cache = cache_fn(name="monitored")
cache.on("hit", lambda event: print(f"Cache hit: {event.key}"))
cache.on("miss", lambda event: print(f"Cache miss: {event.key}"))
cache.on("set", lambda event: print(f"Cache set: {event.key}"))
cache.on("delete", lambda event: print(f"Cache delete: {event.key}"))
cache.on("eviction", lambda event: print(f"Evicted: {event.key}"))
cache.on("invalidate", lambda event: print(f"Invalidated {event.count} keys"))
Statistics
stats = await cache.get_stats()
print(f"Hits: {stats.hits}")
print(f"Misses: {stats.misses}")
print(f"Hit Rate: {stats.hit_rate:.2f}%")
print(f"Size: {stats.size}")
print(f"Memory Usage: {stats.memory_usage} bytes")
Integration with SuperFunctions
CacheFn integrates seamlessly with other superfunctions packages:
from cachefn import cache_fn
# Future: from superfunctions.db import create_adapter
# Use with database adapter (coming soon)
cache = cache_fn(
name="app-cache",
storage="memory", # Future: "db" with superfunctions adapter
)
Examples
See the examples/ directory for more examples:
basic_usage.py- Basic cache operationsmemoization.py- Function memoization examplespatterns.py- Common caching patterns
Development
Setup
cd cachefn/python
pip install -e ".[dev]"
Run Tests
pytest
pytest --cov=cachefn
Type Checking
mypy cachefn
Linting
ruff check cachefn
black cachefn
Architecture
cachefn/
├── core/
│ ├── cache.py # Main CacheFn class
│ ├── types.py # Type definitions
│ └── events.py # Event emitter
├── storage/
│ └── memory_storage.py # Memory storage backend
├── memoization/
│ └── memoize.py # Function memoization
├── analytics/
│ └── stats.py # Statistics tracking
└── utils/
├── hash.py # Key hashing
├── pattern.py # Pattern matching
├── serialize.py # Serialization
└── ttl.py # TTL utilities
Roadmap
- Memory storage with LRU eviction
- Function memoization
- Tag-based invalidation
- Analytics and events
- IndexedDB-like storage (file-based)
- Integration with
superfunctions.dbadapters - FastAPI middleware
- Flask middleware
- Compression support
License
Apache-2.0
Contributing
Contributions are welcome! Please see the main superfunctions repository for contribution guidelines.
Project details
Release history Release notifications | RSS feed
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 cachefn-0.0.1.tar.gz.
File metadata
- Download URL: cachefn-0.0.1.tar.gz
- Upload date:
- Size: 19.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c1b87836b686f4660339aa7db2441e70afd38718b3eb022ae5114396c883aa8b
|
|
| MD5 |
58b7d0b22d2f4c1af147bded8a57507d
|
|
| BLAKE2b-256 |
021a657c2b82c45a89a3644eff66fd66b79dd5a9818e968785599645c59ae975
|
File details
Details for the file cachefn-0.0.1-py3-none-any.whl.
File metadata
- Download URL: cachefn-0.0.1-py3-none-any.whl
- Upload date:
- Size: 17.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0b380c04d71f0d56d9254d1f6fc6b9b5c4b137b2024f6b934f96eb0637a71bf7
|
|
| MD5 |
d87e133614a7363b5aade31b135c2545
|
|
| BLAKE2b-256 |
0040f5b98074c967fc7c7fe0fe8762360a809c5862b7def63528d0beb8db21a3
|