1use crate::utils::CaseInsensitiveStr;
2use crate::{Thing, Uuid};
3use async_trait::async_trait;
4use std::cell::RefCell;
5use std::collections::hash_map::Entry;
6use std::collections::HashMap;
7use std::rc::Rc;
8
9#[derive(Default)]
10pub struct NullDataStore;
11
12#[cfg_attr(test, derive(Debug, PartialEq))]
13#[derive(Clone, Default)]
14pub struct MemoryDataStore {
15 pub things: Rc<RefCell<HashMap<Uuid, Thing>>>,
16 pub key_values: Rc<RefCell<HashMap<String, String>>>,
17}
18
19#[async_trait(?Send)]
20impl DataStore for NullDataStore {
21 async fn health_check(&self) -> Result<(), ()> {
22 Err(())
23 }
24
25 async fn delete_thing_by_uuid(&mut self, _uuid: &Uuid) -> Result<(), ()> {
26 Err(())
27 }
28
29 async fn edit_thing(&mut self, _thing: &Thing) -> Result<(), ()> {
30 Err(())
31 }
32
33 async fn get_all_the_things(&self) -> Result<Vec<Thing>, ()> {
34 Err(())
35 }
36
37 async fn get_thing_by_uuid(&self, _uuid: &Uuid) -> Result<Option<Thing>, ()> {
38 Err(())
39 }
40
41 async fn get_thing_by_name(&self, _name: &str) -> Result<Option<Thing>, ()> {
42 Err(())
43 }
44
45 async fn get_things_by_name_start(
46 &self,
47 _name: &str,
48 _limit: Option<usize>,
49 ) -> Result<Vec<Thing>, ()> {
50 Err(())
51 }
52
53 async fn save_thing(&mut self, _thing: &Thing) -> Result<(), ()> {
54 Err(())
55 }
56
57 async fn set_value(&mut self, _key: &str, _value: &str) -> Result<(), ()> {
58 Err(())
59 }
60
61 async fn get_value(&self, _key: &str) -> Result<Option<String>, ()> {
62 Err(())
63 }
64
65 async fn delete_value(&mut self, _key: &str) -> Result<(), ()> {
66 Err(())
67 }
68}
69
70impl MemoryDataStore {
71 pub fn snapshot(&self) -> (HashMap<Uuid, Thing>, HashMap<String, String>) {
72 (
73 self.things.borrow().clone(),
74 self.key_values.borrow().clone(),
75 )
76 }
77}
78
79#[async_trait(?Send)]
80impl DataStore for MemoryDataStore {
81 async fn health_check(&self) -> Result<(), ()> {
82 Ok(())
83 }
84
85 async fn delete_thing_by_uuid(&mut self, uuid: &Uuid) -> Result<(), ()> {
86 self.things.borrow_mut().remove(uuid).map(|_| ()).ok_or(())
87 }
88
89 async fn edit_thing(&mut self, thing: &Thing) -> Result<(), ()> {
90 self.things
91 .borrow_mut()
92 .entry(thing.uuid)
93 .and_modify(|t| *t = thing.clone())
94 .or_insert_with(|| thing.clone());
95 Ok(())
96 }
97
98 async fn get_all_the_things(&self) -> Result<Vec<Thing>, ()> {
99 Ok(self.things.borrow().values().cloned().collect())
100 }
101
102 async fn get_thing_by_uuid(&self, uuid: &Uuid) -> Result<Option<Thing>, ()> {
103 Ok(self.things.borrow().get(uuid).cloned())
104 }
105
106 async fn get_thing_by_name(&self, name: &str) -> Result<Option<Thing>, ()> {
107 Ok(self
108 .things
109 .borrow()
110 .values()
111 .find(|thing| thing.name().value().is_some_and(|s| s.eq_ci(name)))
112 .cloned())
113 }
114
115 async fn get_things_by_name_start(
116 &self,
117 name: &str,
118 limit: Option<usize>,
119 ) -> Result<Vec<Thing>, ()> {
120 Ok(self
121 .things
122 .borrow()
123 .values()
124 .filter(|thing| thing.name().value().is_some_and(|s| s.starts_with_ci(name)))
125 .take(limit.unwrap_or(usize::MAX))
126 .cloned()
127 .collect())
128 }
129
130 async fn save_thing(&mut self, thing: &Thing) -> Result<(), ()> {
131 let mut things = self.things.borrow_mut();
132
133 if let Entry::Vacant(e) = things.entry(thing.uuid) {
134 e.insert(thing.clone());
135 Ok(())
136 } else {
137 Err(())
138 }
139 }
140
141 async fn set_value(&mut self, key: &str, value: &str) -> Result<(), ()> {
142 let mut key_values = self.key_values.borrow_mut();
143 key_values.insert(key.to_string(), value.to_string());
144 Ok(())
145 }
146
147 async fn get_value(&self, key: &str) -> Result<Option<String>, ()> {
148 let key_values = self.key_values.borrow();
149 Ok(key_values.get(key).cloned())
150 }
151
152 async fn delete_value(&mut self, key: &str) -> Result<(), ()> {
153 let mut key_values = self.key_values.borrow_mut();
154 key_values.remove(key);
155 Ok(())
156 }
157}
158
159#[async_trait(?Send)]
160pub trait DataStore {
161 async fn health_check(&self) -> Result<(), ()>;
162
163 async fn delete_thing_by_uuid(&mut self, uuid: &Uuid) -> Result<(), ()>;
164
165 async fn edit_thing(&mut self, thing: &Thing) -> Result<(), ()>;
166
167 async fn get_all_the_things(&self) -> Result<Vec<Thing>, ()>;
168
169 async fn get_thing_by_uuid(&self, uuid: &Uuid) -> Result<Option<Thing>, ()>;
170
171 async fn get_thing_by_name(&self, name: &str) -> Result<Option<Thing>, ()>;
172
173 async fn get_things_by_name_start(
174 &self,
175 name: &str,
176 limit: Option<usize>,
177 ) -> Result<Vec<Thing>, ()>;
178
179 async fn save_thing(&mut self, thing: &Thing) -> Result<(), ()>;
180
181 async fn set_value(&mut self, key: &str, value: &str) -> Result<(), ()>;
182
183 async fn get_value(&self, key: &str) -> Result<Option<String>, ()>;
184
185 async fn delete_value(&mut self, key: &str) -> Result<(), ()>;
186}
187
188#[cfg(test)]
189mod test {
190 use super::*;
191 use crate::test_utils as test;
192
193 #[tokio::test]
194 async fn memory_delete_thing_by_uuid_test() {
195 let mut ds = test::data_store::memory::with_test_data();
196 let len = ds.things.borrow().len();
197
198 assert_eq!(
199 Err(()),
200 ds.delete_thing_by_uuid(&test::thing::ODYSSEUS).await
201 );
202 assert_eq!(len, ds.things.borrow().len());
203 assert_eq!(
204 Ok(()),
205 ds.delete_thing_by_uuid(&test::thing::PENELOPE).await
206 );
207 assert_eq!(len - 1, ds.things.borrow().len());
208 }
209
210 #[tokio::test]
211 async fn memory_get_thing_by_uuid_test() {
212 let ds = test::data_store::memory::with_test_data();
213
214 assert_eq!(Ok(None), ds.get_thing_by_uuid(&test::thing::ODYSSEUS).await);
215 assert_eq!(
216 Ok(Some(test::thing::penelope())),
217 ds.get_thing_by_uuid(&test::thing::PENELOPE).await,
218 );
219 }
220
221 #[tokio::test]
222 async fn memory_get_thing_by_name_test() {
223 let ds = test::data_store::memory::with_test_data();
224
225 assert_eq!(Ok(None), ds.get_thing_by_name("odysseus").await);
226 assert_eq!(
227 Ok(Some(test::thing::penelope())),
228 ds.get_thing_by_name("penelope").await,
229 );
230 }
231
232 #[tokio::test]
233 async fn memory_get_things_by_name_start_test() {
234 let ds = test::data_store::memory::with_test_data();
235
236 let mut results = ds.get_things_by_name_start("p", None).await.unwrap();
237 results.sort_by_key(|thing| thing.uuid);
238 assert_eq!(
239 vec![test::thing::phoenicia(), test::thing::penelope()],
240 results,
241 );
242
243 assert_eq!(
244 1,
245 ds.get_things_by_name_start("p", Some(1))
246 .await
247 .unwrap()
248 .len(),
249 );
250 }
251
252 #[tokio::test]
253 async fn memory_edit_thing_test() {
254 let mut ds = test::data_store::memory();
255
256 let odysseus = test::thing::odysseus();
257 let nobody = test::npc().name("Nobody").build_thing(test::npc::ODYSSEUS);
258
259 assert_eq!(Ok(()), ds.edit_thing(&odysseus).await);
260 assert_eq!(1, ds.things.borrow().len());
261 assert_eq!(Ok(()), ds.edit_thing(&nobody).await);
262 assert_eq!(1, ds.things.borrow().len());
263 assert_eq!(
264 "Nobody",
265 ds.things
266 .borrow()
267 .get(&test::npc::ODYSSEUS)
268 .unwrap()
269 .name()
270 .to_string(),
271 );
272 }
273
274 #[tokio::test]
275 async fn memory_get_all_the_things_test() {
276 let ds =
277 test::data_store::memory::with([test::thing::odysseus(), test::thing::penelope()], []);
278
279 let all_the_things = ds.get_all_the_things().await.unwrap();
280 assert_eq!(2, all_the_things.len(), "{all_the_things:?}");
281 }
282
283 #[tokio::test]
284 async fn memory_save_thing_test() {
285 let mut ds = test::data_store::memory();
286
287 assert_eq!(Ok(()), ds.save_thing(&test::thing::odysseus()).await);
288 assert_eq!(
289 Err(()),
290 ds.save_thing(&test::npc().build_thing(test::thing::ODYSSEUS))
291 .await,
292 );
293
294 assert_eq!(Ok(1), ds.get_all_the_things().await.map(|v| v.len()));
295 }
296
297 #[tokio::test]
298 async fn memory_key_value_test() {
299 let mut ds = test::data_store::memory();
300
301 assert_eq!(Ok(()), ds.set_value("somekey", "abc").await);
302 assert_eq!(Ok(()), ds.set_value("otherkey", "def").await);
303 assert_eq!(Ok(()), ds.set_value("somekey", "xyz").await);
304 assert_eq!(Ok(None), ds.get_value("notakey").await);
305 assert_eq!(Ok(Some("xyz".to_string())), ds.get_value("somekey").await);
306 assert_eq!(Ok(()), ds.delete_value("somekey").await);
307 assert_eq!(Ok(None), ds.get_value("somekey").await);
308 }
309
310 #[tokio::test]
311 async fn memory_clone_test() {
312 let mut ds1 = test::data_store::memory();
313 let ds2 = ds1.clone();
314
315 assert_eq!(Ok(()), ds1.set_value("somekey", "abc").await);
316 assert_eq!(Ok(Some("abc".to_string())), ds2.get_value("somekey").await);
317
318 assert_eq!(Ok(()), ds1.save_thing(&test::thing::odysseus()).await);
319 assert_eq!(
320 Ok(Some(test::thing::odysseus())),
321 ds2.get_thing_by_uuid(&test::thing::ODYSSEUS).await,
322 );
323 }
324}