diff options
author | Vika <vika@fireburn.ru> | 2021-05-05 16:33:54 +0300 |
---|---|---|
committer | Vika <vika@fireburn.ru> | 2021-05-05 16:33:54 +0300 |
commit | 3c19ea0eccc25f983a9558d7120884d16b4721c4 (patch) | |
tree | 2b4e94268ae715997cd9f2c6bc4a01143d1bfb7a /src | |
parent | a5963bbdb7464709232486bfe46ccbea3366b226 (diff) | |
download | kittybox-3c19ea0eccc25f983a9558d7120884d16b4721c4.tar.zst |
Removed the in-memory database, it's dragging me down
Diffstat (limited to 'src')
-rw-r--r-- | src/database/memory.rs | 188 | ||||
-rw-r--r-- | src/database/mod.rs | 15 | ||||
-rw-r--r-- | src/lib.rs | 11 |
3 files changed, 0 insertions, 214 deletions
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<RwLock<HashMap<String, serde_json::Value>>>, - pub channels: Arc<RwLock<HashMap<String, Vec<String>>>> -} - -#[async_trait] -impl Storage for MemoryStorage { - async fn read_feed_with_limit<'a>(&self, url: &'a str, after: &'a Option<String>, limit: usize, user: &'a Option<String>) -> Result<Option<serde_json::Value>> { - todo!() - } - - async fn update_post<'a>(&self, url: &'a str, update: serde_json::Value) -> Result<()> { - let mut add_keys: HashMap<String, serde_json::Value> = HashMap::new(); - let mut remove_keys: Vec<String> = vec![]; - let mut remove_values: HashMap<String, Vec<serde_json::Value>> = 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<bool> { - return Ok(self.mapping.read().await.contains_key(url)) - } - - async fn get_post(&self, url: &str) ->Result<Option<serde_json::Value>> { - 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<Vec<MicropubChannel>> { - 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<serde_json::Value>| { - 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::<Vec<_>>()).await.into_iter().filter_map(|chan| chan).collect::<Vec<_>>()), - 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 { @@ -225,17 +221,6 @@ mod tests { } #[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; let backend = super::RedisStorage::new(uri).await.unwrap(); diff --git a/src/lib.rs b/src/lib.rs index 6a0a1cc..2fe87f4 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -82,17 +82,6 @@ pub async fn get_app_with_redis(token_endpoint: surf::Url, redis_uri: String, me } #[cfg(test)] -pub async fn get_app_with_memory_for_testing(token_endpoint: surf::Url) -> (database::MemoryStorage, App<database::MemoryStorage>) { - let database = database::MemoryStorage::new(); - let app = tide::with_state(ApplicationState { - token_endpoint, media_endpoint: None, - storage: database.clone(), - http_client: surf::Client::new(), - }); - - return (database, equip_app(app)) -} -#[cfg(test)] pub async fn get_app_with_test_redis(token_endpoint: surf::Url) -> (tempdir::TempDir, std::process::Child, database::RedisStorage, App<database::RedisStorage>) { let (tempdir, child, uri) = crate::database::get_redis_instance().await; let backend = database::RedisStorage::new(uri).await.unwrap(); |