rustvello_mem/
client_data_store.rs1use std::collections::HashMap;
4use tokio::sync::Mutex;
5
6use async_trait::async_trait;
7
8use rustvello_core::client_data_store::ClientDataStore;
9use rustvello_core::error::{RustvelloError, RustvelloResult};
10
11pub struct MemClientDataStore {
16 data: Mutex<HashMap<String, String>>,
17}
18
19impl MemClientDataStore {
20 pub fn new() -> Self {
21 Self {
22 data: Mutex::new(HashMap::new()),
23 }
24 }
25}
26
27impl Default for MemClientDataStore {
28 fn default() -> Self {
29 Self::new()
30 }
31}
32
33#[async_trait]
34impl ClientDataStore for MemClientDataStore {
35 async fn store(&self, key: &str, value: &str) -> RustvelloResult<()> {
36 self.data
37 .lock()
38 .await
39 .insert(key.to_owned(), value.to_owned());
40 Ok(())
41 }
42
43 async fn retrieve(&self, key: &str) -> RustvelloResult<String> {
44 self.data
45 .lock()
46 .await
47 .get(key)
48 .cloned()
49 .ok_or_else(|| RustvelloError::state_backend(format!("key not found: {key}")))
50 }
51
52 async fn purge(&self) -> RustvelloResult<()> {
53 self.data.lock().await.clear();
54 Ok(())
55 }
56
57 fn backend_name(&self) -> &'static str {
58 "In-Memory"
59 }
60
61 async fn usage_stats(&self) -> Vec<(&'static str, String)> {
62 let count = self.data.lock().await.len();
63 vec![("Stored Entries", count.to_string())]
64 }
65}
66
67#[cfg(test)]
68mod tests {
69 use super::*;
70
71 #[tokio::test]
72 async fn store_and_retrieve() {
73 let store = MemClientDataStore::new();
74 store.store("k1", "v1").await.unwrap();
75 assert_eq!(store.retrieve("k1").await.unwrap(), "v1");
76 }
77
78 #[tokio::test]
79 async fn retrieve_missing_key_errors() {
80 let store = MemClientDataStore::new();
81 let err = store.retrieve("nonexistent").await;
82 assert!(err.is_err());
83 }
84
85 #[tokio::test]
86 async fn purge_removes_all() {
87 let store = MemClientDataStore::new();
88 store.store("k1", "v1").await.unwrap();
89 store.store("k2", "v2").await.unwrap();
90 store.purge().await.unwrap();
91 assert!(store.retrieve("k1").await.is_err());
92 assert!(store.retrieve("k2").await.is_err());
93 }
94
95 #[tokio::test]
96 async fn upsert_semantics() {
97 let store = MemClientDataStore::new();
98 store.store("k1", "v1").await.unwrap();
99 store.store("k1", "v2").await.unwrap();
100 assert_eq!(store.retrieve("k1").await.unwrap(), "v2");
101 }
102}