From 46bb4274caa3c48f1560fc6efe724c358cf13173 Mon Sep 17 00:00:00 2001 From: Brandon Thomas Date: Sun, 12 Mar 2023 03:00:47 -0400 Subject: [PATCH] work in progress session caching (redis) --- Cargo.lock | 1 + .../get_user_session_by_token_light.rs | 2 + crates/service/plugins/users/Cargo.toml | 1 + .../users/src/utils/session_checker.rs | 59 +++++++++++++++++++ .../endpoints/tts/get_tts_model.rs | 11 ++-- 5 files changed, 68 insertions(+), 6 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ac75cba236..ef80eca6fe 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -7758,6 +7758,7 @@ dependencies = [ "md-5", "once_cell", "r2d2_redis", + "redis_caching", "regex", "reusable_types", "serde", diff --git a/crates/lib/database_queries/src/queries/users/user_sessions/get_user_session_by_token_light.rs b/crates/lib/database_queries/src/queries/users/user_sessions/get_user_session_by_token_light.rs index 92ddde72c3..61cb18c558 100644 --- a/crates/lib/database_queries/src/queries/users/user_sessions/get_user_session_by_token_light.rs +++ b/crates/lib/database_queries/src/queries/users/user_sessions/get_user_session_by_token_light.rs @@ -8,10 +8,12 @@ use log::warn; use sqlx::MySql; use sqlx::pool::PoolConnection; +#[derive(Clone, Serialize, Deserialize)] pub struct SessionRecord { pub session_token: String, pub user_token: String, } + pub async fn get_user_session_by_token_light( mysql_connection: &mut PoolConnection, session_token: &str, diff --git a/crates/service/plugins/users/Cargo.toml b/crates/service/plugins/users/Cargo.toml index 299063e3f7..9405faf7e8 100644 --- a/crates/service/plugins/users/Cargo.toml +++ b/crates/service/plugins/users/Cargo.toml @@ -19,6 +19,7 @@ container_common = { path = "../../../lib/container_common" } database_queries = { path = "../../../lib/database_queries" } enums = { path = "../../../_types/enums" } http_server_common = { path = "../../../lib/http_server_common" } +redis_caching = { path = "../../../lib/caching/redis_caching" } reusable_types = { path = "../../../_types/reusable_types" } tokens = { path = "../../../_types/tokens" } user_input_common = { path = "../../../lib/user_input_common" } diff --git a/crates/service/plugins/users/src/utils/session_checker.rs b/crates/service/plugins/users/src/utils/session_checker.rs index 1f5dc95717..4118f38e84 100644 --- a/crates/service/plugins/users/src/utils/session_checker.rs +++ b/crates/service/plugins/users/src/utils/session_checker.rs @@ -4,18 +4,21 @@ #![forbid(unused_variables)] use actix_web::HttpRequest; +use log::warn; use container_common::anyhow_result::AnyhowResult; use crate::utils::session_cookie_manager::SessionCookieManager; use crate::utils::user_session_extended::{UserSessionExtended, UserSessionPreferences, UserSessionPremiumPlanInfo, UserSessionRoleAndPermissions, UserSessionSubscriptionPlan, UserSessionUserDetails}; use database_queries::queries::users::user_sessions::get_user_session_by_token::{get_user_session_by_token, SessionUserRecord}; use database_queries::queries::users::user_sessions::get_user_session_by_token_light::{get_user_session_by_token_light, SessionRecord}; use database_queries::queries::users::user_subscriptions::list_active_user_subscriptions::list_active_user_subscriptions; +use redis_caching::redis_ttl_cache::{RedisTtlCache, RedisTtlCacheConnection}; use sqlx::pool::PoolConnection; use sqlx::{MySqlPool, MySql}; #[derive(Clone)] pub struct SessionChecker { cookie_manager: SessionCookieManager, + maybe_redis_ttl_cache: Option, } impl SessionChecker { @@ -23,9 +26,20 @@ impl SessionChecker { pub fn new(cookie_manager: &SessionCookieManager) -> Self { Self { cookie_manager: cookie_manager.clone(), + maybe_redis_ttl_cache: None, } } + pub fn new_with_cache(cookie_manager: &SessionCookieManager, redis_ttl_cache: RedisTtlCache) -> Self { + Self { + cookie_manager: cookie_manager.clone(), + maybe_redis_ttl_cache: Some(redis_ttl_cache), + } + } + + + // ==================== SessionRecord ==================== + #[deprecated = "Use the PoolConnection method instead of the MySqlPool one."] pub async fn maybe_get_session_light( &self, @@ -51,6 +65,36 @@ impl SessionChecker { get_user_session_by_token_light(mysql_connection, &session_token).await } + async fn maybe_get_session_light_from_connection_cached( + &self, + request: &HttpRequest, + mysql_connection: &mut PoolConnection, + ) -> AnyhowResult> + { + let session_token = match self.cookie_manager.decode_session_token_from_request(request)? { + None => return Ok(None), + Some(session_token) => session_token, + }; + + let maybe_redis_cache = self.maybe_get_redis_cache_connection(); + + match maybe_redis_cache { + None => { + get_user_session_by_token_light(mysql_connection, &session_token).await + } + Some(mut redis_ttl_cache) => { + let cache_key = "todo"; + redis_ttl_cache.lazy_load_if_not_cached(cache_key, move || { + //let session_token2 = session_token.to_string(); // TODO FIXME + get_user_session_by_token_light(mysql_connection, "") + }).await + } + } + } + + + // ==================== SessionUserRecord ==================== + //#[deprecated = "Use the PoolConnection method instead of the MySqlPool one."] pub async fn maybe_get_user_session( &self, @@ -76,6 +120,9 @@ impl SessionChecker { get_user_session_by_token(mysql_connection, &session_token).await } + + // ==================== UserSessionExtended ==================== + //#[deprecated = "Use the PoolConnection method instead of the MySqlPool one."] pub async fn maybe_get_user_session_extended( &self, @@ -164,5 +211,17 @@ impl SessionChecker { }, })) } + + fn maybe_get_redis_cache_connection(&self) -> Option { + self.maybe_redis_ttl_cache + .as_ref() + .map(|redis_ttl_cache| redis_ttl_cache.get_connection() + .map_err(|err| { + warn!("redis cache failure: {:?}", err); // NB: We'll fail open if Redis cache fails + err + }) + .ok()) + .flatten() + } } diff --git a/crates/service/web/storyteller_web/src/http_server/endpoints/tts/get_tts_model.rs b/crates/service/web/storyteller_web/src/http_server/endpoints/tts/get_tts_model.rs index b60a01618b..916922bcb7 100644 --- a/crates/service/web/storyteller_web/src/http_server/endpoints/tts/get_tts_model.rs +++ b/crates/service/web/storyteller_web/src/http_server/endpoints/tts/get_tts_model.rs @@ -1,7 +1,7 @@ // NB: Incrementally getting rid of build warnings... -//#![forbid(unused_imports)] -//#![forbid(unused_mut)] -//#![forbid(unused_variables)] +#![forbid(unused_imports)] +#![forbid(unused_mut)] +#![forbid(unused_variables)] use actix_web::error::ResponseError; use actix_web::http::StatusCode; @@ -10,14 +10,13 @@ use actix_web::{web, HttpResponse, HttpRequest}; use chrono::{DateTime, Utc}; use crate::server_state::ServerState; use database_queries::column_types::vocoder_type::VocoderType; -use database_queries::queries::tts::tts_models::get_tts_model::{get_tts_model_by_token_using_connection, TtsModelRecord}; +use database_queries::queries::tts::tts_models::get_tts_model::get_tts_model_by_token_using_connection; use enums::common::visibility::Visibility; use http_server_common::response::serialize_as_json_error::serialize_as_json_error; use log::warn; +use redis_common::redis_cache_keys::RedisCacheKeys; use std::fmt; use std::sync::Arc; -use errors::AnyhowResult; -use redis_common::redis_cache_keys::RedisCacheKeys; use tts_common::text_pipelines::guess_pipeline::guess_text_pipeline_heuristic; use tts_common::text_pipelines::text_pipeline_type::TextPipelineType;