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 assert_eq!(client.exists(key).unwrap(), false);
263
264 client.set(key, value.clone()).unwrap();
266
267 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 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}