From 8584bb439b3cf19fa775f10371eb25c5b7e5f143 Mon Sep 17 00:00:00 2001 From: naskya Date: Thu, 1 Aug 2024 15:57:21 +0900 Subject: [PATCH] refactor (backend-rs): rework static cache Co-authored-by: sup39 --- packages/backend-rs/src/cache/bare.rs | 53 +++++++++++++++++++ packages/backend-rs/src/cache/mod.rs | 3 ++ packages/backend-rs/src/config/meta.rs | 14 ++--- .../src/federation/nodeinfo/generate.rs | 15 ++---- packages/backend-rs/src/lib.rs | 1 + .../backend-rs/src/service/antenna/cache.rs | 26 --------- .../backend-rs/src/service/antenna/mod.rs | 22 +++++++- .../src/service/antenna/process_new_note.rs | 2 +- .../backend-rs/src/service/antenna/update.rs | 2 +- 9 files changed, 90 insertions(+), 48 deletions(-) create mode 100644 packages/backend-rs/src/cache/bare.rs create mode 100644 packages/backend-rs/src/cache/mod.rs delete mode 100644 packages/backend-rs/src/service/antenna/cache.rs diff --git a/packages/backend-rs/src/cache/bare.rs b/packages/backend-rs/src/cache/bare.rs new file mode 100644 index 0000000000..a6af17e0b8 --- /dev/null +++ b/packages/backend-rs/src/cache/bare.rs @@ -0,0 +1,53 @@ +//! In-memory cache handler + +use chrono::{DateTime, Duration, Utc}; +use std::sync::Mutex; + +pub struct Cache { + cache: Mutex>, + ttl: Option, +} + +struct TimedData { + value: Option, + last_updated: DateTime, +} + +impl Cache { + pub const fn new(ttl: Option) -> Self { + Self { + cache: Mutex::new(TimedData { + value: None, + last_updated: DateTime::UNIX_EPOCH, + }), + ttl, + } + } + + pub fn set(&self, value: T) { + if self.ttl.is_none() { + let _ = self + .cache + .lock() + .map(|mut cache| (*cache).value = Some(value)); + } else { + let _ = self.cache.lock().map(|mut cache| { + *cache = TimedData { + value: Some(value), + last_updated: Utc::now(), + } + }); + } + } + + pub fn get(&self) -> Option { + let data = self.cache.lock().ok()?; + + if let Some(ttl) = self.ttl { + if data.last_updated + ttl < Utc::now() { + return None; + } + } + data.value.to_owned() + } +} diff --git a/packages/backend-rs/src/cache/mod.rs b/packages/backend-rs/src/cache/mod.rs new file mode 100644 index 0000000000..0d76e68490 --- /dev/null +++ b/packages/backend-rs/src/cache/mod.rs @@ -0,0 +1,3 @@ +pub mod bare; + +pub use bare::Cache; diff --git a/packages/backend-rs/src/config/meta.rs b/packages/backend-rs/src/config/meta.rs index 969d9d35f5..f0d7beddf8 100644 --- a/packages/backend-rs/src/config/meta.rs +++ b/packages/backend-rs/src/config/meta.rs @@ -1,15 +1,11 @@ //! Server information -use crate::{database::db_conn, model::entity::meta}; +use crate::{cache::Cache, database::db_conn, model::entity::meta}; use sea_orm::{prelude::*, ActiveValue}; -use std::sync::Mutex; type Meta = meta::Model; -static CACHE: Mutex> = Mutex::new(None); -fn set_cache(meta: &Meta) { - let _ = CACHE.lock().map(|mut cache| *cache = Some(meta.clone())); -} +static INSTANCE_META_CACHE: Cache = Cache::new(None); #[macros::export(js_name = "fetchMeta")] pub async fn local_server_info() -> Result { @@ -25,7 +21,7 @@ pub async fn update() -> Result<(), DbErr> { async fn local_server_info_impl(use_cache: bool) -> Result { // try using cache if use_cache { - if let Some(cache) = CACHE.lock().ok().and_then(|cache| cache.clone()) { + if let Some(cache) = INSTANCE_META_CACHE.get() { return Ok(cache); } } @@ -34,7 +30,7 @@ async fn local_server_info_impl(use_cache: bool) -> Result { let db = db_conn().await?; let meta = meta::Entity::find().one(db).await?; if let Some(meta) = meta { - set_cache(&meta); + INSTANCE_META_CACHE.set(meta.clone()); return Ok(meta); } @@ -45,7 +41,7 @@ async fn local_server_info_impl(use_cache: bool) -> Result { }) .exec_with_returning(db) .await?; - set_cache(&meta); + INSTANCE_META_CACHE.set(meta.clone()); Ok(meta) } diff --git a/packages/backend-rs/src/federation/nodeinfo/generate.rs b/packages/backend-rs/src/federation/nodeinfo/generate.rs index 921fc547b0..430e5a1e7a 100644 --- a/packages/backend-rs/src/federation/nodeinfo/generate.rs +++ b/packages/backend-rs/src/federation/nodeinfo/generate.rs @@ -1,6 +1,7 @@ //! NodeInfo generator use crate::{ + cache::Cache, config::{local_server_info, CONFIG}, database::db_conn, federation::nodeinfo::schema::*, @@ -9,15 +10,9 @@ use crate::{ }; use sea_orm::prelude::*; use serde_json::json; -use std::{collections::HashMap, sync::Mutex}; +use std::collections::HashMap; -static CACHE: Mutex> = Mutex::new(None); - -fn set_cache(nodeinfo: &Nodeinfo21) { - let _ = CACHE - .lock() - .map(|mut cache| *cache = Some(nodeinfo.to_owned())); -} +static NODEINFO_CACHE: Cache = Cache::new(None); /// Fetches the number of total/active local users and local posts. /// @@ -129,7 +124,7 @@ async fn generate_nodeinfo_2_1() -> Result { async fn nodeinfo_2_1_impl(use_cache: bool) -> Result { if use_cache { - if let Some(nodeinfo) = CACHE.lock().ok().and_then(|cache| cache.to_owned()) { + if let Some(nodeinfo) = NODEINFO_CACHE.get() { return Ok(nodeinfo); } } @@ -137,7 +132,7 @@ async fn nodeinfo_2_1_impl(use_cache: bool) -> Result { let nodeinfo = generate_nodeinfo_2_1().await?; tracing::info!("updating cache"); - set_cache(&nodeinfo); + NODEINFO_CACHE.set(nodeinfo.clone()); Ok(nodeinfo) } diff --git a/packages/backend-rs/src/lib.rs b/packages/backend-rs/src/lib.rs index ff7a49a471..89d357ed77 100644 --- a/packages/backend-rs/src/lib.rs +++ b/packages/backend-rs/src/lib.rs @@ -1,5 +1,6 @@ #![doc = include_str!(concat!(env!("CARGO_MANIFEST_DIR"), "/README.md"))] +pub mod cache; pub mod config; pub mod database; pub mod federation; diff --git a/packages/backend-rs/src/service/antenna/cache.rs b/packages/backend-rs/src/service/antenna/cache.rs deleted file mode 100644 index ce83895368..0000000000 --- a/packages/backend-rs/src/service/antenna/cache.rs +++ /dev/null @@ -1,26 +0,0 @@ -//! In-memory antennas cache handler - -use crate::{database::db_conn, model::entity::antenna}; -use sea_orm::prelude::*; -use std::sync::{Arc, Mutex}; - -static CACHE: Mutex>> = Mutex::new(None); - -fn set(antennas: Arc<[antenna::Model]>) { - let _ = CACHE.lock().map(|mut cache| *cache = Some(antennas)); -} - -pub(super) async fn update() -> Result, DbErr> { - tracing::debug!("updating cache"); - let antennas: Arc<[antenna::Model]> = - antenna::Entity::find().all(db_conn().await?).await?.into(); - set(antennas.clone()); - Ok(antennas) -} - -pub(super) async fn get() -> Result, DbErr> { - if let Some(cache) = CACHE.lock().ok().and_then(|cache| cache.clone()) { - return Ok(cache); - } - update().await -} diff --git a/packages/backend-rs/src/service/antenna/mod.rs b/packages/backend-rs/src/service/antenna/mod.rs index 2f255581ed..e90693c6ac 100644 --- a/packages/backend-rs/src/service/antenna/mod.rs +++ b/packages/backend-rs/src/service/antenna/mod.rs @@ -1,4 +1,24 @@ -mod cache; mod check_hit; pub mod process_new_note; pub mod update; + +use crate::{cache::Cache, database::db_conn, model::entity::antenna}; +use sea_orm::prelude::*; +use std::sync::Arc; + +static ANTENNAS_CACHE: Cache> = Cache::new(None); + +async fn update() -> Result, DbErr> { + tracing::debug!("updating cache"); + let antennas: Arc<[antenna::Model]> = + antenna::Entity::find().all(db_conn().await?).await?.into(); + ANTENNAS_CACHE.set(antennas.clone()); + Ok(antennas) +} + +async fn get_antennas() -> Result, DbErr> { + if let Some(cache) = ANTENNAS_CACHE.get() { + return Ok(cache); + } + update().await +} diff --git a/packages/backend-rs/src/service/antenna/process_new_note.rs b/packages/backend-rs/src/service/antenna/process_new_note.rs index d9099f867f..689e4c7d33 100644 --- a/packages/backend-rs/src/service/antenna/process_new_note.rs +++ b/packages/backend-rs/src/service/antenna/process_new_note.rs @@ -46,7 +46,7 @@ pub async fn update_antennas_on_new_note( let note_all_texts = elaborate!(note, false).await?; // TODO: do this in parallel - for antenna in antenna::cache::get().await?.iter() { + for antenna in antenna::get_antennas().await?.iter() { if note_muted_users.contains(&antenna.user_id) { continue; } diff --git a/packages/backend-rs/src/service/antenna/update.rs b/packages/backend-rs/src/service/antenna/update.rs index 169e574379..d08ec2c968 100644 --- a/packages/backend-rs/src/service/antenna/update.rs +++ b/packages/backend-rs/src/service/antenna/update.rs @@ -2,6 +2,6 @@ #[macros::ts_export] pub async fn update_antenna_cache() -> Result<(), sea_orm::DbErr> { - super::cache::update().await?; + super::update().await?; Ok(()) }