quick_kv/clients/
normal.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, Clone)]
13pub struct QuickClient<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 QuickClient<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            Some(RunTime::new(RuntTimeType::Disk)),
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 tmp_dir = tempdir().expect("Failed to create tempdir");
175        let tmp_file = tmp_dir.path().join("test.qkv").to_str().unwrap().to_string();
176
177        let config = ClientConfig {
178            path: Some(tmp_file),
179            log: None,
180            log_level: None,
181            default_ttl: None,
182        };
183        let mut client = QuickClient::<String>::new(config);
184
185        let key = "test_key";
186        let value = "test_value".to_string();
187
188        client.set(key, value.clone()).unwrap();
189        let retrieved_value = client.get(key).unwrap().unwrap();
190
191        assert_eq!(retrieved_value, value);
192    }
193
194    #[test]
195    fn test_quick_client_delete()
196    {
197        let tmp_dir = tempdir().expect("Failed to create tempdir");
198        let tmp_file = tmp_dir.path().join("test.qkv").to_str().unwrap().to_string();
199
200        let config = ClientConfig {
201            path: Some(tmp_file),
202            log: None,
203            log_level: None,
204            default_ttl: None,
205        };
206        let mut client = QuickClient::<String>::new(config);
207
208        let key = "test_key";
209        let value = "test_value".to_string();
210
211        client.set(key, value.clone()).unwrap();
212        client.delete(key).unwrap();
213        let retrieved_value = client.get(key).unwrap();
214
215        assert!(retrieved_value.is_none());
216    }
217
218    #[test]
219    fn test_quick_client_set_many_get_many()
220    {
221        let tmp_dir = tempdir().expect("Failed to create tempdir");
222        let tmp_file = tmp_dir.path().join("test.qkv").to_str().unwrap().to_string();
223
224        let config = ClientConfig {
225            path: Some(tmp_file),
226            log: None,
227            log_level: None,
228            default_ttl: None,
229        };
230        let mut client = QuickClient::<String>::new(config);
231
232        let keys = vec!["key1", "key2", "key3"];
233        let values = vec!["value1", "value2", "value3"]
234            .iter()
235            .map(|&s| s.to_string())
236            .collect::<Vec<String>>();
237
238        client.set_many(&keys, &values).unwrap();
239        let retrieved_values = client.get_many(&keys).unwrap().unwrap();
240
241        assert_eq!(retrieved_values, values);
242    }
243
244    #[test]
245    fn test_quick_client_exists()
246    {
247        let tmp_dir = tempdir().expect("Failed to create tempdir");
248        let tmp_file = tmp_dir.path().join("test.qkv").to_str().unwrap().to_string();
249
250        let config = ClientConfig {
251            path: Some(tmp_file),
252            log: None,
253            log_level: None,
254            default_ttl: None,
255        };
256        let mut client = QuickClient::<String>::new(config);
257
258        let key = "test_key";
259        let value = "test_value".to_string();
260
261        // Key doesn't exist yet
262        assert_eq!(client.exists(key).unwrap(), false);
263
264        // Set the key
265        client.set(key, value.clone()).unwrap();
266
267        // Key should now exist
268        assert_eq!(client.exists(key).unwrap(), true);
269    }
270
271    #[test]
272    fn test_quick_client_keys()
273    {
274        let tmp_dir = tempdir().expect("Failed to create tempdir");
275        let tmp_file = tmp_dir.path().join("test.qkv").to_str().unwrap().to_string();
276
277        let config = ClientConfig {
278            path: Some(tmp_file),
279            log: None,
280            log_level: None,
281            default_ttl: None,
282        };
283        let mut client = QuickClient::<String>::new(config);
284
285        let keys = vec!["key1", "key2", "key3"];
286        let values = vec!["value1", "value2", "value3"]
287            .iter()
288            .map(|&s| s.to_string())
289            .collect::<Vec<String>>();
290
291        client.set_many(&keys, &values).unwrap();
292
293        let retrieved_keys = client.keys().unwrap().unwrap().into_iter().collect::<HashSet<_>>();
294        let expected_keys: HashSet<_> = keys.iter().map(|&s| s.to_string()).collect();
295
296        assert_eq!(retrieved_keys, expected_keys);
297    }
298
299    #[test]
300    fn test_quick_client_values()
301    {
302        let tmp_dir = tempdir().expect("Failed to create tempdir");
303        let tmp_file = tmp_dir.path().join("test.qkv").to_str().unwrap().to_string();
304
305        let config = ClientConfig {
306            path: Some(tmp_file),
307            log: None,
308            log_level: None,
309            default_ttl: None,
310        };
311        let mut client = QuickClient::<String>::new(config);
312
313        let keys = vec!["key1", "key2", "key3"];
314        let values = vec!["value1", "value2", "value3"]
315            .iter()
316            .map(|&s| s.to_string())
317            .collect::<Vec<String>>();
318
319        client.set_many(&keys, &values).unwrap();
320
321        let retrieved_values = client.values().unwrap().unwrap().into_iter().collect::<HashSet<_>>();
322        let expected_values: HashSet<_> = values.iter().map(|s| s.to_string()).collect();
323
324        assert_eq!(retrieved_values, expected_values);
325    }
326
327    #[test]
328    fn test_quick_client_len()
329    {
330        let tmp_dir = tempdir().expect("Failed to create tempdir");
331        let tmp_file = tmp_dir.path().join("test.qkv").to_str().unwrap().to_string();
332
333        let config = ClientConfig {
334            path: Some(tmp_file),
335            log: None,
336            log_level: None,
337            default_ttl: None,
338        };
339        let mut client = QuickClient::<String>::new(config);
340
341        let keys = vec!["key1", "key2", "key3"];
342        let values = vec!["value1", "value2", "value3"]
343            .iter()
344            .map(|&s| s.to_string())
345            .collect::<Vec<String>>();
346
347        client.set_many(&keys, &values).unwrap();
348
349        let length = client.len().unwrap();
350        assert_eq!(length, 3);
351    }
352
353    #[test]
354    fn test_quick_client_purge()
355    {
356        let tmp_dir = tempdir().expect("Failed to create tempdir");
357        let tmp_file = tmp_dir.path().join("test.qkv").to_str().unwrap().to_string();
358
359        let config = ClientConfig {
360            path: Some(tmp_file),
361            log: None,
362            log_level: None,
363            default_ttl: None,
364        };
365        let mut client = QuickClient::<String>::new(config);
366
367        let key = "test_key";
368        let value = "test_value".to_string();
369
370        client.set(key, value.clone()).unwrap();
371        client.purge().unwrap();
372
373        assert_eq!(client.len().unwrap(), 0);
374    }
375
376    #[test]
377    fn test_quick_client_update_many()
378    {
379        let config = ClientConfig {
380            path: Some("test_db".to_string()),
381            log: None,
382            log_level: None,
383            default_ttl: None,
384        };
385
386        let mut client = QuickClient::<String>::new(config);
387
388        let keys = vec!["key1", "key2", "key3"];
389        let values = vec!["value1", "value2", "value3"]
390            .iter()
391            .map(|&s| s.to_string())
392            .collect::<Vec<String>>();
393
394        client.set_many(&keys, &values).unwrap();
395
396        let new_values = vec!["new_value1", "new_value2", "new_value3"]
397            .iter()
398            .map(|&s| s.to_string())
399            .collect::<Vec<String>>();
400
401        client.update_many(&keys, &new_values, None).unwrap();
402
403        let retrieved_values = client.values().unwrap().unwrap();
404
405        // Sort the retrieved and new values for comparison
406        let mut sorted_retrieved_values = retrieved_values.clone();
407        let mut sorted_new_values = new_values.clone();
408        sorted_retrieved_values.sort();
409        sorted_new_values.sort();
410
411        assert_eq!(sorted_retrieved_values, sorted_new_values);
412    }
413
414    #[test]
415    fn test_quick_client_delete_many()
416    {
417        let tmp_dir = tempdir().expect("Failed to create tempdir");
418        let tmp_file = tmp_dir.path().join("test.qkv").to_str().unwrap().to_string();
419
420        let config = ClientConfig {
421            path: Some(tmp_file),
422            log: None,
423            log_level: None,
424            default_ttl: None,
425        };
426        let mut client = QuickClient::<String>::new(config);
427
428        let keys = vec!["key1", "key2", "key3"];
429        let values = vec!["value1", "value2", "value3"]
430            .iter()
431            .map(|&s| s.to_string())
432            .collect::<Vec<String>>();
433
434        client.set_many(&keys, &values).unwrap();
435
436        let keys_to_delete = vec!["key1", "key2"];
437
438        client.delete_many(&keys_to_delete).unwrap();
439
440        let remaining_keys = client.keys().unwrap().unwrap();
441        assert_eq!(remaining_keys, vec!["key3"]);
442    }
443}