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 #[doc(hidden)]
64 async fn load_all_chunks(
65 &self,
66 linked_chunk_id: LinkedChunkId<'_>,
67 ) -> Result<Vec<RawChunk<Event, Gap>>, Self::Error>;
68
69 async fn load_all_chunks_metadata(
74 &self,
75 linked_chunk_id: LinkedChunkId<'_>,
76 ) -> Result<Vec<ChunkMetadata>, Self::Error>;
77
78 async fn load_last_chunk(
83 &self,
84 linked_chunk_id: LinkedChunkId<'_>,
85 ) -> Result<(Option<RawChunk<Event, Gap>>, ChunkIdentifierGenerator), Self::Error>;
86
87 async fn load_previous_chunk(
93 &self,
94 linked_chunk_id: LinkedChunkId<'_>,
95 before_chunk_identifier: ChunkIdentifier,
96 ) -> Result<Option<RawChunk<Event, Gap>>, Self::Error>;
97
98 async fn remember_thread(
106 &self,
107 room_id: &RoomId,
108 thread_id: &EventId,
109 ) -> Result<(), Self::Error>;
110
111 async fn clear_all_events(&self, room_id: Option<&RoomId>) -> Result<(), Self::Error>;
122
123 async fn filter_duplicated_events(
126 &self,
127 linked_chunk_id: LinkedChunkId<'_>,
128 events: Vec<OwnedEventId>,
129 ) -> Result<Vec<(OwnedEventId, Position)>, Self::Error>;
130
131 async fn find_event(
136 &self,
137 room_id: &RoomId,
138 event_id: &EventId,
139 ) -> Result<Option<Event>, Self::Error>;
140
141 async fn find_event_relations(
158 &self,
159 room_id: &RoomId,
160 event_id: &EventId,
161 filter: Option<&[RelationType]>,
162 ) -> Result<Vec<(Event, Option<Position>)>, Self::Error>;
163
164 async fn get_room_events(
169 &self,
170 room_id: &RoomId,
171 event_type: Option<&str>,
172 session_id: Option<&str>,
173 ) -> Result<Vec<Event>, Self::Error>;
174
175 async fn save_event(&self, room_id: &RoomId, event: Event) -> Result<(), Self::Error>;
184
185 async fn close(&self) -> Result<(), Self::Error>;
191
192 async fn reopen(&self) -> Result<(), Self::Error>;
195
196 #[doc(hidden)]
202 async fn optimize(&self) -> Result<(), Self::Error>;
203
204 async fn get_size(&self) -> Result<Option<usize>, Self::Error>;
206}
207
208#[repr(transparent)]
209struct EraseEventCacheStoreError<T>(T);
210
211#[cfg(not(tarpaulin_include))]
212impl<T: fmt::Debug> fmt::Debug for EraseEventCacheStoreError<T> {
213 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
214 self.0.fmt(f)
215 }
216}
217
218#[cfg_attr(target_family = "wasm", async_trait(?Send))]
219#[cfg_attr(not(target_family = "wasm"), async_trait)]
220impl<T: EventCacheStore> EventCacheStore for EraseEventCacheStoreError<T> {
221 type Error = EventCacheStoreError;
222
223 async fn try_take_leased_lock(
224 &self,
225 lease_duration_ms: u32,
226 key: &str,
227 holder: &str,
228 ) -> Result<Option<CrossProcessLockGeneration>, Self::Error> {
229 self.0.try_take_leased_lock(lease_duration_ms, key, holder).await.map_err(Into::into)
230 }
231
232 async fn handle_linked_chunk_updates(
233 &self,
234 linked_chunk_id: LinkedChunkId<'_>,
235 updates: Vec<Update<Event, Gap>>,
236 ) -> Result<(), Self::Error> {
237 self.0.handle_linked_chunk_updates(linked_chunk_id, updates).await.map_err(Into::into)
238 }
239
240 async fn load_all_chunks(
241 &self,
242 linked_chunk_id: LinkedChunkId<'_>,
243 ) -> Result<Vec<RawChunk<Event, Gap>>, Self::Error> {
244 self.0.load_all_chunks(linked_chunk_id).await.map_err(Into::into)
245 }
246
247 async fn load_all_chunks_metadata(
248 &self,
249 linked_chunk_id: LinkedChunkId<'_>,
250 ) -> Result<Vec<ChunkMetadata>, Self::Error> {
251 self.0.load_all_chunks_metadata(linked_chunk_id).await.map_err(Into::into)
252 }
253
254 async fn load_last_chunk(
255 &self,
256 linked_chunk_id: LinkedChunkId<'_>,
257 ) -> Result<(Option<RawChunk<Event, Gap>>, ChunkIdentifierGenerator), Self::Error> {
258 self.0.load_last_chunk(linked_chunk_id).await.map_err(Into::into)
259 }
260
261 async fn load_previous_chunk(
262 &self,
263 linked_chunk_id: LinkedChunkId<'_>,
264 before_chunk_identifier: ChunkIdentifier,
265 ) -> Result<Option<RawChunk<Event, Gap>>, Self::Error> {
266 self.0
267 .load_previous_chunk(linked_chunk_id, before_chunk_identifier)
268 .await
269 .map_err(Into::into)
270 }
271
272 async fn remember_thread(
273 &self,
274 room_id: &RoomId,
275 thread_id: &EventId,
276 ) -> Result<(), Self::Error> {
277 self.0.remember_thread(room_id, thread_id).await.map_err(Into::into)
278 }
279
280 async fn clear_all_events(&self, room_id: Option<&RoomId>) -> Result<(), Self::Error> {
281 self.0.clear_all_events(room_id).await.map_err(Into::into)
282 }
283
284 async fn filter_duplicated_events(
285 &self,
286 linked_chunk_id: LinkedChunkId<'_>,
287 events: Vec<OwnedEventId>,
288 ) -> Result<Vec<(OwnedEventId, Position)>, Self::Error> {
289 self.0.filter_duplicated_events(linked_chunk_id, events).await.map_err(Into::into)
290 }
291
292 async fn find_event(
293 &self,
294 room_id: &RoomId,
295 event_id: &EventId,
296 ) -> Result<Option<Event>, Self::Error> {
297 self.0.find_event(room_id, event_id).await.map_err(Into::into)
298 }
299
300 async fn find_event_relations(
301 &self,
302 room_id: &RoomId,
303 event_id: &EventId,
304 filter: Option<&[RelationType]>,
305 ) -> Result<Vec<(Event, Option<Position>)>, Self::Error> {
306 self.0.find_event_relations(room_id, event_id, filter).await.map_err(Into::into)
307 }
308
309 async fn get_room_events(
310 &self,
311 room_id: &RoomId,
312 event_type: Option<&str>,
313 session_id: Option<&str>,
314 ) -> Result<Vec<Event>, Self::Error> {
315 self.0.get_room_events(room_id, event_type, session_id).await.map_err(Into::into)
316 }
317
318 async fn save_event(&self, room_id: &RoomId, event: Event) -> Result<(), Self::Error> {
319 self.0.save_event(room_id, event).await.map_err(Into::into)
320 }
321
322 async fn close(&self) -> Result<(), Self::Error> {
323 self.0.close().await.map_err(Into::into)
324 }
325
326 async fn reopen(&self) -> Result<(), Self::Error> {
327 self.0.reopen().await.map_err(Into::into)
328 }
329
330 async fn optimize(&self) -> Result<(), Self::Error> {
331 self.0.optimize().await.map_err(Into::into)?;
332 Ok(())
333 }
334
335 async fn get_size(&self) -> Result<Option<usize>, Self::Error> {
336 Ok(self.0.get_size().await.map_err(Into::into)?)
337 }
338}
339
340pub type DynEventCacheStore = dyn EventCacheStore<Error = EventCacheStoreError>;
342
343pub trait IntoEventCacheStore {
349 #[doc(hidden)]
350 fn into_event_cache_store(self) -> Arc<DynEventCacheStore>;
351}
352
353impl IntoEventCacheStore for Arc<DynEventCacheStore> {
354 fn into_event_cache_store(self) -> Arc<DynEventCacheStore> {
355 self
356 }
357}
358
359impl<T> IntoEventCacheStore for T
360where
361 T: EventCacheStore + Sized + 'static,
362{
363 fn into_event_cache_store(self) -> Arc<DynEventCacheStore> {
364 Arc::new(EraseEventCacheStoreError(self))
365 }
366}
367
368impl<T> IntoEventCacheStore for Arc<T>
371where
372 T: EventCacheStore + 'static,
373{
374 fn into_event_cache_store(self) -> Arc<DynEventCacheStore> {
375 let ptr: *const T = Arc::into_raw(self);
376 let ptr_erased = ptr as *const EraseEventCacheStoreError<T>;
377 unsafe { Arc::from_raw(ptr_erased) }
380 }
381}