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
180#[repr(transparent)]
181struct EraseEventCacheStoreError<T>(T);
182
183#[cfg(not(tarpaulin_include))]
184impl<T: fmt::Debug> fmt::Debug for EraseEventCacheStoreError<T> {
185 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
186 self.0.fmt(f)
187 }
188}
189
190#[cfg_attr(target_family = "wasm", async_trait(?Send))]
191#[cfg_attr(not(target_family = "wasm"), async_trait)]
192impl<T: EventCacheStore> EventCacheStore for EraseEventCacheStoreError<T> {
193 type Error = EventCacheStoreError;
194
195 async fn try_take_leased_lock(
196 &self,
197 lease_duration_ms: u32,
198 key: &str,
199 holder: &str,
200 ) -> Result<Option<CrossProcessLockGeneration>, Self::Error> {
201 self.0.try_take_leased_lock(lease_duration_ms, key, holder).await.map_err(Into::into)
202 }
203
204 async fn handle_linked_chunk_updates(
205 &self,
206 linked_chunk_id: LinkedChunkId<'_>,
207 updates: Vec<Update<Event, Gap>>,
208 ) -> Result<(), Self::Error> {
209 self.0.handle_linked_chunk_updates(linked_chunk_id, updates).await.map_err(Into::into)
210 }
211
212 async fn load_all_chunks(
213 &self,
214 linked_chunk_id: LinkedChunkId<'_>,
215 ) -> Result<Vec<RawChunk<Event, Gap>>, Self::Error> {
216 self.0.load_all_chunks(linked_chunk_id).await.map_err(Into::into)
217 }
218
219 async fn load_all_chunks_metadata(
220 &self,
221 linked_chunk_id: LinkedChunkId<'_>,
222 ) -> Result<Vec<ChunkMetadata>, Self::Error> {
223 self.0.load_all_chunks_metadata(linked_chunk_id).await.map_err(Into::into)
224 }
225
226 async fn load_last_chunk(
227 &self,
228 linked_chunk_id: LinkedChunkId<'_>,
229 ) -> Result<(Option<RawChunk<Event, Gap>>, ChunkIdentifierGenerator), Self::Error> {
230 self.0.load_last_chunk(linked_chunk_id).await.map_err(Into::into)
231 }
232
233 async fn load_previous_chunk(
234 &self,
235 linked_chunk_id: LinkedChunkId<'_>,
236 before_chunk_identifier: ChunkIdentifier,
237 ) -> Result<Option<RawChunk<Event, Gap>>, Self::Error> {
238 self.0
239 .load_previous_chunk(linked_chunk_id, before_chunk_identifier)
240 .await
241 .map_err(Into::into)
242 }
243
244 async fn clear_all_linked_chunks(&self) -> Result<(), Self::Error> {
245 self.0.clear_all_linked_chunks().await.map_err(Into::into)
246 }
247
248 async fn filter_duplicated_events(
249 &self,
250 linked_chunk_id: LinkedChunkId<'_>,
251 events: Vec<OwnedEventId>,
252 ) -> Result<Vec<(OwnedEventId, Position)>, Self::Error> {
253 self.0.filter_duplicated_events(linked_chunk_id, events).await.map_err(Into::into)
254 }
255
256 async fn find_event(
257 &self,
258 room_id: &RoomId,
259 event_id: &EventId,
260 ) -> Result<Option<Event>, Self::Error> {
261 self.0.find_event(room_id, event_id).await.map_err(Into::into)
262 }
263
264 async fn find_event_relations(
265 &self,
266 room_id: &RoomId,
267 event_id: &EventId,
268 filter: Option<&[RelationType]>,
269 ) -> Result<Vec<(Event, Option<Position>)>, Self::Error> {
270 self.0.find_event_relations(room_id, event_id, filter).await.map_err(Into::into)
271 }
272
273 async fn get_room_events(
274 &self,
275 room_id: &RoomId,
276 event_type: Option<&str>,
277 session_id: Option<&str>,
278 ) -> Result<Vec<Event>, Self::Error> {
279 self.0.get_room_events(room_id, event_type, session_id).await.map_err(Into::into)
280 }
281
282 async fn save_event(&self, room_id: &RoomId, event: Event) -> Result<(), Self::Error> {
283 self.0.save_event(room_id, event).await.map_err(Into::into)
284 }
285}
286
287pub type DynEventCacheStore = dyn EventCacheStore<Error = EventCacheStoreError>;
289
290pub trait IntoEventCacheStore {
296 #[doc(hidden)]
297 fn into_event_cache_store(self) -> Arc<DynEventCacheStore>;
298}
299
300impl IntoEventCacheStore for Arc<DynEventCacheStore> {
301 fn into_event_cache_store(self) -> Arc<DynEventCacheStore> {
302 self
303 }
304}
305
306impl<T> IntoEventCacheStore for T
307where
308 T: EventCacheStore + Sized + 'static,
309{
310 fn into_event_cache_store(self) -> Arc<DynEventCacheStore> {
311 Arc::new(EraseEventCacheStoreError(self))
312 }
313}
314
315impl<T> IntoEventCacheStore for Arc<T>
318where
319 T: EventCacheStore + 'static,
320{
321 fn into_event_cache_store(self) -> Arc<DynEventCacheStore> {
322 let ptr: *const T = Arc::into_raw(self);
323 let ptr_erased = ptr as *const EraseEventCacheStoreError<T>;
324 unsafe { Arc::from_raw(ptr_erased) }
327 }
328}