Cache¶
Caching is how you survive traffic spikes without hammering the database on every request. Arvel treats caching as a contract (CacheContract) with multiple drivers, the same way Laravel swaps redis, file, or array behind a single facade-like surface in the container.
Configuration flows through CacheSettings: prefix, default TTL, Redis URL, and driver name—all overridable with CACHE_* environment variables.
The contract¶
CacheContract defines the async operations your application code should depend on:
get/put/forget/has— the usual key/value lifecycleflush— clear the configured store (use with care)remember— get from cache or run an async callback and store the result
Implementations in the framework include memory (great for tests and local dev), Redis (production-friendly), and null (a no-op that never persists—handy for dry runs).
Configuration¶
CacheSettings lives beside the rest of your module settings. Typical fields:
driver—"memory","redis", or"null"prefix— namespaces keys when you share a Redis instancedefault_ttl— seconds, used when callers omit TTLredis_url— connection string for the Redis driver
You set these via environment variables (CACHE_DRIVER, CACHE_REDIS_URL, etc.) or your config layer—whatever your app’s bootstrap prefers.
Using the cache in application code¶
Resolve CacheContract from the container (pattern depends on your app package) and call async methods:
from arvel.cache.contracts import CacheContract
async def expensive_stats(cache: CacheContract) -> dict[str, int]:
return await cache.remember(
"dashboard.stats",
ttl=300,
callback=_compute_stats,
)
async def _compute_stats() -> dict[str, int]:
# Hit the DB once, then serve from cache for five minutes
return {"users": 42, "orders": 7}
Mental model¶
Think “Laravel cache store,” but async-first and typed: your services take CacheContract, tests swap in memory or null, and production runs Redis without changing call sites. If you need to invalidate after a write, call forget for the keys you own—Arvel does not guess your domain’s consistency rules.
That separation—contract in code, driver in config—is what keeps cache from becoming a hidden global.