use std::sync::Arc;
use std::sync::atomic::{AtomicUsize, Ordering};
use amalgam::Cache;
#[tokio::main]
async fn main() {
let cache: Cache<String> = Cache::new();
let factory_runs = Arc::new(AtomicUsize::new(0));
let first = {
let runs = factory_runs.clone();
cache
.get_or_set("greeting", move |ctx| async move {
runs.fetch_add(1, Ordering::SeqCst);
println!(" [factory] running — computing the value the slow way…");
Ok(ctx.value("Hello from the factory".to_owned()))
})
.await
.expect("factory succeeded")
};
println!("1st get_or_set => {first:?}");
let second = {
let runs = factory_runs.clone();
cache
.get_or_set("greeting", move |ctx| async move {
runs.fetch_add(1, Ordering::SeqCst);
Ok(ctx.value("(this should not appear)".to_owned()))
})
.await
.expect("served from cache")
};
println!("2nd get_or_set => {second:?} (served from L1, no factory call)");
let runs = factory_runs.load(Ordering::SeqCst);
println!("\nfactory ran {runs} time(s) — expected exactly 1");
assert_eq!(runs, 1, "the second call must be a cache hit");
assert_eq!(first, second);
println!("OK: second call was a cache hit.");
}