use fred::interfaces::KeysInterface; use fred::{clients::Pool, prelude::*}; use sqlx::PgPool; pub type AppState = std::sync::Arc>; pub struct AppInternalState { pub database: sqlx::postgres::PgPool, pub cache: Cache, } pub struct Cache { pub inmem: Pool, } impl AppInternalState { pub fn new(database: PgPool, cache: Pool) -> Self { AppInternalState { database, cache: Cache { inmem: cache }, } } } impl Cache { pub async fn get(&mut self, key: String) -> Result, Box> where T: for<'de> serde::Deserialize<'de>, { self.is_connected()?; let value: Option = self.inmem.get(&key).await?; match value { Some(json_str) => match serde_json::from_str::(&json_str) { Ok(deserialized) => Ok(Some(deserialized)), Err(_) => Ok(None), }, None => Ok(None), } } pub async fn set( &mut self, key: String, contents: &T, expiration: Option, set_opts: Option, get: bool, ) -> Result<(), Box> where T: for<'de> serde::Deserialize<'de> + serde::Serialize, { self.is_connected()?; let json_string = match serde_json::to_string::(contents) { Ok(s) => s, Err(_) => { return Err(Box::new(std::io::Error::new( std::io::ErrorKind::Other, "Unable to deserialize contents passed to cache".to_string(), ))) } }; Ok(self .inmem .set(key, json_string, expiration, set_opts, get) .await?) } pub async fn del(&mut self, key: String) -> Result<(), Box> { Ok(self.inmem.del(key).await?) } fn is_connected(&mut self) -> Result<(), Box> { match self.inmem.is_connected() { true => Ok(()), false => Err(Box::new(std::io::Error::new( std::io::ErrorKind::Other, "Not connected to cache".to_string(), ))), } } }