reefactor(base): Create the room::sync_v2::update_joined_room response processor.

This patch extracts the logic to handle a `JoinedRoom` in a response
processor.
This commit is contained in:
Ivan Enderlin
2025-04-14 10:51:19 +02:00
parent 71510de602
commit e62313d7ba
4 changed files with 166 additions and 110 deletions

View File

@@ -65,7 +65,7 @@ use crate::{
Result as StoreResult, RoomLoadSettings, StateChanges, StateStoreDataKey,
StateStoreDataValue, StateStoreExt, StoreConfig,
},
sync::{JoinedRoomUpdate, LeftRoomUpdate, RoomUpdates, SyncResponse},
sync::{LeftRoomUpdate, RoomUpdates, SyncResponse},
RoomStateFilter, SessionMeta,
};
@@ -539,71 +539,23 @@ impl BaseClient {
let mut updated_members_in_room: BTreeMap<OwnedRoomId, BTreeSet<OwnedUserId>> =
BTreeMap::new();
for (room_id, new_info) in response.rooms.join {
let room = self.state_store.get_or_create_room(
for (room_id, joined_room) in response.rooms.join {
let joined_room_update = processors::room::sync_v2::update_joined_room(
&mut context,
&room_id,
RoomState::Joined,
joined_room,
requested_required_states,
&self.state_store,
self.room_info_notable_update_sender.clone(),
);
let mut room_info = room.clone_info();
room_info.mark_as_joined();
room_info.update_from_ruma_summary(&new_info.summary);
room_info.set_prev_batch(new_info.timeline.prev_batch.as_deref());
room_info.mark_state_fully_synced();
room_info.handle_encryption_state(requested_required_states.for_room(&room_id));
let (raw_state_events, state_events) =
processors::state_events::sync::collect(&mut context, &new_info.state.events);
let mut new_user_ids = processors::state_events::sync::dispatch_and_get_new_users(
&mut context,
(&raw_state_events, &state_events),
&mut room_info,
&mut ambiguity_cache,
)
.await?;
processors::ephemeral_events::dispatch(
&mut context,
&new_info.ephemeral.events,
&room_id,
);
if new_info.timeline.limited {
room_info.mark_members_missing();
}
let (raw_state_events_from_timeline, state_events_from_timeline) =
processors::state_events::sync::collect_from_timeline(
&mut context,
&new_info.timeline.events,
);
let mut other_new_user_ids =
processors::state_events::sync::dispatch_and_get_new_users(
&mut context,
(&raw_state_events_from_timeline, &state_events_from_timeline),
&mut room_info,
&mut ambiguity_cache,
)
.await?;
new_user_ids.append(&mut other_new_user_ids);
updated_members_in_room.insert(room_id.to_owned(), new_user_ids.clone());
let timeline = processors::timeline::build(
&mut context,
&room,
&mut room_info,
processors::timeline::builder::Timeline::from(new_info.timeline),
&mut updated_members_in_room,
processors::timeline::builder::Notification::new(
&push_rules,
&mut notifications,
&self.state_store,
),
#[cfg(feature = "e2e-encryption")]
processors::timeline::builder::E2EE::new(
processors::e2ee::E2EE::new(
olm_machine.as_ref(),
self.decryption_trust_requirement,
self.handle_verification_events,
@@ -611,59 +563,7 @@ impl BaseClient {
)
.await?;
// Save the new `RoomInfo`.
context.state_changes.add_room(room_info);
processors::account_data::for_room(
&mut context,
&room_id,
&new_info.account_data.events,
&self.state_store,
)
.await;
// `processors::account_data::from_room` might have updated the `RoomInfo`.
// Let's fetch it again.
//
// SAFETY: `expect` is safe because the `RoomInfo` has been inserted 2 lines
// above.
let mut room_info = context
.state_changes
.room_infos
.get(&room_id)
.expect("`RoomInfo` must exist in `StateChanges` at this point")
.clone();
#[cfg(feature = "e2e-encryption")]
processors::e2ee::tracked_users::update_or_set_if_room_is_newly_encrypted(
&mut context,
olm_machine.as_ref(),
&new_user_ids,
room_info.encryption_state(),
room.encryption_state(),
&room_id,
&self.state_store,
)
.await?;
let notification_count = new_info.unread_notifications.into();
room_info.update_notification_count(notification_count);
let ambiguity_changes = ambiguity_cache.changes.remove(&room_id).unwrap_or_default();
new_rooms.join.insert(
room_id,
JoinedRoomUpdate::new(
timeline,
new_info.state.events,
new_info.account_data.events,
new_info.ephemeral.events,
notification_count,
ambiguity_changes,
),
);
context.state_changes.add_room(room_info);
new_rooms.join.insert(room_id, joined_room_update);
}
for (room_id, new_info) in response.rooms.leave {

View File

@@ -20,6 +20,7 @@ pub mod ephemeral_events;
#[cfg(feature = "e2e-encryption")]
pub mod latest_event;
pub mod profiles;
pub mod room;
pub mod state_events;
pub mod timeline;
#[cfg(feature = "e2e-encryption")]

View File

@@ -0,0 +1,15 @@
// Copyright 2025 The Matrix.org Foundation C.I.C.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
pub mod sync_v2;

View File

@@ -0,0 +1,140 @@
// Copyright 2025 The Matrix.org Foundation C.I.C.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
use std::collections::{BTreeMap, BTreeSet};
use ruma::{api::client::sync::sync_events::v3::JoinedRoom, OwnedRoomId, OwnedUserId, RoomId};
use tokio::sync::broadcast::Sender;
#[cfg(feature = "e2e-encryption")]
use super::super::e2ee;
use super::super::{account_data, ephemeral_events, state_events, timeline, Context};
use crate::{
store::{ambiguity_map::AmbiguityCache, BaseStateStore},
sync::JoinedRoomUpdate,
RequestedRequiredStates, Result, RoomInfoNotableUpdate, RoomState,
};
/// Process updates of a joined room.
#[allow(clippy::too_many_arguments)]
pub async fn update_joined_room(
context: &mut Context,
room_id: &RoomId,
joined_room: JoinedRoom,
requested_required_states: &RequestedRequiredStates,
state_store: &BaseStateStore,
room_info_notable_update_sender: Sender<RoomInfoNotableUpdate>,
ambiguity_cache: &mut AmbiguityCache,
updated_members_in_room: &mut BTreeMap<OwnedRoomId, BTreeSet<OwnedUserId>>,
notification: timeline::builder::Notification<'_>,
#[cfg(feature = "e2e-encryption")] e2ee: e2ee::E2EE<'_>,
) -> Result<JoinedRoomUpdate> {
let room =
state_store.get_or_create_room(room_id, RoomState::Joined, room_info_notable_update_sender);
let mut room_info = room.clone_info();
room_info.mark_as_joined();
room_info.update_from_ruma_summary(&joined_room.summary);
room_info.set_prev_batch(joined_room.timeline.prev_batch.as_deref());
room_info.mark_state_fully_synced();
room_info.handle_encryption_state(requested_required_states.for_room(room_id));
let (raw_state_events, state_events) =
state_events::sync::collect(context, &joined_room.state.events);
let mut new_user_ids = state_events::sync::dispatch_and_get_new_users(
context,
(&raw_state_events, &state_events),
&mut room_info,
ambiguity_cache,
)
.await?;
ephemeral_events::dispatch(context, &joined_room.ephemeral.events, room_id);
if joined_room.timeline.limited {
room_info.mark_members_missing();
}
let (raw_state_events_from_timeline, state_events_from_timeline) =
state_events::sync::collect_from_timeline(context, &joined_room.timeline.events);
let mut other_new_user_ids = state_events::sync::dispatch_and_get_new_users(
context,
(&raw_state_events_from_timeline, &state_events_from_timeline),
&mut room_info,
ambiguity_cache,
)
.await?;
new_user_ids.append(&mut other_new_user_ids);
updated_members_in_room.insert(room_id.to_owned(), new_user_ids.clone());
#[cfg(feature = "e2e-encryption")]
let olm_machine = e2ee.olm_machine.clone();
let timeline = timeline::build(
context,
&room,
&mut room_info,
timeline::builder::Timeline::from(joined_room.timeline),
notification,
#[cfg(feature = "e2e-encryption")]
e2ee,
)
.await?;
// Save the new `RoomInfo`.
context.state_changes.add_room(room_info);
account_data::for_room(context, room_id, &joined_room.account_data.events, state_store).await;
// `processors::account_data::from_room` might have updated the `RoomInfo`.
// Let's fetch it again.
//
// SAFETY: `expect` is safe because the `RoomInfo` has been inserted 2 lines
// above.
let mut room_info = context
.state_changes
.room_infos
.get(room_id)
.expect("`RoomInfo` must exist in `StateChanges` at this point")
.clone();
#[cfg(feature = "e2e-encryption")]
e2ee::tracked_users::update_or_set_if_room_is_newly_encrypted(
context,
olm_machine,
&new_user_ids,
room_info.encryption_state(),
room.encryption_state(),
room_id,
state_store,
)
.await?;
let notification_count = joined_room.unread_notifications.into();
room_info.update_notification_count(notification_count);
context.state_changes.add_room(room_info);
Ok(JoinedRoomUpdate::new(
timeline,
joined_room.state.events,
joined_room.account_data.events,
joined_room.ephemeral.events,
notification_count,
ambiguity_cache.changes.remove(room_id).unwrap_or_default(),
))
}