Skip to main content

tuwunel_service/rooms/spaces/
cache.rs

1use std::time::SystemTime;
2
3use ruma::{
4	RoomId,
5	api::{
6		client::space::SpaceHierarchyRoomsChunk,
7		federation::space::SpaceHierarchyParentSummary as ParentSummary,
8	},
9};
10use serde::{Deserialize, Serialize};
11use tuwunel_core::{Result, at, debug, implement, utils::rand::time_from_now_secs};
12use tuwunel_database::{Deserialized, Json};
13
14use super::is_summary_serializable;
15
16#[derive(Debug, Deserialize, Serialize)]
17pub(super) struct Cached {
18	pub(super) expires: SystemTime,
19	pub(super) summary: Option<ParentSummary>,
20}
21
22/// Remove the entry for `room_id` from the cache.
23#[implement(super::Service)]
24#[inline]
25#[tracing::instrument(name = "evict", level = "debug", skip_all, fields(room_id))]
26pub fn cache_evict(&self, room_id: &RoomId) { self.db.roomid_spacehierarchy.remove(room_id); }
27
28#[implement(super::Service)]
29#[tracing::instrument(
30	level = "debug",
31	skip(self, summary),
32	fields(summary = summary.is_some())
33)]
34pub(super) fn cache_put(&self, room_id: &RoomId, summary: Option<&ParentSummary>) {
35	debug!(?room_id, "cache put");
36	self.db.roomid_spacehierarchy.raw_put(
37		room_id,
38		Json(Cached {
39			expires: self.generate_ttl(),
40			summary: summary.cloned().filter(is_summary_serializable),
41		}),
42	);
43}
44
45#[implement(super::Service)]
46#[tracing::instrument(
47	level = "trace",
48	skip(self),
49	err(level = "debug"),
50	ret(level = "trace")
51)]
52pub(super) async fn cache_get(&self, room_id: &RoomId) -> Result<Cached> {
53	self.db
54		.roomid_spacehierarchy
55		.get(room_id)
56		.await
57		.deserialized::<Json<Cached>>()
58		.map(at!(0))
59}
60
61/// Here because cannot implement `From` across ruma-federation-api and
62/// ruma-client-api types
63impl From<Cached> for Option<SpaceHierarchyRoomsChunk> {
64	#[inline]
65	fn from(value: Cached) -> Self {
66		value
67			.summary
68			.map(|ParentSummary { children_state, summary }: ParentSummary| {
69				SpaceHierarchyRoomsChunk { children_state, summary }
70			})
71	}
72}
73
74#[implement(super::Service)]
75#[inline]
76fn generate_ttl(&self) -> SystemTime {
77	time_from_now_secs(
78		self.services.config.spacehierarchy_cache_ttl_min
79			..self.services.config.spacehierarchy_cache_ttl_max,
80	)
81}