use std::time::Duration;
use amalgam::{Cache, CacheEvent, EntryOptions};
#[tokio::main]
async fn main() {
let cache: Cache<String> = Cache::new();
let mut events = cache.events().subscribe();
let opts = EntryOptions::new(Duration::from_millis(200)).with_fail_safe(
true,
Some(Duration::from_secs(60 * 60)),
Some(Duration::from_secs(1)),
);
let primed = cache
.get_or_set_with(
"report",
|ctx| async move { Ok(ctx.value("GOOD report data".to_owned())) },
opts.clone(),
)
.await
.expect("priming succeeds");
println!("primed value => {primed:?}");
tokio::time::sleep(Duration::from_millis(250)).await;
println!("(slept 250ms — the entry is now stale)");
let served = cache
.get_or_set_with(
"report",
|ctx| async move {
println!(" [factory] backend is down — returning an error");
Err(ctx.fail("backend timeout"))
},
opts,
)
.await
.expect("fail-safe serves stale instead of erroring");
println!("served after failure => {served:?} (stale value reused)");
assert_eq!(
served, "GOOD report data",
"fail-safe must serve the stale value"
);
let mut saw_fail_safe = false;
while let Ok(event) = events.try_recv() {
if let CacheEvent::FailSafeActivate { key } = event {
println!("event: FailSafeActivate {{ key: {key:?} }}");
saw_fail_safe = true;
}
}
assert!(
saw_fail_safe,
"a FailSafeActivate event should have been emitted"
);
println!("OK: stale value served and FailSafeActivate observed.");
}