quick_kv/clients/
memory.rs

1use std::fmt::Debug;
2use std::hash::Hash;
3
4use serde::de::DeserializeOwned;
5use serde::Serialize;
6
7use crate::clients::{BaseClient, ClientConfig};
8use crate::db::config::DatabaseConfiguration;
9use crate::db::runtime::{RunTime, RuntTimeType};
10use crate::db::Database;
11
12#[derive(Debug)]
13pub struct QuickMemoryClient<T>
14where
15    T: Serialize + DeserializeOwned + Debug + Eq + PartialEq + Hash + Send + Sync + Clone + 'static,
16{
17    db: Database<T>,
18}
19
20impl<T> BaseClient<T> for QuickMemoryClient<T>
21where
22    T: Serialize + DeserializeOwned + Debug + Eq + PartialEq + Hash + Send + Sync + Clone + 'static,
23{
24    fn new(config: ClientConfig) -> Self
25    {
26        let _config = DatabaseConfiguration::new(
27            config.path,
28            RunTime::new(RuntTimeType::Memory).into(),
29            config.log,
30            config.log_level,
31            config.default_ttl,
32        )
33        .unwrap();
34
35        let db = Database::new(_config).unwrap();
36
37        Self { db }
38    }
39
40    fn get(&mut self, key: &str) -> anyhow::Result<Option<T>>
41    {
42        match self.db.get(key.to_string()) {
43            Ok(value) => Ok(value),
44            Err(e) => Err(e),
45        }
46    }
47
48    fn set(&mut self, key: &str, value: T) -> anyhow::Result<()>
49    {
50        match self.db.set(key, value, None) {
51            Ok(_) => Ok(()),
52            Err(e) => Err(e),
53        }
54    }
55
56    fn update(&mut self, key: &str, value: T, upsert: Option<bool>) -> anyhow::Result<()>
57    {
58        match self.db.update(key, value, None, upsert) {
59            Ok(_) => Ok(()),
60            Err(e) => Err(e),
61        }
62    }
63
64    fn delete(&mut self, key: &str) -> anyhow::Result<()>
65    {
66        match self.db.delete(key) {
67            Ok(_) => Ok(()),
68            Err(e) => Err(e),
69        }
70    }
71
72    fn exists(&mut self, key: &str) -> anyhow::Result<bool>
73    {
74        match self.db.state.lock().unwrap().entries.contains_key(key) {
75            true => Ok(true),
76            false => Ok(false),
77        }
78    }
79
80    fn keys(&mut self) -> anyhow::Result<Option<Vec<String>>>
81    {
82        let keys = self.db.state.lock().unwrap().entries.keys().cloned().collect::<Vec<String>>();
83        if !keys.is_empty() {
84            Ok(Some(keys))
85        } else {
86            Ok(None)
87        }
88    }
89
90    fn values(&mut self) -> anyhow::Result<Option<Vec<T>>>
91    {
92        let values = self.db.state.lock().unwrap().entries.values().cloned().collect::<Vec<_>>();
93
94        if !values.is_empty() {
95            let v = values.into_iter().map(|entry| entry.data).collect::<Vec<T>>();
96            Ok(Some(v))
97        } else {
98            Ok(None)
99        }
100    }
101
102    fn len(&mut self) -> anyhow::Result<usize>
103    {
104        match self.db.state.lock().unwrap().entries.len() {
105            len if len > 0 => Ok(len),
106            _ => Ok(0),
107        }
108    }
109
110    fn purge(&mut self) -> anyhow::Result<()>
111    {
112        match self.db.purge() {
113            Ok(_) => Ok(()),
114            Err(e) => Err(e),
115        }
116    }
117
118    fn get_many(&mut self, keys: &[&str]) -> anyhow::Result<Option<Vec<T>>>
119    {
120        let mut values = Vec::new();
121
122        for key in keys {
123            if let Ok(Some(v)) = self.db.get(key.to_string()) {
124                values.push(v);
125            }
126        }
127
128        if !values.is_empty() {
129            Ok(Some(values))
130        } else {
131            Ok(None)
132        }
133    }
134
135    fn set_many(&mut self, keys: &[&str], values: &[T]) -> anyhow::Result<()>
136    {
137        for (key, value) in keys.iter().zip(values.iter()) {
138            self.db.set(key, value.clone(), None)?;
139        }
140
141        Ok(())
142    }
143
144    fn delete_many(&mut self, keys: &[&str]) -> anyhow::Result<()>
145    {
146        for key in keys {
147            self.db.delete(key)?;
148        }
149
150        Ok(())
151    }
152
153    fn update_many(&mut self, keys: &[&str], values: &[T], upsert: Option<bool>) -> anyhow::Result<()>
154    {
155        for (key, value) in keys.iter().zip(values.iter()) {
156            self.db.update(key, value.clone(), None, upsert)?;
157        }
158
159        Ok(())
160    }
161}
162
163#[cfg(test)]
164mod tests
165{
166    use tempfile::tempdir;
167
168    use super::*;
169    use crate::types::HashSet;
170
171    #[test]
172    fn test_quick_client_set_get()
173    {
174        let config = ClientConfig {
175            path: Some("test_db".to_string()),
176            log: None,
177            log_level: None,
178            default_ttl: None,
179        };
180        let mut client: QuickMemoryClient<String> = QuickMemoryClient::<String>::new(config);
181
182        let key = "test_key";
183        let value = "test_value".to_string();
184
185        client.set(key, value.clone()).unwrap();
186        let retrieved_value = client.get(key).unwrap().unwrap();
187
188        assert_eq!(retrieved_value, value);
189    }
190
191    #[test]
192    fn test_quick_client_delete()
193    {
194        let tmp_dir = tempdir().expect("Failed to create tempdir");
195        let tmp_file = tmp_dir.path().join("test.qkv").to_str().unwrap().to_string();
196
197        let config = ClientConfig {
198            path: Some(tmp_file),
199            log: None,
200            log_level: None,
201            default_ttl: None,
202        };
203        let mut client = QuickMemoryClient::<String>::new(config);
204
205        let key = "test_key";
206        let value = "test_value".to_string();
207
208        client.set(key, value.clone()).unwrap();
209        client.delete(key).unwrap();
210        let retrieved_value = client.get(key).unwrap();
211
212        assert!(retrieved_value.is_none());
213    }
214
215    #[test]
216    fn test_quick_client_set_many_get_many()
217    {
218        let tmp_dir = tempdir().expect("Failed to create tempdir");
219        let tmp_file = tmp_dir.path().join("test.qkv").to_str().unwrap().to_string();
220
221        let config = ClientConfig {
222            path: Some(tmp_file),
223            log: None,
224            log_level: None,
225            default_ttl: None,
226        };
227        let mut client = QuickMemoryClient::<String>::new(config);
228
229        let keys = vec!["key1", "key2", "key3"];
230        let values = vec!["value1", "value2", "value3"]
231            .iter()
232            .map(|&s| s.to_string())
233            .collect::<Vec<String>>();
234
235        client.set_many(&keys, &values).unwrap();
236        let retrieved_values = client.get_many(&keys).unwrap().unwrap();
237
238        assert_eq!(retrieved_values, values);
239    }
240
241    #[test]
242    fn test_quick_client_exists()
243    {
244        let tmp_dir = tempdir().expect("Failed to create tempdir");
245        let tmp_file = tmp_dir.path().join("test.qkv").to_str().unwrap().to_string();
246
247        let config = ClientConfig {
248            path: Some(tmp_file),
249            log: None,
250            log_level: None,
251            default_ttl: None,
252        };
253        let mut client = QuickMemoryClient::<String>::new(config);
254
255        let key = "test_key";
256        let value = "test_value".to_string();
257
258        // Key doesn't exist yet
259        assert_eq!(client.exists(key).unwrap(), false);
260
261        // Set the key
262        client.set(key, value.clone()).unwrap();
263
264        // Key should now exist
265        assert_eq!(client.exists(key).unwrap(), true);
266    }
267
268    #[test]
269    fn test_quick_client_keys()
270    {
271        let tmp_dir = tempdir().expect("Failed to create tempdir");
272        let tmp_file = tmp_dir.path().join("test.qkv").to_str().unwrap().to_string();
273
274        let config = ClientConfig {
275            path: Some(tmp_file),
276            log: None,
277            log_level: None,
278            default_ttl: None,
279        };
280        let mut client = QuickMemoryClient::<String>::new(config);
281
282        let keys = vec!["key1", "key2", "key3"];
283        let values = vec!["value1", "value2", "value3"]
284            .iter()
285            .map(|&s| s.to_string())
286            .collect::<Vec<String>>();
287
288        client.set_many(&keys, &values).unwrap();
289
290        let retrieved_keys = client.keys().unwrap().unwrap().into_iter().collect::<HashSet<_>>();
291        let expected_keys: HashSet<_> = keys.iter().map(|&s| s.to_string()).collect();
292
293        assert_eq!(retrieved_keys, expected_keys);
294    }
295
296    #[test]
297    fn test_quick_client_values()
298    {
299        let tmp_dir = tempdir().expect("Failed to create tempdir");
300        let tmp_file = tmp_dir.path().join("test.qkv").to_str().unwrap().to_string();
301
302        let config = ClientConfig {
303            path: Some(tmp_file),
304            log: None,
305            log_level: None,
306            default_ttl: None,
307        };
308        let mut client = QuickMemoryClient::<String>::new(config);
309
310        let keys = vec!["key1", "key2", "key3"];
311        let values = vec!["value1", "value2", "value3"]
312            .iter()
313            .map(|&s| s.to_string())
314            .collect::<Vec<String>>();
315
316        client.set_many(&keys, &values).unwrap();
317
318        let retrieved_values = client.values().unwrap().unwrap().into_iter().collect::<HashSet<_>>();
319        let expected_values: HashSet<_> = values.iter().map(|s| s.to_string()).collect();
320
321        assert_eq!(retrieved_values, expected_values);
322    }
323
324    #[test]
325    fn test_quick_client_len()
326    {
327        let tmp_dir = tempdir().expect("Failed to create tempdir");
328        let tmp_file = tmp_dir.path().join("test.qkv").to_str().unwrap().to_string();
329
330        let config = ClientConfig {
331            path: Some(tmp_file),
332            log: None,
333            log_level: None,
334            default_ttl: None,
335        };
336        let mut client = QuickMemoryClient::<String>::new(config);
337
338        let keys = vec!["key1", "key2", "key3"];
339        let values = vec!["value1", "value2", "value3"]
340            .iter()
341            .map(|&s| s.to_string())
342            .collect::<Vec<String>>();
343
344        client.set_many(&keys, &values).unwrap();
345
346        let length = client.len().unwrap();
347        assert_eq!(length, 3);
348    }
349
350    #[test]
351    fn test_quick_client_purge()
352    {
353        let tmp_dir = tempdir().expect("Failed to create tempdir");
354        let tmp_file = tmp_dir.path().join("test.qkv").to_str().unwrap().to_string();
355
356        let config = ClientConfig {
357            path: Some(tmp_file),
358            log: None,
359            log_level: None,
360            default_ttl: None,
361        };
362        let mut client = QuickMemoryClient::<String>::new(config);
363
364        let key = "test_key";
365        let value = "test_value".to_string();
366
367        client.set(key, value.clone()).unwrap();
368        client.purge().unwrap();
369
370        assert_eq!(client.len().unwrap(), 0);
371    }
372
373    #[test]
374    fn test_quick_client_update_many()
375    {
376        let tmp_dir = tempdir().expect("Failed to create tempdir");
377        let tmp_file = tmp_dir.path().join("test.qkv").to_str().unwrap().to_string();
378
379        let config = ClientConfig {
380            path: Some(tmp_file),
381            log: None,
382            log_level: None,
383            default_ttl: None,
384        };
385        let mut client = QuickMemoryClient::<String>::new(config);
386
387        let keys = vec!["key1", "key2", "key3"];
388        let values = vec!["value1", "value2", "value3"]
389            .iter()
390            .map(|&s| s.to_string())
391            .collect::<Vec<String>>();
392
393        client.set_many(&keys, &values).unwrap();
394
395        let new_values = vec!["new_value1", "new_value2", "new_value3"]
396            .iter()
397            .map(|&s| s.to_string())
398            .collect::<Vec<String>>();
399
400        client.update_many(&keys, &new_values, None).unwrap();
401
402        let retrieved_values = client.values().unwrap().unwrap();
403
404        // Sort the retrieved and new values for comparison
405        let mut sorted_retrieved_values = retrieved_values.clone();
406        let mut sorted_new_values = new_values.clone();
407        sorted_retrieved_values.sort();
408        sorted_new_values.sort();
409
410        assert_eq!(sorted_retrieved_values, sorted_new_values);
411    }
412
413    #[test]
414    fn test_quick_client_delete_many()
415    {
416        let tmp_dir = tempdir().expect("Failed to create tempdir");
417        let tmp_file = tmp_dir.path().join("test.qkv").to_str().unwrap().to_string();
418
419        let config = ClientConfig {
420            path: Some(tmp_file),
421            log: None,
422            log_level: None,
423            default_ttl: None,
424        };
425        let mut client = QuickMemoryClient::<String>::new(config);
426
427        let keys = vec!["key1", "key2", "key3"];
428        let values = vec!["value1", "value2", "value3"]
429            .iter()
430            .map(|&s| s.to_string())
431            .collect::<Vec<String>>();
432
433        client.set_many(&keys, &values).unwrap();
434
435        let keys_to_delete = vec!["key1", "key2"];
436
437        client.delete_many(&keys_to_delete).unwrap();
438
439        let remaining_keys = client.keys().unwrap().unwrap();
440        assert_eq!(remaining_keys, vec!["key3"]);
441    }
442}