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 linked_chunk::{
21 ChunkIdentifier, ChunkIdentifierGenerator, ChunkMetadata, LinkedChunkId, Position,
22 RawChunk, Update,
23 },
24};
25use ruma::{EventId, OwnedEventId, RoomId, events::relation::RelationType};
26
27use super::EventCacheStoreError;
28use crate::event_cache::{Event, Gap};
29
30pub const DEFAULT_CHUNK_CAPACITY: usize = 128;
34
35#[cfg_attr(target_family = "wasm", async_trait(?Send))]
38#[cfg_attr(not(target_family = "wasm"), async_trait)]
39pub trait EventCacheStore: AsyncTraitDeps {
40 type Error: fmt::Debug + Into<EventCacheStoreError>;
42
43 async fn try_take_leased_lock(
45 &self,
46 lease_duration_ms: u32,
47 key: &str,
48 holder: &str,
49 ) -> Result<bool, Self::Error>;
50
51 async fn handle_linked_chunk_updates(
55 &self,
56 linked_chunk_id: LinkedChunkId<'_>,
57 updates: Vec<Update<Event, Gap>>,
58 ) -> Result<(), Self::Error>;
59
60 async fn remove_room(&self, room_id: &RoomId) -> Result<(), Self::Error> {
62 self.handle_linked_chunk_updates(LinkedChunkId::Room(room_id), vec![Update::Clear]).await
65 }
66
67 #[doc(hidden)]
70 async fn load_all_chunks(
71 &self,
72 linked_chunk_id: LinkedChunkId<'_>,
73 ) -> Result<Vec<RawChunk<Event, Gap>>, Self::Error>;
74
75 async fn load_all_chunks_metadata(
80 &self,
81 linked_chunk_id: LinkedChunkId<'_>,
82 ) -> Result<Vec<ChunkMetadata>, Self::Error>;
83
84 async fn load_last_chunk(
89 &self,
90 linked_chunk_id: LinkedChunkId<'_>,
91 ) -> Result<(Option<RawChunk<Event, Gap>>, ChunkIdentifierGenerator), Self::Error>;
92
93 async fn load_previous_chunk(
99 &self,
100 linked_chunk_id: LinkedChunkId<'_>,
101 before_chunk_identifier: ChunkIdentifier,
102 ) -> Result<Option<RawChunk<Event, Gap>>, Self::Error>;
103
104 async fn clear_all_linked_chunks(&self) -> Result<(), Self::Error>;
115
116 async fn filter_duplicated_events(
119 &self,
120 linked_chunk_id: LinkedChunkId<'_>,
121 events: Vec<OwnedEventId>,
122 ) -> Result<Vec<(OwnedEventId, Position)>, Self::Error>;
123
124 async fn find_event(
129 &self,
130 room_id: &RoomId,
131 event_id: &EventId,
132 ) -> Result<Option<Event>, Self::Error>;
133
134 async fn find_event_relations(
151 &self,
152 room_id: &RoomId,
153 event_id: &EventId,
154 filter: Option<&[RelationType]>,
155 ) -> Result<Vec<(Event, Option<Position>)>, Self::Error>;
156
157 async fn get_room_events(
162 &self,
163 room_id: &RoomId,
164 event_type: Option<&str>,
165 session_id: Option<&str>,
166 ) -> Result<Vec<Event>, Self::Error>;
167
168 async fn save_event(&self, room_id: &RoomId, event: Event) -> Result<(), Self::Error>;
177}
178
179#[repr(transparent)]
180struct EraseEventCacheStoreError<T>(T);
181
182#[cfg(not(tarpaulin_include))]
183impl<T: fmt::Debug> fmt::Debug for EraseEventCacheStoreError<T> {
184 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
185 self.0.fmt(f)
186 }
187}
188
189#[cfg_attr(target_family = "wasm", async_trait(?Send))]
190#[cfg_attr(not(target_family = "wasm"), async_trait)]
191impl<T: EventCacheStore> EventCacheStore for EraseEventCacheStoreError<T> {
192 type Error = EventCacheStoreError;
193
194 async fn try_take_leased_lock(
195 &self,
196 lease_duration_ms: u32,
197 key: &str,
198 holder: &str,
199 ) -> Result<bool, Self::Error> {
200 self.0.try_take_leased_lock(lease_duration_ms, key, holder).await.map_err(Into::into)
201 }
202
203 async fn handle_linked_chunk_updates(
204 &self,
205 linked_chunk_id: LinkedChunkId<'_>,
206 updates: Vec<Update<Event, Gap>>,
207 ) -> Result<(), Self::Error> {
208 self.0.handle_linked_chunk_updates(linked_chunk_id, updates).await.map_err(Into::into)
209 }
210
211 async fn load_all_chunks(
212 &self,
213 linked_chunk_id: LinkedChunkId<'_>,
214 ) -> Result<Vec<RawChunk<Event, Gap>>, Self::Error> {
215 self.0.load_all_chunks(linked_chunk_id).await.map_err(Into::into)
216 }
217
218 async fn load_all_chunks_metadata(
219 &self,
220 linked_chunk_id: LinkedChunkId<'_>,
221 ) -> Result<Vec<ChunkMetadata>, Self::Error> {
222 self.0.load_all_chunks_metadata(linked_chunk_id).await.map_err(Into::into)
223 }
224
225 async fn load_last_chunk(
226 &self,
227 linked_chunk_id: LinkedChunkId<'_>,
228 ) -> Result<(Option<RawChunk<Event, Gap>>, ChunkIdentifierGenerator), Self::Error> {
229 self.0.load_last_chunk(linked_chunk_id).await.map_err(Into::into)
230 }
231
232 async fn load_previous_chunk(
233 &self,
234 linked_chunk_id: LinkedChunkId<'_>,
235 before_chunk_identifier: ChunkIdentifier,
236 ) -> Result<Option<RawChunk<Event, Gap>>, Self::Error> {
237 self.0
238 .load_previous_chunk(linked_chunk_id, before_chunk_identifier)
239 .await
240 .map_err(Into::into)
241 }
242
243 async fn clear_all_linked_chunks(&self) -> Result<(), Self::Error> {
244 self.0.clear_all_linked_chunks().await.map_err(Into::into)
245 }
246
247 async fn filter_duplicated_events(
248 &self,
249 linked_chunk_id: LinkedChunkId<'_>,
250 events: Vec<OwnedEventId>,
251 ) -> Result<Vec<(OwnedEventId, Position)>, Self::Error> {
252 self.0.filter_duplicated_events(linked_chunk_id, events).await.map_err(Into::into)
253 }
254
255 async fn find_event(
256 &self,
257 room_id: &RoomId,
258 event_id: &EventId,
259 ) -> Result<Option<Event>, Self::Error> {
260 self.0.find_event(room_id, event_id).await.map_err(Into::into)
261 }
262
263 async fn find_event_relations(
264 &self,
265 room_id: &RoomId,
266 event_id: &EventId,
267 filter: Option<&[RelationType]>,
268 ) -> Result<Vec<(Event, Option<Position>)>, Self::Error> {
269 self.0.find_event_relations(room_id, event_id, filter).await.map_err(Into::into)
270 }
271
272 async fn get_room_events(
273 &self,
274 room_id: &RoomId,
275 event_type: Option<&str>,
276 session_id: Option<&str>,
277 ) -> Result<Vec<Event>, Self::Error> {
278 self.0.get_room_events(room_id, event_type, session_id).await.map_err(Into::into)
279 }
280
281 async fn save_event(&self, room_id: &RoomId, event: Event) -> Result<(), Self::Error> {
282 self.0.save_event(room_id, event).await.map_err(Into::into)
283 }
284}
285
286pub type DynEventCacheStore = dyn EventCacheStore<Error = EventCacheStoreError>;
288
289pub trait IntoEventCacheStore {
295 #[doc(hidden)]
296 fn into_event_cache_store(self) -> Arc<DynEventCacheStore>;
297}
298
299impl IntoEventCacheStore for Arc<DynEventCacheStore> {
300 fn into_event_cache_store(self) -> Arc<DynEventCacheStore> {
301 self
302 }
303}
304
305impl<T> IntoEventCacheStore for T
306where
307 T: EventCacheStore + Sized + 'static,
308{
309 fn into_event_cache_store(self) -> Arc<DynEventCacheStore> {
310 Arc::new(EraseEventCacheStoreError(self))
311 }
312}
313
314impl<T> IntoEventCacheStore for Arc<T>
317where
318 T: EventCacheStore + 'static,
319{
320 fn into_event_cache_store(self) -> Arc<DynEventCacheStore> {
321 let ptr: *const T = Arc::into_raw(self);
322 let ptr_erased = ptr as *const EraseEventCacheStoreError<T>;
323 unsafe { Arc::from_raw(ptr_erased) }
326 }
327}