PSR-like cache pools live in serenade-cache.
| Piece | Role |
|---|---|
CacheItem / ArrayCacheItem |
Key, hit flag, Arc value, optional TTL, optional tags |
CacheItemPool / ArrayAdapter |
In-memory get/save/delete/clear; tag invalidation |
FilesystemAdapter |
Disk-backed pool (directory + prefix); TTL in file header |
CacheMarshaller / BytesMarshaller |
Wire encoding (Vec<u8>, String) for durable adapters |
RedisAdapter (feature redis) |
Redis via redis-rs + r2d2 |
cache.pool tag |
DI tag; RegisterDefaultCachePoolPass seeds cache.app with ArrayAdapter |
Symfony-shaped tags on items, invalidation on the pool:
use std::sync::Arc;
use serenade_cache::{ArrayAdapter, ArrayCacheItem, CacheItem, CacheItemPool};
let pool = ArrayAdapter::new();
let mut item = ArrayCacheItem::miss("product:42");
item.set(Arc::new(String::from("payload")));
item.tag(&["product", "catalog"]);
pool.save(item)?;
pool.invalidate_tags(&["product"])?; // removes every item tagged `product`- Empty tag names are ignored when tagging or invalidating
- Re-saving an item without tags clears its previous tag links
ArrayAdapterkeeps an in-memory tag indexFilesystemAdapterembeds tags in the on-disk record (format v2) and indexes them under{prefix}/.tags/RedisAdapter(featureredis) stores tag membership in Redis SETs ({prefix}\0tag\0…/{prefix}\0tags\0…)
No feature flag. Open with a directory and optional prefix subdirectory (default serenade):
use std::sync::Arc;
use serenade_cache::{
BytesMarshaller, CacheItemPool, FilesystemAdapter, FilesystemAdapterConfig,
};
let pool = FilesystemAdapter::open(
FilesystemAdapterConfig::new("/var/cache/myapp").with_prefix("serenade"),
Arc::new(BytesMarshaller),
)?;- One file per key under
{directory}/{prefix}/{hex(key)}.cache - File header stores version + absolute expiry (Unix millis);
0means no TTL - Format v2 also stores invalidation tags; tag membership lives in
{prefix}/.tags/{hex(tag)}.idx - Expired items are deleted on read (
get_item/ miss path), including tag unlinking clearremoves*.cachefiles and the.tagsindex directory (not the whole disk)- Values must be marshallable (
BytesMarshaller:String/Vec<u8>); other types: serialize in the app first - Atomic write via temp file + rename
Default DI pass still registers ArrayAdapter. Apps register FilesystemAdapter (or Redis) themselves under cache.pool / cache.app.
Enable with --features redis on serenade-cache.
- URL:
RedisAdapterConfig::new("redis://127.0.0.1:6379/0") - Logical key
cart:1becomes Redis key{prefix}cart:1(default prefixserenade:) - TTL uses
SET … PX - Tags: SET
{prefix}\0tags\0{key}(tag names) and SET{prefix}\0tag\0{tag}(member keys);invalidate_tagsdeletes members clearrunsSCAN MATCH {prefix}*thenDEL(neverFLUSHDB), including tag metadata keys- Uses the same
BytesMarshalleras the filesystem adapter
CacheItemPool is sync. Async HTTP callers should use spawn_blocking (or call from sync code).
make redis-up
make redis-test
make redis-down
Compose file: docker/compose.yml (redis:7-alpine on port 6379). Override with REDIS_URL.
BytesMarshaller stores tagged Vec<u8> and String payloads. Other types: serialize in the app, then CacheItem::set(Arc::new(bytes)).
Application item pools (serenade-cache) are not the same as HTTP caching. Helpers live in serenade-http:
| Piece | Role |
|---|---|
HttpCacheHeaders |
Build Cache-Control, ETag, Last-Modified, Vary on a Response |
etag / weak_etag |
Quote strong / weak validators |
maybe_not_modified |
Conditional GET/HEAD → 304 when validators match |
use serenade_http::{
HttpCacheHeaders, Method, Request, Response, etag, maybe_not_modified,
};
let response = HttpCacheHeaders::public_max_age(60)
.with_etag(etag("v1"))
.with_vary("Accept-Encoding")
.apply(Response::text(200, "body"));
let request = Request::new(Method::Get, "/page").with_header("If-None-Match", "\"v1\"");
let response = maybe_not_modified(&request, response); // 304, empty bodyIf-None-Matchtakes precedence overIf-Modified-Sincewhen both are sent- 304 keeps
cache-control,etag,last-modified,vary, andexpiresfrom the full response - Does not configure Varnish, ESI, or CDN products