1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63
use super::{TokenStore, TokenStoreInternalError}; use async_trait::async_trait; use houseflow_types::token::{Token, TokenID}; use redis::{aio::Connection, AsyncCommands, Client}; use std::sync::Arc; use tokio::sync::Mutex; pub use redis::RedisError as Error; impl TokenStoreInternalError for Error {} #[derive(Clone)] pub struct RedisTokenStore { connection: Arc<Mutex<Connection>>, } impl RedisTokenStore { pub async fn new() -> Result<Self, Error> { let client = Client::open("redis://127.0.0.1")?; let connection = client.get_tokio_connection().await?; Ok(Self { connection: Arc::new(Mutex::new(connection)), }) } } #[async_trait] impl TokenStore for RedisTokenStore { async fn exists(&self, id: &TokenID) -> Result<bool, super::Error> { Ok(self .connection .lock() .await .exists::<_, bool>(id.to_string()) .await?) } async fn get(&self, id: &TokenID) -> Result<Option<Token>, super::Error> { use std::str::FromStr; let token: Option<String> = self.connection.lock().await.get(id.to_string()).await?; let token: Option<Token> = match token.map(|token| Token::from_str(token.as_str())) { Some(token) => Some(token?), None => None, }; Ok(token) } async fn remove(&self, id: &TokenID) -> Result<bool, super::Error> { let removed: bool = self.connection.lock().await.del(id.to_string()).await?; Ok(removed) } async fn add(&self, token: &Token) -> Result<(), super::Error> { self.connection .lock() .await .set(token.id().to_string(), token.to_string()) .await?; Ok(()) } }