matrix_sdk_base/event_cache/store/
traits.rs1use std::{fmt, sync::Arc};
16
17use async_trait::async_trait;
18use matrix_sdk_common::{
19 AsyncTraitDeps,
20 cross_process_lock::CrossProcessLockGeneration,
21 linked_chunk::{
22 ChunkIdentifier, ChunkIdentifierGenerator, ChunkMetadata, LinkedChunkId, Position,
23 RawChunk, Update,
24 },
25};
26use ruma::{EventId, OwnedEventId, RoomId, events::relation::RelationType};
27
28use super::EventCacheStoreError;
29use crate::event_cache::{Event, Gap};
30
31pub const DEFAULT_CHUNK_CAPACITY: usize = 128;
35
36#[cfg_attr(target_family = "wasm", async_trait(?Send))]
39#[cfg_attr(not(target_family = "wasm"), async_trait)]
40pub trait EventCacheStore: AsyncTraitDeps {
41 type Error: fmt::Debug + Into<EventCacheStoreError>;
43
44 async fn try_take_leased_lock(
46 &self,
47 lease_duration_ms: u32,
48 key: &str,
49 holder: &str,
50 ) -> Result<Option<CrossProcessLockGeneration>, Self::Error>;
51
52 async fn handle_linked_chunk_updates(
56 &self,
57 linked_chunk_id: LinkedChunkId<'_>,
58 updates: Vec<Update<Event, Gap>>,
59 ) -> Result<(), Self::Error>;
60
61 async fn remove_room(&self, room_id: &RoomId) -> Result<(), Self::Error> {
63 self.handle_linked_chunk_updates(LinkedChunkId::Room(room_id), vec![Update::Clear]).await
66 }
67
68 #[doc(hidden)]
71 async fn load_all_chunks(
72 &self,
73 linked_chunk_id: LinkedChunkId<'_>,
74 ) -> Result<Vec<RawChunk<Event, Gap>>, Self::Error>;
75
76 async fn load_all_chunks_metadata(
81 &self,
82 linked_chunk_id: LinkedChunkId<'_>,
83 ) -> Result<Vec<ChunkMetadata>, Self::Error>;
84
85 async fn load_last_chunk(
90 &self,
91 linked_chunk_id: LinkedChunkId<'_>,
92 ) -> Result<(Option<RawChunk<Event, Gap>>, ChunkIdentifierGenerator), Self::Error>;
93
94 async fn load_previous_chunk(
100 &self,
101 linked_chunk_id: LinkedChunkId<'_>,
102 before_chunk_identifier: ChunkIdentifier,
103 ) -> Result<Option<RawChunk<Event, Gap>>, Self::Error>;
104
105 async fn clear_all_linked_chunks(&self) -> Result<(), Self::Error>;
116
117 async fn filter_duplicated_events(
120 &self,
121 linked_chunk_id: LinkedChunkId<'_>,
122 events: Vec<OwnedEventId>,
123 ) -> Result<Vec<(OwnedEventId, Position)>, Self::Error>;
124
125 async fn find_event(
130 &self,
131 room_id: &RoomId,
132 event_id: &EventId,
133 ) -> Result<Option<Event>, Self::Error>;
134
135 async fn find_event_relations(
152 &self,
153 room_id: &RoomId,
154 event_id: &EventId,
155 filter: Option<&[RelationType]>,
156 ) -> Result<Vec<(Event, Option<Position>)>, Self::Error>;
157
158 async fn get_room_events(
163 &self,
164 room_id: &RoomId,
165 event_type: Option<&str>,
166 session_id: Option<&str>,
167 ) -> Result<Vec<Event>, Self::Error>;
168
169 async fn save_event(&self, room_id: &RoomId, event: Event) -> Result<(), Self::Error>;
178
179 #[doc(hidden)]
185 async fn optimize(&self) -> Result<(), Self::Error>;
186
187 async fn get_size(&self) -> Result<Option<usize>, Self::Error>;
189}
190
191#[repr(transparent)]
192struct EraseEventCacheStoreError<T>(T);
193
194#[cfg(not(tarpaulin_include))]
195impl<T: fmt::Debug> fmt::Debug for EraseEventCacheStoreError<T> {
196 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
197 self.0.fmt(f)
198 }
199}
200
201#[cfg_attr(target_family = "wasm", async_trait(?Send))]
202#[cfg_attr(not(target_family = "wasm"), async_trait)]
203impl<T: EventCacheStore> EventCacheStore for EraseEventCacheStoreError<T> {
204 type Error = EventCacheStoreError;
205
206 async fn try_take_leased_lock(
207 &self,
208 lease_duration_ms: u32,
209 key: &str,
210 holder: &str,
211 ) -> Result<Option<CrossProcessLockGeneration>, Self::Error> {
212 self.0.try_take_leased_lock(lease_duration_ms, key, holder).await.map_err(Into::into)
213 }
214
215 async fn handle_linked_chunk_updates(
216 &self,
217 linked_chunk_id: LinkedChunkId<'_>,
218 updates: Vec<Update<Event, Gap>>,
219 ) -> Result<(), Self::Error> {
220 self.0.handle_linked_chunk_updates(linked_chunk_id, updates).await.map_err(Into::into)
221 }
222
223 async fn load_all_chunks(
224 &self,
225 linked_chunk_id: LinkedChunkId<'_>,
226 ) -> Result<Vec<RawChunk<Event, Gap>>, Self::Error> {
227 self.0.load_all_chunks(linked_chunk_id).await.map_err(Into::into)
228 }
229
230 async fn load_all_chunks_metadata(
231 &self,
232 linked_chunk_id: LinkedChunkId<'_>,
233 ) -> Result<Vec<ChunkMetadata>, Self::Error> {
234 self.0.load_all_chunks_metadata(linked_chunk_id).await.map_err(Into::into)
235 }
236
237 async fn load_last_chunk(
238 &self,
239 linked_chunk_id: LinkedChunkId<'_>,
240 ) -> Result<(Option<RawChunk<Event, Gap>>, ChunkIdentifierGenerator), Self::Error> {
241 self.0.load_last_chunk(linked_chunk_id).await.map_err(Into::into)
242 }
243
244 async fn load_previous_chunk(
245 &self,
246 linked_chunk_id: LinkedChunkId<'_>,
247 before_chunk_identifier: ChunkIdentifier,
248 ) -> Result<Option<RawChunk<Event, Gap>>, Self::Error> {
249 self.0
250 .load_previous_chunk(linked_chunk_id, before_chunk_identifier)
251 .await
252 .map_err(Into::into)
253 }
254
255 async fn clear_all_linked_chunks(&self) -> Result<(), Self::Error> {
256 self.0.clear_all_linked_chunks().await.map_err(Into::into)
257 }
258
259 async fn filter_duplicated_events(
260 &self,
261 linked_chunk_id: LinkedChunkId<'_>,
262 events: Vec<OwnedEventId>,
263 ) -> Result<Vec<(OwnedEventId, Position)>, Self::Error> {
264 self.0.filter_duplicated_events(linked_chunk_id, events).await.map_err(Into::into)
265 }
266
267 async fn find_event(
268 &self,
269 room_id: &RoomId,
270 event_id: &EventId,
271 ) -> Result<Option<Event>, Self::Error> {
272 self.0.find_event(room_id, event_id).await.map_err(Into::into)
273 }
274
275 async fn find_event_relations(
276 &self,
277 room_id: &RoomId,
278 event_id: &EventId,
279 filter: Option<&[RelationType]>,
280 ) -> Result<Vec<(Event, Option<Position>)>, Self::Error> {
281 self.0.find_event_relations(room_id, event_id, filter).await.map_err(Into::into)
282 }
283
284 async fn get_room_events(
285 &self,
286 room_id: &RoomId,
287 event_type: Option<&str>,
288 session_id: Option<&str>,
289 ) -> Result<Vec<Event>, Self::Error> {
290 self.0.get_room_events(room_id, event_type, session_id).await.map_err(Into::into)
291 }
292
293 async fn save_event(&self, room_id: &RoomId, event: Event) -> Result<(), Self::Error> {
294 self.0.save_event(room_id, event).await.map_err(Into::into)
295 }
296
297 async fn optimize(&self) -> Result<(), Self::Error> {
298 self.0.optimize().await.map_err(Into::into)?;
299 Ok(())
300 }
301
302 async fn get_size(&self) -> Result<Option<usize>, Self::Error> {
303 Ok(self.0.get_size().await.map_err(Into::into)?)
304 }
305}
306
307pub type DynEventCacheStore = dyn EventCacheStore<Error = EventCacheStoreError>;
309
310pub trait IntoEventCacheStore {
316 #[doc(hidden)]
317 fn into_event_cache_store(self) -> Arc<DynEventCacheStore>;
318}
319
320impl IntoEventCacheStore for Arc<DynEventCacheStore> {
321 fn into_event_cache_store(self) -> Arc<DynEventCacheStore> {
322 self
323 }
324}
325
326impl<T> IntoEventCacheStore for T
327where
328 T: EventCacheStore + Sized + 'static,
329{
330 fn into_event_cache_store(self) -> Arc<DynEventCacheStore> {
331 Arc::new(EraseEventCacheStoreError(self))
332 }
333}
334
335impl<T> IntoEventCacheStore for Arc<T>
338where
339 T: EventCacheStore + 'static,
340{
341 fn into_event_cache_store(self) -> Arc<DynEventCacheStore> {
342 let ptr: *const T = Arc::into_raw(self);
343 let ptr_erased = ptr as *const EraseEventCacheStoreError<T>;
344 unsafe { Arc::from_raw(ptr_erased) }
347 }
348}