From 3c19ea0eccc25f983a9558d7120884d16b4721c4 Mon Sep 17 00:00:00 2001 From: Vika Date: Wed, 5 May 2021 16:33:54 +0300 Subject: Removed the in-memory database, it's dragging me down --- src/database/memory.rs | 188 ------------------------------------------------- src/database/mod.rs | 15 ---- 2 files changed, 203 deletions(-) delete mode 100644 src/database/memory.rs (limited to 'src/database') diff --git a/src/database/memory.rs b/src/database/memory.rs deleted file mode 100644 index d1a69a2..0000000 --- a/src/database/memory.rs +++ /dev/null @@ -1,188 +0,0 @@ -use async_trait::async_trait; -use std::collections::HashMap; -use std::sync::Arc; -use async_std::sync::RwLock; -use futures_util::FutureExt; -use serde_json::json; - -use crate::database::{Storage, Result, StorageError, ErrorKind, MicropubChannel}; -use crate::indieauth::User; - -#[derive(Clone)] -pub struct MemoryStorage { - pub mapping: Arc>>, - pub channels: Arc>>> -} - -#[async_trait] -impl Storage for MemoryStorage { - async fn read_feed_with_limit<'a>(&self, url: &'a str, after: &'a Option, limit: usize, user: &'a Option) -> Result> { - todo!() - } - - async fn update_post<'a>(&self, url: &'a str, update: serde_json::Value) -> Result<()> { - let mut add_keys: HashMap = HashMap::new(); - let mut remove_keys: Vec = vec![]; - let mut remove_values: HashMap> = HashMap::new(); - - if let Some(delete) = update["delete"].as_array() { - remove_keys.extend(delete.iter().filter_map(|v| v.as_str()).map(|v| v.to_string())); - } else if let Some(delete) = update["delete"].as_object() { - for (k, v) in delete { - if let Some(v) = v.as_array() { - remove_values.entry(k.to_string()).or_default().extend(v.clone()); - } else { - return Err(StorageError::new(ErrorKind::BadRequest, "Malformed update object")); - } - } - } - if let Some(add) = update["add"].as_object() { - for (k, v) in add { - if v.is_array() { - add_keys.insert(k.to_string(), v.clone()); - } else { - return Err(StorageError::new(ErrorKind::BadRequest, "Malformed update object")); - } - } - } - if let Some(replace) = update["replace"].as_object() { - for (k, v) in replace { - remove_keys.push(k.to_string()); - add_keys.insert(k.to_string(), v.clone()); - } - } - let mut mapping = self.mapping.write().await; - if let Some(mut post) = mapping.get(url) { - if let Some(url) = post["see_other"].as_str() { - if let Some(new_post) = mapping.get(url) { - post = new_post - } else { - return Err(StorageError::new(ErrorKind::NotFound, "The post you have requested is not found in the database.")); - } - } - let mut post = post.clone(); - for k in remove_keys { - post["properties"].as_object_mut().unwrap().remove(&k); - } - for (k, v) in remove_values { - let k = &k; - let props; - if k == "children" { - props = &mut post; - } else { - props = &mut post["properties"]; - } - v.iter().for_each(|v| { - if let Some(vec) = props[k].as_array_mut() { - if let Some(index) = vec.iter().position(|w| w == v) { - vec.remove(index); - } - } - }); - } - for (k, v) in add_keys { - let props; - if k == "children" { - props = &mut post; - } else { - props = &mut post["properties"]; - } - let k = &k; - if let Some(prop) = props[k].as_array_mut() { - if k == "children" { - v.as_array().unwrap().iter().cloned().rev().for_each(|v| prop.insert(0, v)); - } else { - prop.extend(v.as_array().unwrap().iter().cloned()); - } - } else { - post["properties"][k] = v - } - } - mapping.insert(post["properties"]["uid"][0].as_str().unwrap().to_string(), post); - } else { - return Err(StorageError::new(ErrorKind::NotFound, "The designated post wasn't found in the database.")); - } - Ok(()) - } - - async fn delete_post<'a>(&self, url: &'a str) -> Result<()> { - self.mapping.write().await.remove(url); - Ok(()) - } - - async fn post_exists(&self, url: &str) -> Result { - return Ok(self.mapping.read().await.contains_key(url)) - } - - async fn get_post(&self, url: &str) ->Result> { - let mapping = self.mapping.read().await; - match mapping.get(url) { - Some(val) => { - if let Some(new_url) = val["see_other"].as_str() { - match mapping.get(new_url) { - Some(val) => Ok(Some(val.clone())), - None => { - drop(mapping); - self.mapping.write().await.remove(url); - Ok(None) - } - } - } else { - Ok(Some(val.clone())) - } - }, - _ => Ok(None) - } - } - - async fn get_channels(&self, user: &User) -> Result> { - match self.channels.read().await.get(&user.me.to_string()) { - Some(channels) => Ok(futures_util::future::join_all(channels.iter() - .map(|channel| self.get_post(channel) - .map(|result| result.unwrap()) - .map(|post: Option| { - if let Some(post) = post { - Some(MicropubChannel { - uid: post["properties"]["uid"][0].as_str().unwrap().to_string(), - name: post["properties"]["name"][0].as_str().unwrap().to_string() - }) - } else { None } - }) - ).collect::>()).await.into_iter().filter_map(|chan| chan).collect::>()), - None => Ok(vec![]) - } - - } - - async fn put_post<'a>(&self, post: &'a serde_json::Value) -> Result<()> { - let mapping = &mut self.mapping.write().await; - let key: &str; - match post["properties"]["uid"][0].as_str() { - Some(uid) => key = uid, - None => return Err(StorageError::new(ErrorKind::Other, "post doesn't have a UID")) - } - mapping.insert(key.to_string(), post.clone()); - if post["properties"]["url"].is_array() { - for url in post["properties"]["url"].as_array().unwrap().iter().map(|i| i.as_str().unwrap().to_string()) { - if &url != key { - mapping.insert(url, json!({"see_other": key})); - } - } - } - if post["type"].as_array().unwrap().iter().any(|i| i == "h-feed") { - // This is a feed. Add it to the channels array if it's not already there. - println!("{:#}", post); - self.channels.write().await.entry(post["properties"]["author"][0].as_str().unwrap().to_string()).or_insert(vec![]).push(key.to_string()) - } - Ok(()) - } -} - -impl MemoryStorage { - pub fn new() -> Self { - Self { - mapping: Arc::new(RwLock::new(HashMap::new())), - channels: Arc::new(RwLock::new(HashMap::new())) - } - } -} diff --git a/src/database/mod.rs b/src/database/mod.rs index 1a6aa84..d6b7dd6 100644 --- a/src/database/mod.rs +++ b/src/database/mod.rs @@ -7,10 +7,6 @@ mod redis; pub use crate::database::redis::RedisStorage; #[cfg(test)] pub use redis::tests::get_redis_instance; -#[cfg(test)] -mod memory; -#[cfg(test)] -pub(crate) use crate::database::memory::MemoryStorage; #[derive(Serialize, Deserialize, PartialEq, Debug)] pub struct MicropubChannel { @@ -224,17 +220,6 @@ mod tests { assert_eq!(chans[0], MicropubChannel { uid: "https://fireburn.ru/feeds/main".to_string(), name: "Main Page".to_string() }); } - #[async_std::test] - async fn test_memory_storage_basic_operations() { - let backend = super::MemoryStorage::new(); - test_backend_basic_operations(backend).await - } - #[async_std::test] - async fn test_memory_storage_channel_support() { - let backend = super::MemoryStorage::new(); - test_backend_get_channel_list(backend).await - } - #[async_std::test] async fn test_redis_storage_basic_operations() { let (tempdir, mut redis, uri) = get_redis_instance().await; -- cgit 1.4.1