wacore/store/cache.rs
1//! Pluggable cache storage trait.
2//!
3//! Implementations of [`CacheStore`] can back any of the client's data caches
4//! (group metadata, device lists, LID-PN mappings, etc.). The default behaviour
5//! uses in-process moka caches; a Redis, Memcached, or any other implementation
6//! can be plugged in via [`CacheConfig`](crate::CacheConfig).
7
8use async_trait::async_trait;
9use std::time::Duration;
10
11/// Backend trait for pluggable cache storage.
12///
13/// Keys and values are opaque strings / bytes — the typed cache wrapper in
14/// `whatsapp-rust` handles serialization via serde.
15///
16/// # Namespaces
17///
18/// Each logical cache uses a unique namespace string (e.g., `"group"`,
19/// `"device"`, `"lid_pn_by_lid"`). Implementations should use this to
20/// partition keys — for example, a Redis implementation might prefix keys
21/// as `{namespace}:{key}`.
22///
23/// # Error handling
24///
25/// Cache operations are best-effort. The client falls back gracefully when
26/// cache reads fail (treats as miss) and logs warnings on write failures.
27/// Implementations should still return errors for observability.
28#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
29#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
30pub trait CacheStore: Send + Sync + 'static {
31 /// Retrieve a cached value by namespace and key.
32 async fn get(&self, namespace: &str, key: &str) -> anyhow::Result<Option<Vec<u8>>>;
33
34 /// Store a value with an optional TTL.
35 ///
36 /// When `ttl` is `None`, the entry should persist until explicitly deleted
37 /// or evicted by the implementation's own policy.
38 async fn set(
39 &self,
40 namespace: &str,
41 key: &str,
42 value: &[u8],
43 ttl: Option<Duration>,
44 ) -> anyhow::Result<()>;
45
46 /// Delete a single key from the given namespace.
47 async fn delete(&self, namespace: &str, key: &str) -> anyhow::Result<()>;
48
49 /// Delete all keys in a namespace.
50 async fn clear(&self, namespace: &str) -> anyhow::Result<()>;
51
52 /// Return the approximate number of entries in a namespace.
53 ///
54 /// Used only for diagnostics. Implementations that cannot cheaply
55 /// report counts should return `Ok(0)`.
56 async fn entry_count(&self, _namespace: &str) -> anyhow::Result<u64> {
57 Ok(0)
58 }
59}