Skip to main content

doido_cache/
versioning.rs

1//! Recyclable cache versioning (Rails `cache_versioning`): a stored entry
2//! carries a version, and a read with a different version is a miss — so bumping
3//! the version cheaply invalidates without deleting keys.
4
5use crate::store::CacheStore;
6use doido_core::Result;
7use serde_json::{json, Value};
8
9/// A versioned key: `versioned_key("post/1", 3)` → `"post/1:v3"`.
10pub fn versioned_key(key: &str, version: u64) -> String {
11    format!("{key}:v{version}")
12}
13
14/// Store `value` under `key` tagged with `version`.
15pub async fn write_versioned(
16    store: &dyn CacheStore,
17    key: &str,
18    version: u64,
19    value: Value,
20    ttl_secs: Option<u64>,
21) -> Result<()> {
22    store
23        .set(key, json!({ "__v": version, "value": value }), ttl_secs)
24        .await
25}
26
27/// Read `key` only if its stored version matches `version`; a mismatch (or a
28/// missing key) is a miss.
29pub async fn read_versioned(
30    store: &dyn CacheStore,
31    key: &str,
32    version: u64,
33) -> Result<Option<Value>> {
34    match store.get(key).await? {
35        Some(entry) if entry.get("__v") == Some(&json!(version)) => Ok(entry.get("value").cloned()),
36        _ => Ok(None),
37    }
38}