diff --git a/crates/lib/database_queries/src/queries/w2l/w2l_templates/list_w2l_templates.rs b/crates/lib/database_queries/src/queries/w2l/w2l_templates/list_w2l_templates.rs index 0ce308eba7..f39e10c208 100644 --- a/crates/lib/database_queries/src/queries/w2l/w2l_templates/list_w2l_templates.rs +++ b/crates/lib/database_queries/src/queries/w2l/w2l_templates/list_w2l_templates.rs @@ -7,7 +7,7 @@ use sqlx::MySqlPool; // FIXME: This is the old style of query scoping and shouldn't be copied. -#[derive(Serialize)] +#[derive(Serialize, Clone)] pub struct W2lTemplateRecordForList { pub template_token: String, pub template_type: String, diff --git a/crates/service/storyteller_web/src/http_server/endpoints/w2l/list_w2l_templates.rs b/crates/service/storyteller_web/src/http_server/endpoints/w2l/list_w2l_templates.rs index 4c7a0e0236..f9d7d3b3f1 100644 --- a/crates/service/storyteller_web/src/http_server/endpoints/w2l/list_w2l_templates.rs +++ b/crates/service/storyteller_web/src/http_server/endpoints/w2l/list_w2l_templates.rs @@ -10,7 +10,7 @@ use crate::AnyhowResult; use crate::http_server::web_utils::response_error_helpers::to_simple_json_error; use crate::server_state::ServerState; use database_queries::queries::w2l::w2l_templates::list_w2l_templates::{W2lTemplateRecordForList, list_w2l_templates}; -use log::{info, warn, log}; +use log::{info, warn, log, error}; use regex::Regex; use sqlx::MySqlPool; use sqlx::error::DatabaseError; @@ -57,22 +57,47 @@ pub async fn list_w2l_templates_handler( http_request: HttpRequest, server_state: web::Data>) -> Result { - let no_scope_creator = None; + // TODO(bt): Perhaps we should build a second endpoint to allow fetching a user's W2L templates + // and including them in the global list (before they're mod approved!) just for the uploader. - // TODO(bt): Ideally we show users their own W2L templates here before they're mod approved. + let maybe_templates = server_state + .caches + .w2l_template_list + .copy_without_bump_if_unexpired() + .map_err(|e| { + error!("Error consulting cache: {:?}", e); + ListW2lTemplatesError::ServerError + })?; - let query_results = list_w2l_templates( - &server_state.mysql_pool, - no_scope_creator, - true, - ).await; + let templates = match maybe_templates { + Some(templates) => { + templates + }, + None => { + const NO_CREATOR_SCOPING_HERE : Option<&'static str> = None; - let templates = match query_results { - Ok(results) => results, - Err(e) => { - warn!("w2l template list query error: {:?}", e); - return Err(ListW2lTemplatesError::ServerError); - } + let query_results = list_w2l_templates( + &server_state.mysql_pool, + NO_CREATOR_SCOPING_HERE, + true, + ).await; + + let templates = match query_results { + Ok(results) => results, + Err(e) => { + warn!("w2l template list query error: {:?}", e); + return Err(ListW2lTemplatesError::ServerError); + } + }; + + server_state.caches.w2l_template_list.store_copy(&templates) + .map_err(|e| { + error!("error storing cache: {:?}", e); + ListW2lTemplatesError::ServerError + })?; + + templates + }, }; let response = ListW2lTemplatesSuccessResponse { diff --git a/crates/service/storyteller_web/src/main.rs b/crates/service/storyteller_web/src/main.rs index 669ab286e5..379f929852 100644 --- a/crates/service/storyteller_web/src/main.rs +++ b/crates/service/storyteller_web/src/main.rs @@ -316,6 +316,10 @@ async fn main() -> AnyhowResult<()> { let voice_list_cache = SingleItemTtlCache::create_with_duration(voice_list_cache_ttl); let category_list_cache = SingleItemTtlCache::create_with_duration(category_list_cache_ttl); + let w2l_template_cache = SingleItemTtlCache::create_with_duration( + easyenv::get_env_duration_seconds_or_default("W2L_TEMPLATE_LIST_CACHE_TTL_SECONDS", Duration::from_secs(300)) // 5 minutes + ); + let tts_queue_length_cache = SingleItemTtlCache::create_with_duration( easyenv::get_env_duration_seconds_or_default("TTS_QUEUE_LENGTH_CACHE_TTL_SECONDS", Duration::from_secs(30)) ); @@ -392,6 +396,7 @@ async fn main() -> AnyhowResult<()> { static_api_token_set, caches: InMemoryCaches { voice_list: voice_list_cache, + w2l_template_list: w2l_template_cache, category_list: category_list_cache, tts_queue_length: tts_queue_length_cache, }, diff --git a/crates/service/storyteller_web/src/server_state.rs b/crates/service/storyteller_web/src/server_state.rs index 7cf0f9d02d..30130f5afd 100644 --- a/crates/service/storyteller_web/src/server_state.rs +++ b/crates/service/storyteller_web/src/server_state.rs @@ -13,6 +13,7 @@ use memory_caching::single_item_ttl_cache::SingleItemTtlCache; use r2d2_redis::{r2d2, RedisConnectionManager}; use sqlx::MySqlPool; use database_queries::queries::tts::tts_inference_jobs::get_pending_tts_inference_job_count::TtsQueueLengthResult; +use database_queries::queries::w2l::w2l_templates::list_w2l_templates::W2lTemplateRecordForList; use storage_buckets_common::bucket_client::BucketClient; /// State that is injected into every endpoint. @@ -105,6 +106,9 @@ pub struct InMemoryCaches { /// In-memory caches with TTL-based eviction. Contains a list of all voices. pub voice_list: SingleItemTtlCache>, + /// Contains a list of all W2L templates. + pub w2l_template_list: SingleItemTtlCache>, + /// In-memory caches with TTL-based eviction. Contains a list of all TTS categories. pub category_list: SingleItemTtlCache>,