Getting started
Installation
ferncache requires Rust 1.75+. Add it to your project:
cargo add ferncache
Quick start
Here is a complete program that uses ferncache.
use std::time::Duration;
use ferncache::{Store, Error};
#[tokio::main]
async fn main() -> Result<(), Error> {
let store = Store::builder()
.max_entries(10_000)
.default_ttl(Duration::from_secs(300))
.build()?;
store.set("user:42", b"Ada").await?;
let v = store.get("user:42").await?;
println!("{v:?}");
Ok(())
}
Choosing a capacity
Every store has a capacity, expressed either as a number of entries or as a total cost. When an insert would exceed it, ferncache evicts entries until the new one fits.
Cost is whatever you want it to be: bytes, rows, or a constant 1. Start with the number of entries and switch to cost only when your values vary a lot in size.
Expiration
Entries can expire after a fixed time-to-live. The default TTL applies to every insert; pass an explicit TTL to override it for a single key.
Expired entries are removed lazily, when they are read or when their shard needs room. There is no background thread or timer per entry.
Loading on a miss
Use the loader form of a read to fill the store from a slower source. If several callers miss the same key at the same time, only the first one runs the loader; the others wait for its result.
Errors returned by the loader are not cached. The next caller will try again.
Sharding
Keys are hashed into a fixed number of shards. More shards mean less lock contention but slightly more memory overhead; the default works well up to dozens of cores.
The shard count must be a power of two and cannot be changed after the store is created.
Testing
Inject a fake clock to test expiration without sleeping. All time-dependent behaviour in ferncache goes through it.
Call clear() between tests instead of creating a new store if construction is expensive in your setup.