1use std::{fmt, sync::Arc};
16
17use async_trait::async_trait;
18use matrix_sdk_common::{
19 linked_chunk::{ChunkIdentifier, ChunkIdentifierGenerator, Position, RawChunk, Update},
20 AsyncTraitDeps,
21};
22use ruma::{events::relation::RelationType, EventId, MxcUri, OwnedEventId, RoomId};
23
24use super::{
25 media::{IgnoreMediaRetentionPolicy, MediaRetentionPolicy},
26 EventCacheStoreError,
27};
28use crate::{
29 event_cache::{Event, Gap},
30 media::MediaRequestParameters,
31};
32
33pub const DEFAULT_CHUNK_CAPACITY: usize = 128;
37
38#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
41#[cfg_attr(not(target_arch = "wasm32"), 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<bool, Self::Error>;
53
54 async fn handle_linked_chunk_updates(
58 &self,
59 room_id: &RoomId,
60 updates: Vec<Update<Event, Gap>>,
61 ) -> Result<(), Self::Error>;
62
63 async fn remove_room(&self, room_id: &RoomId) -> Result<(), Self::Error> {
65 self.handle_linked_chunk_updates(room_id, vec![Update::Clear]).await
68 }
69
70 #[doc(hidden)]
73 async fn load_all_chunks(
74 &self,
75 room_id: &RoomId,
76 ) -> Result<Vec<RawChunk<Event, Gap>>, Self::Error>;
77
78 async fn load_last_chunk(
83 &self,
84 room_id: &RoomId,
85 ) -> Result<(Option<RawChunk<Event, Gap>>, ChunkIdentifierGenerator), Self::Error>;
86
87 async fn load_previous_chunk(
93 &self,
94 room_id: &RoomId,
95 before_chunk_identifier: ChunkIdentifier,
96 ) -> Result<Option<RawChunk<Event, Gap>>, Self::Error>;
97
98 async fn clear_all_rooms_chunks(&self) -> Result<(), Self::Error>;
109
110 async fn filter_duplicated_events(
113 &self,
114 room_id: &RoomId,
115 events: Vec<OwnedEventId>,
116 ) -> Result<Vec<(OwnedEventId, Position)>, Self::Error>;
117
118 async fn find_event(
120 &self,
121 room_id: &RoomId,
122 event_id: &EventId,
123 ) -> Result<Option<Event>, Self::Error>;
124
125 async fn find_event_relations(
130 &self,
131 room_id: &RoomId,
132 event_id: &EventId,
133 filter: Option<&[RelationType]>,
134 ) -> Result<Vec<Event>, Self::Error>;
135
136 async fn save_event(&self, room_id: &RoomId, event: Event) -> Result<(), Self::Error>;
145
146 async fn add_media_content(
154 &self,
155 request: &MediaRequestParameters,
156 content: Vec<u8>,
157 ignore_policy: IgnoreMediaRetentionPolicy,
158 ) -> Result<(), Self::Error>;
159
160 async fn replace_media_key(
180 &self,
181 from: &MediaRequestParameters,
182 to: &MediaRequestParameters,
183 ) -> Result<(), Self::Error>;
184
185 async fn get_media_content(
191 &self,
192 request: &MediaRequestParameters,
193 ) -> Result<Option<Vec<u8>>, Self::Error>;
194
195 async fn remove_media_content(
201 &self,
202 request: &MediaRequestParameters,
203 ) -> Result<(), Self::Error>;
204
205 async fn get_media_content_for_uri(&self, uri: &MxcUri)
220 -> Result<Option<Vec<u8>>, Self::Error>;
221
222 async fn remove_media_content_for_uri(&self, uri: &MxcUri) -> Result<(), Self::Error>;
232
233 async fn set_media_retention_policy(
240 &self,
241 policy: MediaRetentionPolicy,
242 ) -> Result<(), Self::Error>;
243
244 fn media_retention_policy(&self) -> MediaRetentionPolicy;
246
247 async fn set_ignore_media_retention_policy(
259 &self,
260 request: &MediaRequestParameters,
261 ignore_policy: IgnoreMediaRetentionPolicy,
262 ) -> Result<(), Self::Error>;
263
264 async fn clean_up_media_cache(&self) -> Result<(), Self::Error>;
268}
269
270#[repr(transparent)]
271struct EraseEventCacheStoreError<T>(T);
272
273#[cfg(not(tarpaulin_include))]
274impl<T: fmt::Debug> fmt::Debug for EraseEventCacheStoreError<T> {
275 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
276 self.0.fmt(f)
277 }
278}
279
280#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
281#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
282impl<T: EventCacheStore> EventCacheStore for EraseEventCacheStoreError<T> {
283 type Error = EventCacheStoreError;
284
285 async fn try_take_leased_lock(
286 &self,
287 lease_duration_ms: u32,
288 key: &str,
289 holder: &str,
290 ) -> Result<bool, Self::Error> {
291 self.0.try_take_leased_lock(lease_duration_ms, key, holder).await.map_err(Into::into)
292 }
293
294 async fn handle_linked_chunk_updates(
295 &self,
296 room_id: &RoomId,
297 updates: Vec<Update<Event, Gap>>,
298 ) -> Result<(), Self::Error> {
299 self.0.handle_linked_chunk_updates(room_id, updates).await.map_err(Into::into)
300 }
301
302 async fn load_all_chunks(
303 &self,
304 room_id: &RoomId,
305 ) -> Result<Vec<RawChunk<Event, Gap>>, Self::Error> {
306 self.0.load_all_chunks(room_id).await.map_err(Into::into)
307 }
308
309 async fn load_last_chunk(
310 &self,
311 room_id: &RoomId,
312 ) -> Result<(Option<RawChunk<Event, Gap>>, ChunkIdentifierGenerator), Self::Error> {
313 self.0.load_last_chunk(room_id).await.map_err(Into::into)
314 }
315
316 async fn load_previous_chunk(
317 &self,
318 room_id: &RoomId,
319 before_chunk_identifier: ChunkIdentifier,
320 ) -> Result<Option<RawChunk<Event, Gap>>, Self::Error> {
321 self.0.load_previous_chunk(room_id, before_chunk_identifier).await.map_err(Into::into)
322 }
323
324 async fn clear_all_rooms_chunks(&self) -> Result<(), Self::Error> {
325 self.0.clear_all_rooms_chunks().await.map_err(Into::into)
326 }
327
328 async fn filter_duplicated_events(
329 &self,
330 room_id: &RoomId,
331 events: Vec<OwnedEventId>,
332 ) -> Result<Vec<(OwnedEventId, Position)>, Self::Error> {
333 self.0.filter_duplicated_events(room_id, events).await.map_err(Into::into)
334 }
335
336 async fn find_event(
337 &self,
338 room_id: &RoomId,
339 event_id: &EventId,
340 ) -> Result<Option<Event>, Self::Error> {
341 self.0.find_event(room_id, event_id).await.map_err(Into::into)
342 }
343
344 async fn find_event_relations(
345 &self,
346 room_id: &RoomId,
347 event_id: &EventId,
348 filter: Option<&[RelationType]>,
349 ) -> Result<Vec<Event>, Self::Error> {
350 self.0.find_event_relations(room_id, event_id, filter).await.map_err(Into::into)
351 }
352
353 async fn save_event(&self, room_id: &RoomId, event: Event) -> Result<(), Self::Error> {
354 self.0.save_event(room_id, event).await.map_err(Into::into)
355 }
356
357 async fn add_media_content(
358 &self,
359 request: &MediaRequestParameters,
360 content: Vec<u8>,
361 ignore_policy: IgnoreMediaRetentionPolicy,
362 ) -> Result<(), Self::Error> {
363 self.0.add_media_content(request, content, ignore_policy).await.map_err(Into::into)
364 }
365
366 async fn replace_media_key(
367 &self,
368 from: &MediaRequestParameters,
369 to: &MediaRequestParameters,
370 ) -> Result<(), Self::Error> {
371 self.0.replace_media_key(from, to).await.map_err(Into::into)
372 }
373
374 async fn get_media_content(
375 &self,
376 request: &MediaRequestParameters,
377 ) -> Result<Option<Vec<u8>>, Self::Error> {
378 self.0.get_media_content(request).await.map_err(Into::into)
379 }
380
381 async fn remove_media_content(
382 &self,
383 request: &MediaRequestParameters,
384 ) -> Result<(), Self::Error> {
385 self.0.remove_media_content(request).await.map_err(Into::into)
386 }
387
388 async fn get_media_content_for_uri(
389 &self,
390 uri: &MxcUri,
391 ) -> Result<Option<Vec<u8>>, Self::Error> {
392 self.0.get_media_content_for_uri(uri).await.map_err(Into::into)
393 }
394
395 async fn remove_media_content_for_uri(&self, uri: &MxcUri) -> Result<(), Self::Error> {
396 self.0.remove_media_content_for_uri(uri).await.map_err(Into::into)
397 }
398
399 async fn set_media_retention_policy(
400 &self,
401 policy: MediaRetentionPolicy,
402 ) -> Result<(), Self::Error> {
403 self.0.set_media_retention_policy(policy).await.map_err(Into::into)
404 }
405
406 fn media_retention_policy(&self) -> MediaRetentionPolicy {
407 self.0.media_retention_policy()
408 }
409
410 async fn set_ignore_media_retention_policy(
411 &self,
412 request: &MediaRequestParameters,
413 ignore_policy: IgnoreMediaRetentionPolicy,
414 ) -> Result<(), Self::Error> {
415 self.0.set_ignore_media_retention_policy(request, ignore_policy).await.map_err(Into::into)
416 }
417
418 async fn clean_up_media_cache(&self) -> Result<(), Self::Error> {
419 self.0.clean_up_media_cache().await.map_err(Into::into)
420 }
421}
422
423pub type DynEventCacheStore = dyn EventCacheStore<Error = EventCacheStoreError>;
425
426pub trait IntoEventCacheStore {
432 #[doc(hidden)]
433 fn into_event_cache_store(self) -> Arc<DynEventCacheStore>;
434}
435
436impl<T> IntoEventCacheStore for T
437where
438 T: EventCacheStore + Sized + 'static,
439{
440 fn into_event_cache_store(self) -> Arc<DynEventCacheStore> {
441 Arc::new(EraseEventCacheStoreError(self))
442 }
443}
444
445impl<T> IntoEventCacheStore for Arc<T>
448where
449 T: EventCacheStore + 'static,
450{
451 fn into_event_cache_store(self) -> Arc<DynEventCacheStore> {
452 let ptr: *const T = Arc::into_raw(self);
453 let ptr_erased = ptr as *const EraseEventCacheStoreError<T>;
454 unsafe { Arc::from_raw(ptr_erased) }
457 }
458}