Deserialise events early so we don't have to do it multiple times

We pass the already-deserialised event in to handle_state and
process_sliding_sync_room_membership, to avoid deserialising inside both
of them.
This commit is contained in:
Andy Balaam
2023-06-13 12:34:19 +01:00
parent 451398612a
commit f36a5b8cd7
2 changed files with 58 additions and 35 deletions

View File

@@ -17,7 +17,7 @@
use std::ops::Deref;
use std::{
collections::{BTreeMap, BTreeSet},
fmt,
fmt, iter,
sync::Arc,
};
@@ -478,10 +478,16 @@ impl BaseClient {
changes.stripped_state.insert(room_info.room_id().to_owned(), state_events);
}
/// Process the events provided during a sync.
///
/// events must be exactly the same list of events that are in raw_events,
/// but deserialised. We demand them here to avoid deserialising
/// multiple times.
#[instrument(skip_all, fields(room_id = ?room_info.room_id))]
pub(crate) async fn handle_state(
&self,
events: &[Raw<AnySyncStateEvent>],
raw_events: &[Raw<AnySyncStateEvent>],
events: &[AnySyncStateEvent],
room_info: &mut RoomInfo,
changes: &mut StateChanges,
ambiguity_cache: &mut AmbiguityCache,
@@ -490,16 +496,8 @@ impl BaseClient {
let mut user_ids = BTreeSet::new();
let mut profiles = BTreeMap::new();
for raw_event in events {
let event = match raw_event.deserialize() {
Ok(ev) => ev,
Err(e) => {
warn!("Couldn't deserialize state event: {e}");
continue;
}
};
room_info.handle_state_event(&event);
for (raw_event, event) in iter::zip(raw_events, events) {
room_info.handle_state_event(event);
if let AnySyncStateEvent::RoomMember(member) = &event {
ambiguity_cache.handle_event(changes, &room_info.room_id, member).await?;
@@ -714,9 +712,12 @@ impl BaseClient {
room_info.set_prev_batch(new_info.timeline.prev_batch.as_deref());
room_info.mark_state_fully_synced();
let deserialized_events = Self::deserialize_events(&new_info.state.events);
let mut user_ids = self
.handle_state(
&new_info.state.events,
&deserialized_events,
&mut room_info,
&mut changes,
&mut ambiguity_cache,
@@ -800,9 +801,12 @@ impl BaseClient {
room_info.mark_as_left();
room_info.mark_state_partially_synced();
let deserialized_events = Self::deserialize_events(&new_info.state.events);
let mut user_ids = self
.handle_state(
&new_info.state.events,
&deserialized_events,
&mut room_info,
&mut changes,
&mut ambiguity_cache,
@@ -1242,6 +1246,21 @@ impl BaseClient {
pub fn subscribe_to_ignore_user_list_changes(&self) -> Subscriber<()> {
self.ignore_user_list_changes_tx.subscribe()
}
pub(crate) fn deserialize_events(
raw_events: &[Raw<AnySyncStateEvent>],
) -> Vec<AnySyncStateEvent> {
raw_events
.iter()
.filter_map(|raw_event| match raw_event.deserialize() {
Ok(ev) => Some(ev),
Err(e) => {
warn!("Couldn't deserialize state event: {e}");
None
}
})
.collect()
}
}
impl Default for BaseClient {

View File

@@ -21,10 +21,9 @@ use ruma::{
v4::{self, AccountData},
},
events::AnySyncStateEvent,
serde::Raw,
RoomId,
};
use tracing::{debug, info, instrument, warn};
use tracing::{debug, info, instrument};
use super::BaseClient;
#[cfg(feature = "e2e-encryption")]
@@ -193,15 +192,30 @@ impl BaseClient {
ambiguity_cache: &mut AmbiguityCache,
account_data: &AccountData,
) -> Result<(RoomInfo, Option<JoinedRoom>, Option<InvitedRoom>)> {
let required_state = Self::deserialize_events(&room_data.required_state);
// Find or create the room in the store
let (room, mut room_info, invited_room) =
self.process_sliding_sync_room_membership(room_data, store, room_id, changes).await;
let (room, mut room_info, invited_room) = self
.process_sliding_sync_room_membership(
room_data,
&required_state,
store,
room_id,
changes,
)
.await;
room_info.mark_state_partially_synced();
let mut user_ids = if !room_data.required_state.is_empty() {
self.handle_state(&room_data.required_state, &mut room_info, changes, ambiguity_cache)
.await?
let mut user_ids = if !required_state.is_empty() {
self.handle_state(
&room_data.required_state,
&required_state,
&mut room_info,
changes,
ambiguity_cache,
)
.await?
} else {
Default::default()
};
@@ -276,6 +290,7 @@ impl BaseClient {
async fn process_sliding_sync_room_membership(
&self,
room_data: &v4::SlidingSyncRoom,
required_state: &[AnySyncStateEvent],
store: &Store,
room_id: &RoomId,
changes: &mut StateChanges,
@@ -319,31 +334,20 @@ impl BaseClient {
// property. In sliding sync we only have invite_state and
// required_state, so we must process required_state looking for
// relevant membership events.
self.handle_own_room_membership(&room_data.required_state, &mut room_info).await;
self.handle_own_room_membership(required_state, &mut room_info).await;
(room, room_info, None)
}
}
/// Find any m.room.member events that refer to the current user, and update the state in
/// room_info to reflect the "membership" property.
/// Find any m.room.member events that refer to the current user, and update
/// the state in room_info to reflect the "membership" property.
pub(crate) async fn handle_own_room_membership(
&self,
required_state: &[Raw<AnySyncStateEvent>],
required_state: &[AnySyncStateEvent],
room_info: &mut RoomInfo,
) {
// Note: we deserialise these same events inside handle_state(). We could refactor to do
// this only once.
for raw_event in required_state {
let event = match raw_event.deserialize() {
Ok(ev) => ev,
Err(e) => {
warn!("Couldn't deserialize state event: {e}");
continue;
}
};
for event in required_state {
if let AnySyncStateEvent::RoomMember(member) = &event {
// If this event updates the current user's membership, record that in the
// room_info.