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(
109 &self,
110 room_id: &RoomId,
111 thread_id: &EventId,
112 ) -> Result<ThreadInfo, Self::Error>;
113
114 async fn update_thread_info(
120 &self,
121 room_id: &RoomId,
122 thread_id: &EventId,
123 thread_info: &ThreadInfo,
124 ) -> Result<(), Self::Error>;
125
126 async fn clear_all_events(&self, room_id: Option<&RoomId>) -> Result<(), Self::Error>;
137
138 async fn filter_duplicated_events(
141 &self,
142 linked_chunk_id: LinkedChunkId<'_>,
143 events: Vec<OwnedEventId>,
144 ) -> Result<Vec<(OwnedEventId, Position)>, Self::Error>;
145
146 async fn find_event(
151 &self,
152 room_id: &RoomId,
153 event_id: &EventId,
154 ) -> Result<Option<Event>, Self::Error>;
155
156 async fn find_event_relations(
173 &self,
174 room_id: &RoomId,
175 event_id: &EventId,
176 filter: Option<&[RelationType]>,
177 ) -> Result<Vec<(Event, Option<Position>)>, Self::Error>;
178
179 async fn get_room_events(
184 &self,
185 room_id: &RoomId,
186 event_type: Option<&str>,
187 session_id: Option<&str>,
188 ) -> Result<Vec<Event>, Self::Error>;
189
190 async fn save_event(&self, room_id: &RoomId, event: Event) -> Result<(), Self::Error>;
199
200 async fn close(&self) -> Result<(), Self::Error>;
206
207 async fn reopen(&self) -> Result<(), Self::Error>;
210
211 #[doc(hidden)]
217 async fn optimize(&self) -> Result<(), Self::Error>;
218
219 async fn get_size(&self) -> Result<Option<usize>, Self::Error>;
221}
222
223#[repr(transparent)]
224struct EraseEventCacheStoreError<T>(T);
225
226#[cfg(not(tarpaulin_include))]
227impl<T: fmt::Debug> fmt::Debug for EraseEventCacheStoreError<T> {
228 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
229 self.0.fmt(f)
230 }
231}
232
233#[cfg_attr(target_family = "wasm", async_trait(?Send))]
234#[cfg_attr(not(target_family = "wasm"), async_trait)]
235impl<T: EventCacheStore> EventCacheStore for EraseEventCacheStoreError<T> {
236 type Error = EventCacheStoreError;
237
238 async fn try_take_leased_lock(
239 &self,
240 lease_duration_ms: u32,
241 key: &str,
242 holder: &str,
243 ) -> Result<Option<CrossProcessLockGeneration>, Self::Error> {
244 self.0.try_take_leased_lock(lease_duration_ms, key, holder).await.map_err(Into::into)
245 }
246
247 async fn handle_linked_chunk_updates(
248 &self,
249 linked_chunk_id: LinkedChunkId<'_>,
250 updates: Vec<Update<Event, Gap>>,
251 ) -> Result<(), Self::Error> {
252 self.0.handle_linked_chunk_updates(linked_chunk_id, updates).await.map_err(Into::into)
253 }
254
255 async fn load_all_chunks(
256 &self,
257 linked_chunk_id: LinkedChunkId<'_>,
258 ) -> Result<Vec<RawChunk<Event, Gap>>, Self::Error> {
259 self.0.load_all_chunks(linked_chunk_id).await.map_err(Into::into)
260 }
261
262 async fn load_all_chunks_metadata(
263 &self,
264 linked_chunk_id: LinkedChunkId<'_>,
265 ) -> Result<Vec<ChunkMetadata>, Self::Error> {
266 self.0.load_all_chunks_metadata(linked_chunk_id).await.map_err(Into::into)
267 }
268
269 async fn load_last_chunk(
270 &self,
271 linked_chunk_id: LinkedChunkId<'_>,
272 ) -> Result<(Option<RawChunk<Event, Gap>>, ChunkIdentifierGenerator), Self::Error> {
273 self.0.load_last_chunk(linked_chunk_id).await.map_err(Into::into)
274 }
275
276 async fn load_previous_chunk(
277 &self,
278 linked_chunk_id: LinkedChunkId<'_>,
279 before_chunk_identifier: ChunkIdentifier,
280 ) -> Result<Option<RawChunk<Event, Gap>>, Self::Error> {
281 self.0
282 .load_previous_chunk(linked_chunk_id, before_chunk_identifier)
283 .await
284 .map_err(Into::into)
285 }
286
287 async fn load_thread_info(
288 &self,
289 room_id: &RoomId,
290 thread_id: &EventId,
291 ) -> Result<ThreadInfo, Self::Error> {
292 self.0.load_thread_info(room_id, thread_id).await.map_err(Into::into)
293 }
294
295 async fn update_thread_info(
296 &self,
297 room_id: &RoomId,
298 thread_id: &EventId,
299 thread_info: &ThreadInfo,
300 ) -> Result<(), Self::Error> {
301 self.0.update_thread_info(room_id, thread_id, thread_info).await.map_err(Into::into)
302 }
303
304 async fn clear_all_events(&self, room_id: Option<&RoomId>) -> Result<(), Self::Error> {
305 self.0.clear_all_events(room_id).await.map_err(Into::into)
306 }
307
308 async fn filter_duplicated_events(
309 &self,
310 linked_chunk_id: LinkedChunkId<'_>,
311 events: Vec<OwnedEventId>,
312 ) -> Result<Vec<(OwnedEventId, Position)>, Self::Error> {
313 self.0.filter_duplicated_events(linked_chunk_id, events).await.map_err(Into::into)
314 }
315
316 async fn find_event(
317 &self,
318 room_id: &RoomId,
319 event_id: &EventId,
320 ) -> Result<Option<Event>, Self::Error> {
321 self.0.find_event(room_id, event_id).await.map_err(Into::into)
322 }
323
324 async fn find_event_relations(
325 &self,
326 room_id: &RoomId,
327 event_id: &EventId,
328 filter: Option<&[RelationType]>,
329 ) -> Result<Vec<(Event, Option<Position>)>, Self::Error> {
330 self.0.find_event_relations(room_id, event_id, filter).await.map_err(Into::into)
331 }
332
333 async fn get_room_events(
334 &self,
335 room_id: &RoomId,
336 event_type: Option<&str>,
337 session_id: Option<&str>,
338 ) -> Result<Vec<Event>, Self::Error> {
339 self.0.get_room_events(room_id, event_type, session_id).await.map_err(Into::into)
340 }
341
342 async fn save_event(&self, room_id: &RoomId, event: Event) -> Result<(), Self::Error> {
343 self.0.save_event(room_id, event).await.map_err(Into::into)
344 }
345
346 async fn close(&self) -> Result<(), Self::Error> {
347 self.0.close().await.map_err(Into::into)
348 }
349
350 async fn reopen(&self) -> Result<(), Self::Error> {
351 self.0.reopen().await.map_err(Into::into)
352 }
353
354 async fn optimize(&self) -> Result<(), Self::Error> {
355 self.0.optimize().await.map_err(Into::into)?;
356 Ok(())
357 }
358
359 async fn get_size(&self) -> Result<Option<usize>, Self::Error> {
360 Ok(self.0.get_size().await.map_err(Into::into)?)
361 }
362}
363
364pub type DynEventCacheStore = dyn EventCacheStore<Error = EventCacheStoreError>;
366
367pub trait IntoEventCacheStore {
373 #[doc(hidden)]
374 fn into_event_cache_store(self) -> Arc<DynEventCacheStore>;
375}
376
377impl IntoEventCacheStore for Arc<DynEventCacheStore> {
378 fn into_event_cache_store(self) -> Arc<DynEventCacheStore> {
379 self
380 }
381}
382
383impl<T> IntoEventCacheStore for T
384where
385 T: EventCacheStore + Sized + 'static,
386{
387 fn into_event_cache_store(self) -> Arc<DynEventCacheStore> {
388 Arc::new(EraseEventCacheStoreError(self))
389 }
390}
391
392impl<T> IntoEventCacheStore for Arc<T>
395where
396 T: EventCacheStore + 'static,
397{
398 fn into_event_cache_store(self) -> Arc<DynEventCacheStore> {
399 let ptr: *const T = Arc::into_raw(self);
400 let ptr_erased = ptr as *const EraseEventCacheStoreError<T>;
401 unsafe { Arc::from_raw(ptr_erased) }
404 }
405}