Skip to content

Commit 72f4ce8

Browse files
committed
feat(base): Add EventCacheStore::find_event.
This patch adds the method `find_event` on the `EventCacheStore` trait. It helps to find a single event from the store.
1 parent f3f37a3 commit 72f4ce8

File tree

5 files changed

+154
-10
lines changed

5 files changed

+154
-10
lines changed

crates/matrix-sdk-base/src/event_cache/store/integration_tests.rs

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,9 @@ pub trait EventCacheStoreIntegrationTests {
127127

128128
/// Test that filtering duplicated events works as expected.
129129
async fn test_filter_duplicated_events(&self);
130+
131+
/// Test that an event can be find or not.
132+
async fn test_find_event(&self);
130133
}
131134

132135
#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
@@ -797,6 +800,61 @@ impl EventCacheStoreIntegrationTests for DynEventCacheStore {
797800
assert_eq!(duplicated_events[1], event_morbier.event_id().unwrap());
798801
assert_eq!(duplicated_events[2], event_mont_dor.event_id().unwrap());
799802
}
803+
804+
async fn test_find_event(&self) {
805+
let room_id = room_id!("!r0:matrix.org");
806+
let another_room_id = room_id!("!r1:matrix.org");
807+
let event = |msg: &str| make_test_event(room_id, msg);
808+
809+
let event_comte = event("comté");
810+
let event_gruyere = event("gruyère");
811+
812+
// Add one event in one room.
813+
self.handle_linked_chunk_updates(
814+
room_id,
815+
vec![
816+
Update::NewItemsChunk { previous: None, new: CId::new(0), next: None },
817+
Update::PushItems {
818+
at: Position::new(CId::new(0), 0),
819+
items: vec![event_comte.clone()],
820+
},
821+
],
822+
)
823+
.await
824+
.unwrap();
825+
826+
// Add another event in another room.
827+
self.handle_linked_chunk_updates(
828+
another_room_id,
829+
vec![
830+
Update::NewItemsChunk { previous: None, new: CId::new(0), next: None },
831+
Update::PushItems {
832+
at: Position::new(CId::new(0), 0),
833+
items: vec![event_gruyere.clone()],
834+
},
835+
],
836+
)
837+
.await
838+
.unwrap();
839+
840+
// Now let's find out the event.
841+
let (position, event) = self
842+
.find_event(room_id, event_comte.event_id().unwrap().as_ref())
843+
.await
844+
.expect("failed to query for finding an event")
845+
.expect("failed to find an event");
846+
847+
assert_eq!(position.chunk_identifier(), 0);
848+
assert_eq!(position.index(), 0);
849+
assert_eq!(event.event_id(), event_comte.event_id());
850+
851+
// Now let's try to find an event that exists, but not in the expected room.
852+
assert!(self
853+
.find_event(room_id, event_gruyere.event_id().unwrap().as_ref())
854+
.await
855+
.expect("failed to query for finding an event")
856+
.is_none());
857+
}
800858
}
801859

802860
/// Macro building to allow your `EventCacheStore` implementation to run the
@@ -893,6 +951,13 @@ macro_rules! event_cache_store_integration_tests {
893951
get_event_cache_store().await.unwrap().into_event_cache_store();
894952
event_cache_store.test_filter_duplicated_events().await;
895953
}
954+
955+
#[async_test]
956+
async fn test_find_event() {
957+
let event_cache_store =
958+
get_event_cache_store().await.unwrap().into_event_cache_store();
959+
event_cache_store.test_find_event().await;
960+
}
896961
}
897962
};
898963
}

crates/matrix-sdk-base/src/event_cache/store/memory_store.rs

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,15 +21,15 @@ use std::{
2121
use async_trait::async_trait;
2222
use matrix_sdk_common::{
2323
linked_chunk::{
24-
relational::RelationalLinkedChunk, ChunkIdentifier, ChunkIdentifierGenerator, RawChunk,
25-
Update,
24+
relational::RelationalLinkedChunk, ChunkIdentifier, ChunkIdentifierGenerator, Position,
25+
RawChunk, Update,
2626
},
2727
ring_buffer::RingBuffer,
2828
store_locks::memory_store_helper::try_take_leased_lock,
2929
};
3030
use ruma::{
3131
time::{Instant, SystemTime},
32-
MxcUri, OwnedEventId, OwnedMxcUri, RoomId,
32+
EventId, MxcUri, OwnedEventId, OwnedMxcUri, RoomId,
3333
};
3434

3535
use super::{
@@ -183,7 +183,7 @@ impl EventCacheStore for MemoryStore {
183183

184184
let mut duplicated_events = Vec::new();
185185

186-
for event in inner.events.unordered_events(room_id) {
186+
for event in inner.events.unordered_items(room_id) {
187187
// If `events` is empty, we can short-circuit.
188188
if events.is_empty() {
189189
break;
@@ -202,6 +202,21 @@ impl EventCacheStore for MemoryStore {
202202
Ok(duplicated_events)
203203
}
204204

205+
async fn find_event(
206+
&self,
207+
room_id: &RoomId,
208+
event_id: &EventId,
209+
) -> Result<Option<(Position, Event)>, Self::Error> {
210+
let inner = self.inner.read().unwrap();
211+
212+
let event_and_room = inner.events.items().find_map(|(position, event, this_room_id)| {
213+
(room_id == this_room_id && event.event_id()? == event_id)
214+
.then_some((position, event.clone()))
215+
});
216+
217+
Ok(event_and_room)
218+
}
219+
205220
async fn add_media_content(
206221
&self,
207222
request: &MediaRequestParameters,

crates/matrix-sdk-base/src/event_cache/store/traits.rs

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,10 @@ use std::{fmt, sync::Arc};
1616

1717
use async_trait::async_trait;
1818
use matrix_sdk_common::{
19-
linked_chunk::{ChunkIdentifier, ChunkIdentifierGenerator, RawChunk, Update},
19+
linked_chunk::{ChunkIdentifier, ChunkIdentifierGenerator, Position, RawChunk, Update},
2020
AsyncTraitDeps,
2121
};
22-
use ruma::{MxcUri, OwnedEventId, RoomId};
22+
use ruma::{EventId, MxcUri, OwnedEventId, RoomId};
2323

2424
use super::{
2525
media::{IgnoreMediaRetentionPolicy, MediaRetentionPolicy},
@@ -109,6 +109,13 @@ pub trait EventCacheStore: AsyncTraitDeps {
109109
events: Vec<OwnedEventId>,
110110
) -> Result<Vec<OwnedEventId>, Self::Error>;
111111

112+
/// Find an event by its ID.
113+
async fn find_event(
114+
&self,
115+
room_id: &RoomId,
116+
event_id: &EventId,
117+
) -> Result<Option<(Position, Event)>, Self::Error>;
118+
112119
/// Add a media file's content in the media store.
113120
///
114121
/// # Arguments
@@ -299,6 +306,14 @@ impl<T: EventCacheStore> EventCacheStore for EraseEventCacheStoreError<T> {
299306
self.0.filter_duplicated_events(room_id, events).await.map_err(Into::into)
300307
}
301308

309+
async fn find_event(
310+
&self,
311+
room_id: &RoomId,
312+
event_id: &EventId,
313+
) -> Result<Option<(Position, Event)>, Self::Error> {
314+
self.0.find_event(room_id, event_id).await.map_err(Into::into)
315+
}
316+
302317
async fn add_media_content(
303318
&self,
304319
request: &MediaRequestParameters,

crates/matrix-sdk-common/src/linked_chunk/relational.rs

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -293,9 +293,9 @@ impl<Item, Gap> RelationalLinkedChunk<Item, Gap> {
293293
}
294294
}
295295

296-
/// Return an iterator that yields events of a particular room with no
296+
/// Return an iterator that yields items of a particular room with no
297297
/// particular order.
298-
pub fn unordered_events<'a>(&'a self, room_id: &'a RoomId) -> impl Iterator<Item = &'a Item> {
298+
pub fn unordered_items<'a>(&'a self, room_id: &'a RoomId) -> impl Iterator<Item = &'a Item> {
299299
self.items.iter().filter_map(move |item_row| {
300300
if item_row.room_id == room_id {
301301
match &item_row.item {
@@ -307,6 +307,17 @@ impl<Item, Gap> RelationalLinkedChunk<Item, Gap> {
307307
}
308308
})
309309
}
310+
311+
/// Return an iterator over all items.
312+
pub fn items(&self) -> impl Iterator<Item = (Position, &Item, &RoomId)> {
313+
self.items.iter().filter_map(|item_row| {
314+
if let Either::Item(item) = &item_row.item {
315+
Some((item_row.position, item, item_row.room_id.as_ref()))
316+
} else {
317+
None
318+
}
319+
})
320+
}
310321
}
311322

312323
impl<Item, Gap> RelationalLinkedChunk<Item, Gap>
@@ -1128,7 +1139,7 @@ mod tests {
11281139
],
11291140
);
11301141

1131-
let mut events = relational_linked_chunk.unordered_events(room_id);
1142+
let mut events = relational_linked_chunk.unordered_items(room_id);
11321143

11331144
assert_eq!(*events.next().unwrap(), 'a');
11341145
assert_eq!(*events.next().unwrap(), 'b');

crates/matrix-sdk-sqlite/src/event_cache_store.rs

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,9 @@ use matrix_sdk_base::{
2929
},
3030
Event, Gap,
3131
},
32-
linked_chunk::{ChunkContent, ChunkIdentifier, ChunkIdentifierGenerator, RawChunk, Update},
32+
linked_chunk::{
33+
ChunkContent, ChunkIdentifier, ChunkIdentifierGenerator, Position, RawChunk, Update,
34+
},
3335
media::{MediaRequestParameters, UniqueKey},
3436
};
3537
use matrix_sdk_store_encryption::StoreCipher;
@@ -846,6 +848,42 @@ impl EventCacheStore for SqliteEventCacheStore {
846848
.await
847849
}
848850

851+
async fn find_event(
852+
&self,
853+
room_id: &RoomId,
854+
event_id: &EventId,
855+
) -> Result<Option<(Position, Event)>, Self::Error> {
856+
let hashed_room_id = self.encode_key(keys::LINKED_CHUNKS, room_id);
857+
let event_id = event_id.to_owned();
858+
let this = self.clone();
859+
860+
self.acquire()
861+
.await?
862+
.with_transaction(move |txn| -> Result<_> {
863+
let Some((chunk_identifier, index, event)) = txn
864+
.prepare(
865+
"SELECT chunk_id, position, content FROM events WHERE room_id = ? AND event_id = ?",
866+
)?
867+
.query_row((hashed_room_id, event_id.as_str(),), |row| {
868+
Ok((
869+
row.get::<_, u64>(0)?,
870+
row.get::<_, usize>(1)?,
871+
row.get::<_, Vec<u8>>(2)?,
872+
))
873+
})
874+
.optional()?
875+
else {
876+
// Event is not found.
877+
return Ok(None);
878+
};
879+
880+
let event = serde_json::from_slice(&this.decode_value(&event)?)?;
881+
882+
Ok(Some((Position::new(ChunkIdentifier::new(chunk_identifier), index), event)))
883+
})
884+
.await
885+
}
886+
849887
async fn add_media_content(
850888
&self,
851889
request: &MediaRequestParameters,

0 commit comments

Comments
 (0)