fractal/session/remote/
cache.rs1use std::{cell::RefCell, fmt, rc::Rc};
2
3use quick_cache::unsync::Cache;
4use ruma::{OwnedRoomOrAliasId, OwnedUserId, RoomId};
5
6use super::{RemoteRoom, RemoteUser};
7use crate::{session::Session, utils::matrix::MatrixRoomIdUri};
8
9struct RemoteCacheData {
11 rooms: RefCell<Cache<OwnedRoomOrAliasId, RemoteRoom>>,
13 users: RefCell<Cache<OwnedUserId, RemoteUser>>,
15}
16
17#[derive(Clone)]
19pub(crate) struct RemoteCache {
20 session: Session,
21 data: Rc<RemoteCacheData>,
22}
23
24impl RemoteCache {
25 pub(crate) fn new(session: Session) -> Self {
27 Self {
28 session,
29 data: RemoteCacheData {
30 rooms: Cache::new(30).into(),
31 users: Cache::new(30).into(),
32 }
33 .into(),
34 }
35 }
36
37 pub(crate) fn room(&self, uri: MatrixRoomIdUri) -> RemoteRoom {
39 let mut rooms = self.data.rooms.borrow_mut();
40
41 if let Some(room) = rooms.get(&uri.id) {
43 room.load_data_if_stale();
44 return room.clone();
45 }
46
47 let mut found_id = None;
50 let id_or_alias = <&RoomId>::try_from(&*uri.id);
51
52 for (id, room) in rooms.iter() {
53 match id_or_alias {
54 Ok(room_id) => {
55 if room.room_id().is_some_and(|id| id == room_id) {
56 found_id = Some(id.clone());
57 break;
58 }
59 }
60 Err(room_alias) => {
61 if room
62 .canonical_alias()
63 .is_some_and(|alias| alias == room_alias)
64 {
65 found_id = Some(id.clone());
66 break;
67 }
68 }
69 }
70 }
71
72 if let Some(id) = found_id {
73 let room = rooms.get(&id).expect("room should be in cache");
74 room.load_data_if_stale();
75 return room.clone();
76 }
77
78 let id = uri.id.clone();
80 let room = RemoteRoom::new(&self.session, uri);
81 rooms.insert(id, room.clone());
82
83 room
84 }
85
86 pub(crate) fn user(&self, user_id: OwnedUserId) -> RemoteUser {
88 let mut users = self.data.users.borrow_mut();
89
90 if let Some(user) = users.get(&user_id) {
92 user.load_profile_if_stale();
93 return user.clone();
94 }
95
96 let user = RemoteUser::new(&self.session, user_id.clone());
98 users.insert(user_id, user.clone());
99
100 user
101 }
102}
103
104impl fmt::Debug for RemoteCache {
105 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
106 f.debug_struct("RemoteCache").finish_non_exhaustive()
107 }
108}