feat: global users cache for faster resolution

not the fanciest way to do it (with lazy_static) but whatevs it works
This commit is contained in:
əlemi 2024-04-15 05:27:53 +02:00
parent 268265e34a
commit e1176c7ec1
Signed by: alemi
GPG key ID: A4895B84D311642C
3 changed files with 37 additions and 12 deletions

View file

@ -26,3 +26,4 @@ reqwest = { version = "0.12", features = ["json"] }
apb = { path = "../apb", features = ["unstructured"] } apb = { path = "../apb", features = ["unstructured"] }
futures = "0.3.30" futures = "0.3.30"
dissolve = "0.2" # TODO strip html without this crate dissolve = "0.2" # TODO strip html without this crate
lazy_static = "1.4"

23
web/src/context.rs Normal file
View file

@ -0,0 +1,23 @@
use std::sync::Arc;
use dashmap::DashMap;
use lazy_static::lazy_static;
lazy_static! {
pub static ref CTX: Context = Context::default();
}
#[derive(Debug, Default, Clone)]
pub struct Context {
pub cache: Arc<Cache>,
pub timelines: Arc<Timelines>,
}
#[derive(Debug, Default)]
pub struct Cache {
pub user: DashMap<String, serde_json::Value>,
}
#[derive(Debug, Default)]
pub struct Timelines {
}

View file

@ -1,10 +1,11 @@
use std::sync::Arc; pub mod context;
use apb::{target::Addressed, Activity, ActivityMut, Actor, Base, Collection, Object, ObjectMut}; use apb::{target::Addressed, Activity, ActivityMut, Actor, Base, Collection, Object, ObjectMut};
use dashmap::DashMap; use context::CTX;
use leptos::{leptos_dom::logging::console_log, *}; use leptos::{leptos_dom::logging::console_log, *};
use leptos_router::*; use leptos_router::*;
pub const URL_BASE: &str = "https://feditest.alemi.dev"; pub const URL_BASE: &str = "https://feditest.alemi.dev";
pub const URL_PREFIX: &str = "/web"; pub const URL_PREFIX: &str = "/web";
@ -145,12 +146,16 @@ pub fn Actor() -> impl IntoView {
let params = use_params_map(); let params = use_params_map();
let actor = create_local_resource(move || params.get().get("id").cloned().unwrap_or_default(), |uid| { let actor = create_local_resource(move || params.get().get("id").cloned().unwrap_or_default(), |uid| {
async move { async move {
reqwest::get(format!("{URL_BASE}/users/{uid}")) let uid = format!("{URL_BASE}/users/{uid}");
match CTX.cache.user.get(&uid) {
Some(x) => x.clone(),
None => reqwest::get(uid)
.await .await
.unwrap() .unwrap()
.json::<serde_json::Value>() .json::<serde_json::Value>()
.await .await
.unwrap() .unwrap(),
}
} }
}); });
view! { view! {
@ -231,11 +236,8 @@ pub fn Timeline(
token: Signal<Option<String>>, token: Signal<Option<String>>,
) -> impl IntoView { ) -> impl IntoView {
let (timeline, set_timeline) = create_signal(format!("{URL_BASE}/inbox/page")); let (timeline, set_timeline) = create_signal(format!("{URL_BASE}/inbox/page"));
let users : Arc<DashMap<String, serde_json::Value>> = Arc::new(DashMap::new()); let items = create_local_resource(move || timeline.get(), move |feed_url| async move {
let _users = users.clone(); // TODO i think there is syntactic sugar i forgot? fetch_activities_with_users(&feed_url, token).await
let items = create_local_resource(move || timeline.get(), move |feed_url| {
let __users = _users.clone(); // TODO lmao this is meme tier
async move { fetch_activities_with_users(&feed_url, token, __users).await }
}); });
view! { view! {
<div class="ml-1"> <div class="ml-1">
@ -275,7 +277,6 @@ pub fn Timeline(
async fn fetch_activities_with_users( async fn fetch_activities_with_users(
feed_url: &str, feed_url: &str,
token: Signal<Option<String>>, token: Signal<Option<String>>,
users: Arc<DashMap<String, serde_json::Value>>,
) -> reqwest::Result<Vec<serde_json::Value>> { ) -> reqwest::Result<Vec<serde_json::Value>> {
let mut req = reqwest::Client::new().get(feed_url); let mut req = reqwest::Client::new().get(feed_url);
@ -298,7 +299,7 @@ async fn fetch_activities_with_users(
let mut out = Vec::new(); let mut out = Vec::new();
for x in activities { for x in activities {
if let Some(uid) = x.actor().id() { if let Some(uid) = x.actor().id() {
if let Some(actor) = users.get(&uid) { if let Some(actor) = CTX.cache.user.get(&uid) {
out.push(x.set_actor(apb::Node::object(actor.clone()))) out.push(x.set_actor(apb::Node::object(actor.clone())))
} else { } else {
let mut req = reqwest::Client::new() let mut req = reqwest::Client::new()
@ -310,7 +311,7 @@ async fn fetch_activities_with_users(
// TODO don't fail whole timeline fetch when one user fails fetching... // TODO don't fail whole timeline fetch when one user fails fetching...
let actor = req.send().await?.json::<serde_json::Value>().await?; let actor = req.send().await?.json::<serde_json::Value>().await?;
users.insert(uid, actor.clone()); CTX.cache.user.insert(uid, actor.clone());
out.push(x.set_actor(apb::Node::object(actor))) out.push(x.set_actor(apb::Node::object(actor)))
} }