From e923c8772423e660a9db6f69f9c35f2def2def2a Mon Sep 17 00:00:00 2001 From: Felix Ableitner Date: Thu, 21 Nov 2024 23:20:44 +0100 Subject: [PATCH] Better caching of api calls --- crates/api_crud/src/site/read.rs | 77 ++++++++++++++++++-------------- 1 file changed, 43 insertions(+), 34 deletions(-) diff --git a/crates/api_crud/src/site/read.rs b/crates/api_crud/src/site/read.rs index 47fd1f154..30e74837f 100644 --- a/crates/api_crud/src/site/read.rs +++ b/crates/api_crud/src/site/read.rs @@ -16,54 +16,37 @@ use lemmy_db_schema::source::{ use lemmy_db_views::structs::{LocalUserView, SiteView}; use lemmy_db_views_actor::structs::{CommunityFollowerView, CommunityModeratorView, PersonView}; use lemmy_utils::{ - error::{LemmyError, LemmyErrorExt, LemmyErrorType, LemmyResult}, + error::{LemmyErrorExt, LemmyErrorType, LemmyResult}, CACHE_DURATION_API, VERSION, }; use moka::future::Cache; use std::sync::LazyLock; +fn build_cache() -> Cache +where + K: std::fmt::Debug + Eq + std::hash::Hash + Send + Sync + 'static, + V: std::fmt::Debug + Clone + Send + Sync + 'static, +{ + Cache::::builder() + .max_capacity(1) + .time_to_live(CACHE_DURATION_API) + .build() +} + +type CacheLock = LazyLock>; + #[tracing::instrument(skip(context))] pub async fn get_site( local_user_view: Option, context: Data, ) -> LemmyResult> { - static CACHE: LazyLock> = LazyLock::new(|| { - Cache::builder() - .max_capacity(1) - .time_to_live(CACHE_DURATION_API) - .build() - }); - // This data is independent from the user account so we can cache it across requests + static CACHE: CacheLock = LazyLock::new(build_cache); let mut site_response = CACHE - .try_get_with::<_, LemmyError>((), async { - let site_view = SiteView::read_local(&mut context.pool()).await?; - let admins = PersonView::admins(&mut context.pool()).await?; - let all_languages = Language::read_all(&mut context.pool()).await?; - let discussion_languages = SiteLanguage::read_local_raw(&mut context.pool()).await?; - let blocked_urls = LocalSiteUrlBlocklist::get_all(&mut context.pool()).await?; - let tagline = Tagline::get_random(&mut context.pool()).await.ok(); - let admin_oauth_providers = OAuthProvider::get_all(&mut context.pool()).await?; - let oauth_providers = - OAuthProvider::convert_providers_to_public(admin_oauth_providers.clone()); - - Ok(GetSiteResponse { - site_view, - admins, - version: VERSION.to_string(), - my_user: None, - all_languages, - discussion_languages, - blocked_urls, - tagline, - oauth_providers: Some(oauth_providers), - admin_oauth_providers: Some(admin_oauth_providers), - taglines: vec![], - custom_emojis: vec![], - }) - }) + .try_get_with((), read_site(&context)) .await + // TODO: we should never call anyhow like this, add lemmyerror instead .map_err(|e| anyhow::anyhow!("Failed to construct site response: {e}"))?; // Build the local user with parallel queries and add it to site response @@ -112,3 +95,29 @@ pub async fn get_site( Ok(Json(site_response)) } + +async fn read_site(context: &LemmyContext) -> LemmyResult { + let site_view = SiteView::read_local(&mut context.pool()).await?; + let admins = PersonView::admins(&mut context.pool()).await?; + let all_languages = Language::read_all(&mut context.pool()).await?; + let discussion_languages = SiteLanguage::read_local_raw(&mut context.pool()).await?; + let blocked_urls = LocalSiteUrlBlocklist::get_all(&mut context.pool()).await?; + let tagline = Tagline::get_random(&mut context.pool()).await.ok(); + let admin_oauth_providers = OAuthProvider::get_all(&mut context.pool()).await?; + let oauth_providers = OAuthProvider::convert_providers_to_public(admin_oauth_providers.clone()); + + Ok(GetSiteResponse { + site_view, + admins, + version: VERSION.to_string(), + my_user: None, + all_languages, + discussion_languages, + blocked_urls, + tagline, + oauth_providers: Some(oauth_providers), + admin_oauth_providers: Some(admin_oauth_providers), + taglines: vec![], + custom_emojis: vec![], + }) +}