1use 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::{
29 super::{Event, Gap, thread::ThreadInfo},
30 EventCacheStoreError,
31};
32
33pub const DEFAULT_CHUNK_CAPACITY: usize = 128;
37
38#[cfg_attr(target_family = "wasm", async_trait(?Send))]
41#[cfg_attr(not(target_family = "wasm"), async_trait)]
42pub trait EventCacheStore: AsyncTraitDeps {
43 type Error: fmt::Debug + Into<EventCacheStoreError>;
45
46 async fn try_take_leased_lock(
48 &self,
49 lease_duration_ms: u32,
50 key: &str,
51 holder: &str,
52 ) -> Result<Option<CrossProcessLockGeneration>, Self::Error>;
53
54 async fn handle_linked_chunk_updates(
58 &self,
59 linked_chunk_id: LinkedChunkId<'_>,
60 updates: Vec<Update<Event, Gap>>,
61 ) -> Result<(), Self::Error>;
62
63 #[doc(hidden)]
66 async fn load_all_chunks(
67 &self,
68 linked_chunk_id: LinkedChunkId<'_>,
69 ) -> Result<Vec<RawChunk<Event, Gap>>, Self::Error>;
70
71 async fn load_all_chunks_metadata(
76 &self,
77 linked_chunk_id: LinkedChunkId<'_>,
78 ) -> Result<Vec<ChunkMetadata>, Self::Error>;
79
80 async fn load_last_chunk(
85 &self,
86 linked_chunk_id: LinkedChunkId<'_>,
87 ) -> Result<(Option<RawChunk<Event, Gap>>, ChunkIdentifierGenerator), Self::Error>;
88
89 async fn load_previous_chunk(
95 &self,
96 linked_chunk_id: LinkedChunkId<'_>,
97 before_chunk_identifier: ChunkIdentifier,
98 ) -> Result<Option<RawChunk<Event, Gap>>, Self::Error>;
99
100 async fn load_thread_info(
111 &self,
112 room_id: &RoomId,
113 thread_id: &EventId,
114 insert_default_if_missing: bool,
115 ) -> Result<Option<ThreadInfo>, Self::Error>;
116
117 async fn update_thread_info(
123 &self,
124 room_id: &RoomId,
125 thread_id: &EventId,
126 thread_info: &ThreadInfo,
127 ) -> Result<(), Self::Error>;
128
129 async fn clear_all_events(&self, room_id: Option<&RoomId>) -> Result<(), Self::Error>;
140
141 async fn filter_duplicated_events(
144 &self,
145 linked_chunk_id: LinkedChunkId<'_>,
146 events: Vec<OwnedEventId>,
147 ) -> Result<Vec<(OwnedEventId, Position)>, Self::Error>;
148
149 async fn find_event(
154 &self,
155 room_id: &RoomId,
156 event_id: &EventId,
157 ) -> Result<Option<Event>, Self::Error>;
158
159 async fn find_event_relations(
176 &self,
177 room_id: &RoomId,
178 event_id: &EventId,
179 filter: Option<&[RelationType]>,
180 ) -> Result<Vec<(Event, Option<Position>)>, Self::Error>;
181
182 async fn find_events_before_timestamp(
188 &self,
189 room_id: &RoomId,
190 cutoff_ms: u64,
191 ) -> Result<Vec<Event>, Self::Error>;
192
193 async fn get_room_events(
198 &self,
199 room_id: &RoomId,
200 event_type: Option<&str>,
201 session_id: Option<&str>,
202 ) -> Result<Vec<Event>, Self::Error>;
203
204 async fn save_event(&self, room_id: &RoomId, event: Event) -> Result<(), Self::Error>;
213
214 async fn close(&self) -> Result<(), Self::Error>;
220
221 async fn reopen(&self) -> Result<(), Self::Error>;
224
225 #[doc(hidden)]
231 async fn optimize(&self) -> Result<(), Self::Error>;
232
233 async fn get_size(&self) -> Result<Option<usize>, Self::Error>;
235}
236
237#[repr(transparent)]
238struct EraseEventCacheStoreError<T>(T);
239
240#[cfg(not(tarpaulin_include))]
241impl<T: fmt::Debug> fmt::Debug for EraseEventCacheStoreError<T> {
242 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
243 self.0.fmt(f)
244 }
245}
246
247#[cfg_attr(target_family = "wasm", async_trait(?Send))]
248#[cfg_attr(not(target_family = "wasm"), async_trait)]
249impl<T: EventCacheStore> EventCacheStore for EraseEventCacheStoreError<T> {
250 type Error = EventCacheStoreError;
251
252 async fn try_take_leased_lock(
253 &self,
254 lease_duration_ms: u32,
255 key: &str,
256 holder: &str,
257 ) -> Result<Option<CrossProcessLockGeneration>, Self::Error> {
258 self.0.try_take_leased_lock(lease_duration_ms, key, holder).await.map_err(Into::into)
259 }
260
261 async fn handle_linked_chunk_updates(
262 &self,
263 linked_chunk_id: LinkedChunkId<'_>,
264 updates: Vec<Update<Event, Gap>>,
265 ) -> Result<(), Self::Error> {
266 self.0.handle_linked_chunk_updates(linked_chunk_id, updates).await.map_err(Into::into)
267 }
268
269 async fn load_all_chunks(
270 &self,
271 linked_chunk_id: LinkedChunkId<'_>,
272 ) -> Result<Vec<RawChunk<Event, Gap>>, Self::Error> {
273 self.0.load_all_chunks(linked_chunk_id).await.map_err(Into::into)
274 }
275
276 async fn load_all_chunks_metadata(
277 &self,
278 linked_chunk_id: LinkedChunkId<'_>,
279 ) -> Result<Vec<ChunkMetadata>, Self::Error> {
280 self.0.load_all_chunks_metadata(linked_chunk_id).await.map_err(Into::into)
281 }
282
283 async fn load_last_chunk(
284 &self,
285 linked_chunk_id: LinkedChunkId<'_>,
286 ) -> Result<(Option<RawChunk<Event, Gap>>, ChunkIdentifierGenerator), Self::Error> {
287 self.0.load_last_chunk(linked_chunk_id).await.map_err(Into::into)
288 }
289
290 async fn load_previous_chunk(
291 &self,
292 linked_chunk_id: LinkedChunkId<'_>,
293 before_chunk_identifier: ChunkIdentifier,
294 ) -> Result<Option<RawChunk<Event, Gap>>, Self::Error> {
295 self.0
296 .load_previous_chunk(linked_chunk_id, before_chunk_identifier)
297 .await
298 .map_err(Into::into)
299 }
300
301 async fn load_thread_info(
302 &self,
303 room_id: &RoomId,
304 thread_id: &EventId,
305 insert_default_if_missing: bool,
306 ) -> Result<Option<ThreadInfo>, Self::Error> {
307 self.0
308 .load_thread_info(room_id, thread_id, insert_default_if_missing)
309 .await
310 .map_err(Into::into)
311 }
312
313 async fn update_thread_info(
314 &self,
315 room_id: &RoomId,
316 thread_id: &EventId,
317 thread_info: &ThreadInfo,
318 ) -> Result<(), Self::Error> {
319 self.0.update_thread_info(room_id, thread_id, thread_info).await.map_err(Into::into)
320 }
321
322 async fn clear_all_events(&self, room_id: Option<&RoomId>) -> Result<(), Self::Error> {
323 self.0.clear_all_events(room_id).await.map_err(Into::into)
324 }
325
326 async fn filter_duplicated_events(
327 &self,
328 linked_chunk_id: LinkedChunkId<'_>,
329 events: Vec<OwnedEventId>,
330 ) -> Result<Vec<(OwnedEventId, Position)>, Self::Error> {
331 self.0.filter_duplicated_events(linked_chunk_id, events).await.map_err(Into::into)
332 }
333
334 async fn find_event(
335 &self,
336 room_id: &RoomId,
337 event_id: &EventId,
338 ) -> Result<Option<Event>, Self::Error> {
339 self.0.find_event(room_id, event_id).await.map_err(Into::into)
340 }
341
342 async fn find_event_relations(
343 &self,
344 room_id: &RoomId,
345 event_id: &EventId,
346 filter: Option<&[RelationType]>,
347 ) -> Result<Vec<(Event, Option<Position>)>, Self::Error> {
348 self.0.find_event_relations(room_id, event_id, filter).await.map_err(Into::into)
349 }
350
351 async fn find_events_before_timestamp(
352 &self,
353 room_id: &RoomId,
354 cutoff_ms: u64,
355 ) -> Result<Vec<Event>, Self::Error> {
356 self.0.find_events_before_timestamp(room_id, cutoff_ms).await.map_err(Into::into)
357 }
358
359 async fn get_room_events(
360 &self,
361 room_id: &RoomId,
362 event_type: Option<&str>,
363 session_id: Option<&str>,
364 ) -> Result<Vec<Event>, Self::Error> {
365 self.0.get_room_events(room_id, event_type, session_id).await.map_err(Into::into)
366 }
367
368 async fn save_event(&self, room_id: &RoomId, event: Event) -> Result<(), Self::Error> {
369 self.0.save_event(room_id, event).await.map_err(Into::into)
370 }
371
372 async fn close(&self) -> Result<(), Self::Error> {
373 self.0.close().await.map_err(Into::into)
374 }
375
376 async fn reopen(&self) -> Result<(), Self::Error> {
377 self.0.reopen().await.map_err(Into::into)
378 }
379
380 async fn optimize(&self) -> Result<(), Self::Error> {
381 self.0.optimize().await.map_err(Into::into)?;
382 Ok(())
383 }
384
385 async fn get_size(&self) -> Result<Option<usize>, Self::Error> {
386 Ok(self.0.get_size().await.map_err(Into::into)?)
387 }
388}
389
390pub type DynEventCacheStore = dyn EventCacheStore<Error = EventCacheStoreError>;
392
393pub trait IntoEventCacheStore {
399 #[doc(hidden)]
400 fn into_event_cache_store(self) -> Arc<DynEventCacheStore>;
401}
402
403impl IntoEventCacheStore for Arc<DynEventCacheStore> {
404 fn into_event_cache_store(self) -> Arc<DynEventCacheStore> {
405 self
406 }
407}
408
409impl<T> IntoEventCacheStore for T
410where
411 T: EventCacheStore + Sized + 'static,
412{
413 fn into_event_cache_store(self) -> Arc<DynEventCacheStore> {
414 Arc::new(EraseEventCacheStoreError(self))
415 }
416}
417
418impl<T> IntoEventCacheStore for Arc<T>
421where
422 T: EventCacheStore + 'static,
423{
424 fn into_event_cache_store(self) -> Arc<DynEventCacheStore> {
425 let ptr: *const T = Arc::into_raw(self);
426 let ptr_erased = ptr as *const EraseEventCacheStoreError<T>;
427 unsafe { Arc::from_raw(ptr_erased) }
430 }
431}