Skip to content

Commit e8e8c32

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 5dd5710 commit e8e8c32

File tree

5 files changed

+148
-6
lines changed

5 files changed

+148
-6
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 found or not.
132+
async fn test_find_event(&self);
130133
}
131134

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

811869
/// Macro building to allow your `EventCacheStore` implementation to run the
@@ -902,6 +960,13 @@ macro_rules! event_cache_store_integration_tests {
902960
get_event_cache_store().await.unwrap().into_event_cache_store();
903961
event_cache_store.test_filter_duplicated_events().await;
904962
}
963+
964+
#[async_test]
965+
async fn test_find_event() {
966+
let event_cache_store =
967+
get_event_cache_store().await.unwrap().into_event_cache_store();
968+
event_cache_store.test_find_event().await;
969+
}
905970
}
906971
};
907972
}

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

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ use matrix_sdk_common::{
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, position) in inner.events.unordered_events(room_id) {
186+
for (event, position) 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: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ use matrix_sdk_common::{
1919
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, Position)>, 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>(
298+
pub fn unordered_items<'a>(
299299
&'a self,
300300
room_id: &'a RoomId,
301301
) -> impl Iterator<Item = (&'a Item, Position)> {
@@ -310,6 +310,17 @@ impl<Item, Gap> RelationalLinkedChunk<Item, Gap> {
310310
}
311311
})
312312
}
313+
314+
/// Return an iterator over all items.
315+
pub fn items(&self) -> impl Iterator<Item = (Position, &Item, &RoomId)> {
316+
self.items.iter().filter_map(|item_row| {
317+
if let Either::Item(item) = &item_row.item {
318+
Some((item_row.position, item, item_row.room_id.as_ref()))
319+
} else {
320+
None
321+
}
322+
})
323+
}
313324
}
314325

315326
impl<Item, Gap> RelationalLinkedChunk<Item, Gap>
@@ -1131,7 +1142,7 @@ mod tests {
11311142
],
11321143
);
11331144

1134-
let mut events = relational_linked_chunk.unordered_events(room_id);
1145+
let mut events = relational_linked_chunk.unordered_items(room_id);
11351146

11361147
assert_eq!(events.next().unwrap(), (&'a', Position::new(CId::new(0), 0)));
11371148
assert_eq!(events.next().unwrap(), (&'b', Position::new(CId::new(0), 1)));

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

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -854,6 +854,42 @@ impl EventCacheStore for SqliteEventCacheStore {
854854
.await
855855
}
856856

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

0 commit comments

Comments
 (0)