Skip to main content

reinhardt_utils/cache/
cache_trait.rs

1//! Base cache trait definition
2
3use async_trait::async_trait;
4use reinhardt_core::exception::Result;
5use serde::{Deserialize, Serialize};
6use std::collections::HashMap;
7use std::time::Duration;
8
9/// Base cache trait
10#[async_trait]
11pub trait Cache: Send + Sync {
12	/// Get a value from the cache
13	async fn get<T>(&self, key: &str) -> Result<Option<T>>
14	where
15		T: for<'de> Deserialize<'de> + Serialize + Send + Sync;
16
17	/// Set a value in the cache with optional TTL
18	async fn set<T>(&self, key: &str, value: &T, ttl: Option<Duration>) -> Result<()>
19	where
20		T: Serialize + Send + Sync;
21
22	/// Delete a value from the cache
23	async fn delete(&self, key: &str) -> Result<()>;
24
25	/// Check if a key exists in the cache
26	async fn has_key(&self, key: &str) -> Result<bool>;
27
28	/// Clear all values from the cache
29	async fn clear(&self) -> Result<()>;
30
31	/// Get multiple values at once
32	async fn get_many<T>(&self, keys: &[&str]) -> Result<HashMap<String, T>>
33	where
34		T: for<'de> Deserialize<'de> + Serialize + Send + Sync,
35	{
36		let mut results = HashMap::new();
37		for key in keys {
38			if let Some(value) = self.get::<T>(key).await? {
39				results.insert(key.to_string(), value);
40			}
41		}
42		Ok(results)
43	}
44
45	/// Set multiple values at once
46	async fn set_many<T>(&self, values: HashMap<String, T>, ttl: Option<Duration>) -> Result<()>
47	where
48		T: Serialize + Send + Sync,
49	{
50		for (key, value) in values.iter() {
51			self.set(key, value, ttl).await?;
52		}
53		Ok(())
54	}
55
56	/// Delete multiple keys at once
57	async fn delete_many(&self, keys: &[&str]) -> Result<()> {
58		for key in keys {
59			self.delete(key).await?;
60		}
61		Ok(())
62	}
63
64	/// Increment a numeric value
65	///
66	/// # Warning
67	///
68	/// Default implementation is not atomic. The get-modify-set sequence is
69	/// subject to race conditions under concurrent access. Override in backends
70	/// that support atomic operations (e.g., Redis INCRBY).
71	async fn incr(&self, key: &str, delta: i64) -> Result<i64> {
72		// WARNING: Default implementation is not atomic.
73		// Override in backends that support atomic operations.
74		let current: i64 = self.get(key).await?.unwrap_or(0);
75		let new_value = current + delta;
76		self.set(key, &new_value, None).await?;
77		Ok(new_value)
78	}
79
80	/// Decrement a numeric value
81	///
82	/// # Warning
83	///
84	/// Default implementation is not atomic. See [`Cache::incr`] for details.
85	async fn decr(&self, key: &str, delta: i64) -> Result<i64> {
86		self.incr(key, -delta).await
87	}
88}