Skip to main content

Add your description here

Project description

🌐 cachka

Enterprise-grade hybrid cache for Python
Combines in-memory (L1) and disk-based (L2) caching with observability, encryption, and circuit breaking.
Works seamlessly in async, sync, and threaded environments.

PyPI - Version PyPI - Python Version License


✨ Features

  • Hybrid architecture: L1 (memory) + L2 (SQLite disk)
  • Async & sync support: Use the same decorator everywhere
  • TTL with smart LRU eviction (no memory leaks)
  • Observability: Prometheus metrics, OpenTelemetry tracing
  • Security: AES-GCM encryption for disk storage
  • Resilience: Circuit breaker, graceful degradation
  • Zero dependencies for core functionality
  • Type-safe: Full type hints and Pydantic config

🚀 Quick Start

1. Install

# Core (required)
pip install cachka

# With Prometheus metrics
pip install "cachka[prometheus]"

# Full enterprise features
pip install "cachka[full]"

2. Initialize Cache

from cachka import cache_registry, CacheConfig

# Basic initialization
cache_registry.initialize()

# Or with custom configuration
config = CacheConfig(
    db_path="my_cache.db",
    l1_maxsize=2048,  # L1 cache size
    l1_ttl=600,       # L1 TTL in seconds
    enable_metrics=True,
    enable_encryption=True,
    encryption_key="your-base64-encoded-32-byte-key"
)
cache_registry.initialize(config)

📖 Usage Examples

Basic Async Function Caching

import asyncio
from cachka import cached, cache_registry, CacheConfig

# Initialize cache
config = CacheConfig(db_path="cache.db")
cache_registry.initialize(config)

@cached(ttl=300)  # Cache for 5 minutes
async def fetch_user_data(user_id: int):
    # Simulate API call
    await asyncio.sleep(0.1)
    return {"id": user_id, "name": f"User {user_id}"}

async def main():
    # First call - fetches data
    user1 = await fetch_user_data(1)
    print(user1)  # {"id": 1, "name": "User 1"}
    
    # Second call - returns cached data (no API call)
    user1_cached = await fetch_user_data(1)
    print(user1_cached)  # {"id": 1, "name": "User 1"} (from cache)
    
    # Cleanup
    await cache_registry.shutdown()

asyncio.run(main())

Sync Function Caching

from cachka import cached, cache_registry, CacheConfig

cache_registry.initialize()

@cached(ttl=60)
def expensive_computation(n: int) -> int:
    """Fibonacci calculation - cached after first call"""
    if n < 2:
        return n
    return expensive_computation(n - 1) + expensive_computation(n - 2)

# First call - computes
result1 = expensive_computation(30)  # Takes time

# Second call - returns cached result instantly
result2 = expensive_computation(30)  # Instant!

Class Methods with ignore_self

from cachka import cached, cache_registry, CacheConfig

cache_registry.initialize()

class UserService:
    @cached(ttl=300, ignore_self=True)
    async def get_user(self, user_id: int):
        # Cache key will be based on user_id only, not self instance
        return await self._fetch_from_db(user_id)
    
    async def _fetch_from_db(self, user_id: int):
        # Database query simulation
        return {"id": user_id, "name": f"User {user_id}"}

service = UserService()
user = await service.get_user(123)  # Cached by user_id only

Advanced Configuration

from cachka import cache_registry, CacheConfig
import base64
import secrets

# Generate encryption key (32 bytes, base64-encoded)
encryption_key = base64.b64encode(secrets.token_bytes(32)).decode()

config = CacheConfig(
    db_path="secure_cache.db",
    name="my_cache",
    l1_maxsize=4096,              # Larger L1 cache
    l1_ttl=1800,                   # 30 minutes L1 TTL
    vacuum_interval=3600,          # Cleanup every hour
    cleanup_on_start=True,          # Clean expired on startup
    enable_metrics=True,            # Prometheus metrics
    enable_encryption=True,         # AES-GCM encryption
    encryption_key=encryption_key,  # Your encryption key
    circuit_breaker_threshold=50,   # Open circuit after 50 failures
    circuit_breaker_window=60       # Recovery window: 60 seconds
)

cache_registry.initialize(config)

Graceful Shutdown

import asyncio
from cachka import cache_registry

async def main():
    # Your application code
    pass

# Cleanup on application exit
async def cleanup():
    await cache_registry.shutdown()

# In FastAPI, for example:
# @app.on_event("shutdown")
# async def shutdown_event():
#     await cache_registry.shutdown()

Accessing Metrics (Prometheus)

from cachka import cache_registry

# After enabling metrics in config
cache = cache_registry.get()
metrics_text = cache.get_metrics_text()
print(metrics_text)
# Output: Prometheus metrics in text format

Health Check

from cachka import cache_registry

cache = cache_registry.get()
health = await cache.health_check()
print(health)
# {
#     "status": "healthy",
#     "l1_size": 42,
#     "circuit_breaker": "CLOSED",
#     "storage": "ok"
# }

FastAPI Integration

from fastapi import FastAPI
from cachka import cached, cache_registry, CacheConfig

app = FastAPI()

# Initialize cache on startup
@app.on_event("startup")
async def startup():
    config = CacheConfig(
        db_path="api_cache.db",
        enable_metrics=True
    )
    cache_registry.initialize(config)

# Cleanup on shutdown
@app.on_event("shutdown")
async def shutdown():
    await cache_registry.shutdown()

# Use cache in your endpoints
@app.get("/users/{user_id}")
@cached(ttl=300)
async def get_user(user_id: int):
    # Expensive database query - cached for 5 minutes
    return {"id": user_id, "name": f"User {user_id}"}

@app.get("/health")
async def health():
    cache = cache_registry.get()
    return await cache.health_check()

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

cachka-0.1.4.tar.gz (12.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

cachka-0.1.4-py3-none-any.whl (11.2 kB view details)

Uploaded Python 3

File details

Details for the file cachka-0.1.4.tar.gz.

File metadata

  • Download URL: cachka-0.1.4.tar.gz
  • Upload date:
  • Size: 12.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.9.15 {"installer":{"name":"uv","version":"0.9.15","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for cachka-0.1.4.tar.gz
Algorithm Hash digest
SHA256 0384207f50695e286e543b3e9e4b45fa046aaf5278844a1cd94d02268aa4dfcd
MD5 7697b2d77f774305bb1883862329e53f
BLAKE2b-256 b56495989e11647fccb247b928986ccca00bb92f41f0fdd4fe06d06a9cd88825

See more details on using hashes here.

File details

Details for the file cachka-0.1.4-py3-none-any.whl.

File metadata

  • Download URL: cachka-0.1.4-py3-none-any.whl
  • Upload date:
  • Size: 11.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.9.15 {"installer":{"name":"uv","version":"0.9.15","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for cachka-0.1.4-py3-none-any.whl
Algorithm Hash digest
SHA256 8f563f4acd460b3b46ccec5fe8959574a667b7eacd82b26672ac5483811329b8
MD5 b68f8c5d4d79542663d685ade9f63afc
BLAKE2b-256 cd4ed3e56bc5a4c69feabaf500a36340dbf216d20a5f16d614ca621a1a25af8d

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page