From 0f076cbacdd8ae09b2cee1df9230c682c63ae11c Mon Sep 17 00:00:00 2001 From: Brandon Thomas Date: Sat, 11 Mar 2023 23:21:39 -0500 Subject: [PATCH] work in progress redis caching (this compiles) --- Cargo.lock | 1 + .../redis_caching/src/redis_ttl_cache.rs | 10 ++-- .../queries/tts/tts_models/get_tts_model.rs | 3 ++ crates/service/web/storyteller_web/Cargo.toml | 1 + .../endpoints/tts/get_tts_model.rs | 52 +++++++++++++++++-- .../service/web/storyteller_web/src/main.rs | 4 ++ .../web/storyteller_web/src/server_state.rs | 2 + 7 files changed, 66 insertions(+), 7 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 49c9b947df..ac75cba236 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6456,6 +6456,7 @@ dependencies = [ "pulldown-cmark", "r2d2_redis", "rand 0.8.5", + "redis_caching", "redis_common", "regex", "reqwest", diff --git a/crates/lib/caching/redis_caching/src/redis_ttl_cache.rs b/crates/lib/caching/redis_caching/src/redis_ttl_cache.rs index 10c6f95871..968e5e63ad 100644 --- a/crates/lib/caching/redis_caching/src/redis_ttl_cache.rs +++ b/crates/lib/caching/redis_caching/src/redis_ttl_cache.rs @@ -1,3 +1,4 @@ +use std::future::Future; use r2d2_redis::RedisConnectionManager; use r2d2_redis::r2d2::{Pool, PooledConnection}; use r2d2_redis::redis::Commands; @@ -65,10 +66,13 @@ impl RedisTtlCacheConnection { Ok(()) } - pub fn lazy_load_if_not_cached(&mut self, item_key: &str, loader_func: &mut F) + // NB(bt,2023-03-11): As of this writing, async closures are not yet stable. + // Return closures with internal async blocks instead. See: https://stackoverflow.com/a/74004017 + pub async fn lazy_load_if_not_cached(&mut self, item_key: &str, loader_func: F) -> AnyhowResult> where for<'a> T: Serialize + Deserialize<'a> + Clone, - F: FnMut() -> AnyhowResult>, + F: FnOnce() -> Fut, + Fut: Future>>, { let maybe_value = self.get_from_cache(item_key)?; @@ -76,7 +80,7 @@ impl RedisTtlCacheConnection { return Ok(value); } - let maybe_value = loader_func()?; + let maybe_value = loader_func().await?; if let Some(value) = maybe_value { self.persist_to_cache(item_key, value.clone())?; diff --git a/crates/lib/database_queries/src/queries/tts/tts_models/get_tts_model.rs b/crates/lib/database_queries/src/queries/tts/tts_models/get_tts_model.rs index 3c61c15781..60615d3718 100644 --- a/crates/lib/database_queries/src/queries/tts/tts_models/get_tts_model.rs +++ b/crates/lib/database_queries/src/queries/tts/tts_models/get_tts_model.rs @@ -16,6 +16,7 @@ use sqlx::{MySql, MySqlPool}; // FIXME: This is the old style of query scoping and shouldn't be copied. // The moderator-only fields are good practice, though. +#[derive(Serialize, Deserialize, Clone)] pub struct TtsModelRecord { pub model_token: String, pub tts_model_type: String, @@ -59,6 +60,7 @@ pub struct TtsModelRecord { pub maybe_moderator_fields: Option, } +#[derive(Serialize, Deserialize, Clone)] pub struct CustomVocoderFields { pub vocoder_token: String, pub vocoder_title: String, @@ -70,6 +72,7 @@ pub struct CustomVocoderFields { /// "Moderator-only fields" that we wouldn't want to expose to ordinary users. /// It's the web endpoint controller's responsibility to clear these for non-mods. +#[derive(Serialize, Deserialize, Clone)] pub struct TtsModelModeratorFields { // Moderator-set mel multiply factors pub use_default_mel_multiply_factor: bool, diff --git a/crates/service/web/storyteller_web/Cargo.toml b/crates/service/web/storyteller_web/Cargo.toml index 3631e0c2f5..f4091d3eaa 100644 --- a/crates/service/web/storyteller_web/Cargo.toml +++ b/crates/service/web/storyteller_web/Cargo.toml @@ -31,6 +31,7 @@ http_server_common = { path = "../../../lib/http_server_common" } jobs_common = { path = "../../../lib/jobs_common" } media = { path = "../../../lib/media" } memory_caching = { path = "../../../lib/caching/memory_caching" } +redis_caching = { path = "../../../lib/caching/redis_caching" } redis_common = { path = "../../../lib/redis_common" } reusable_types = { path = "../../../_types/reusable_types" } tokens = { path = "../../../_types/tokens" } 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 20b308282f..2726d1f1dd 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,12 +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; +use database_queries::queries::tts::tts_models::get_tts_model::{get_tts_model_by_token_using_connection, TtsModelRecord}; use enums::common::visibility::Visibility; use http_server_common::response::serialize_as_json_error::serialize_as_json_error; use log::warn; use std::fmt; use std::sync::Arc; +use errors::AnyhowResult; use tts_common::text_pipelines::guess_pipeline::guess_text_pipeline_heuristic; use tts_common::text_pipelines::text_pipeline_type::TextPipelineType; @@ -193,6 +194,49 @@ pub async fn get_tts_model_handler( || user_session.can_edit_other_users_tts_models; } + + + let mut redis_ttl_cache = server_state.redis_ttl_cache.get_connection() + .map_err(|err| { + warn!("Error loading Redis connection from TTL cache: {:?}", err); + GetTtsModelError::ServerError + })?; + + let key = path.token.clone(); + + //let _result :AnyhowResult> = redis_ttl_cache.lazy_load_if_not_cached(&key, move || { + let _r = redis_ttl_cache.lazy_load_if_not_cached(&key, move || { + let _r = async { + //let _model_query_result = get_tts_model_by_token_using_connection( + // &path.token, + // show_deleted_models, + // &mut mysql_connection, + //).await; + }; + let foo = "foo".to_string(); + + std::future::ready(Ok(Some(foo))) + + }).await; + + + + + + + + + + + + + + + + + + + let model_query_result = get_tts_model_by_token_using_connection( &path.token, show_deleted_models, diff --git a/crates/service/web/storyteller_web/src/main.rs b/crates/service/web/storyteller_web/src/main.rs index 5ec5631ac3..e4ab599d6c 100644 --- a/crates/service/web/storyteller_web/src/main.rs +++ b/crates/service/web/storyteller_web/src/main.rs @@ -89,6 +89,7 @@ use actix_helpers::middleware::endpoint_disablement::disabled_endpoints::disable use actix_helpers::middleware::endpoint_disablement::disabled_endpoints::exact_match_endpoint_disablements::ExactMatchEndpointDisablements; use actix_helpers::middleware::endpoint_disablement::disabled_endpoints::prefix_endpoint_disablements::PrefixEndpointDisablements; use actix_helpers::middleware::endpoint_disablement::endpoint_disablement_middleware::EndpointDisablementFilter; +use redis_caching::redis_ttl_cache::RedisTtlCache; use twitch_common::twitch_secrets::TwitchSecrets; use url_config::third_party_url_redirector::ThirdPartyUrlRedirector; use users_component::utils::session_checker::SessionChecker; @@ -155,6 +156,8 @@ async fn main() -> AnyhowResult<()> { let redis_pool = r2d2::Pool::builder() .build(redis_manager)?; + let redis_ttl_cache = RedisTtlCache::new(redis_pool.clone()); + info!("Setting up Redis rate limiters..."); // Old env vars: @@ -397,6 +400,7 @@ async fn main() -> AnyhowResult<()> { health_check_status, mysql_pool: pool, redis_pool, + redis_ttl_cache, redis_rate_limiters: RedisRateLimiters { logged_out: logged_out_redis_rate_limiter, logged_in: logged_in_redis_rate_limiter, diff --git a/crates/service/web/storyteller_web/src/server_state.rs b/crates/service/web/storyteller_web/src/server_state.rs index 70579404b1..fb9f5e5654 100644 --- a/crates/service/web/storyteller_web/src/server_state.rs +++ b/crates/service/web/storyteller_web/src/server_state.rs @@ -16,6 +16,7 @@ use database_queries::queries::tts::tts_inference_jobs::get_pending_tts_inferenc use database_queries::queries::w2l::w2l_templates::list_w2l_templates::W2lTemplateRecordForList; use memory_caching::single_item_ttl_cache::SingleItemTtlCache; use r2d2_redis::{r2d2, RedisConnectionManager}; +use redis_caching::redis_ttl_cache::RedisTtlCache; use reusable_types::server_environment::ServerEnvironment; use sqlx::MySqlPool; use url_config::third_party_url_redirector::ThirdPartyUrlRedirector; @@ -46,6 +47,7 @@ pub struct ServerState { pub mysql_pool: MySqlPool, pub redis_pool: r2d2::Pool, + pub redis_ttl_cache: RedisTtlCache, pub redis_rate_limiters: RedisRateLimiters,