Skip to content

Commit b214a0e

Browse files
authored
feat(sdk): Remove clones of large responses in Sliding Sync
feat(sdk): Remove clones of large responses in Sliding Sync
2 parents 1783cd7 + 70380a6 commit b214a0e

File tree

4 files changed

+74
-44
lines changed

4 files changed

+74
-44
lines changed

crates/matrix-sdk-base/src/sliding_sync.rs

Lines changed: 44 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,16 @@
1+
use std::collections::BTreeMap;
12
#[cfg(feature = "e2e-encryption")]
23
use std::ops::Deref;
34

4-
use ruma::api::client::sync::sync_events::{
5-
v3::{self, Ephemeral},
6-
v4,
7-
};
85
#[cfg(feature = "e2e-encryption")]
96
use ruma::UserId;
7+
use ruma::{
8+
api::client::sync::sync_events::{
9+
v3::{self, Ephemeral},
10+
v4, DeviceLists,
11+
},
12+
DeviceKeyAlgorithm, UInt,
13+
};
1014
use tracing::{debug, info, instrument};
1115

1216
use super::BaseClient;
@@ -26,7 +30,7 @@ impl BaseClient {
2630
/// * `response` - The response that we received after a successful sliding
2731
/// sync.
2832
#[instrument(skip_all, level = "trace")]
29-
pub async fn process_sliding_sync(&self, response: v4::Response) -> Result<SyncResponse> {
33+
pub async fn process_sliding_sync(&self, response: &v4::Response) -> Result<SyncResponse> {
3034
#[allow(unused_variables)]
3135
let v4::Response {
3236
// FIXME not yet supported by sliding sync. see
@@ -39,6 +43,7 @@ impl BaseClient {
3943
//presence,
4044
..
4145
} = response;
46+
4247
info!(rooms = rooms.len(), lists = lists.len(), extensions = !extensions.is_empty());
4348

4449
if rooms.is_empty() && extensions.is_empty() {
@@ -49,21 +54,35 @@ impl BaseClient {
4954

5055
let v4::Extensions { to_device, e2ee, account_data, .. } = extensions;
5156

52-
let to_device_events = to_device.map(|v4| v4.events).unwrap_or_default();
57+
let to_device_events = to_device.as_ref().map(|v4| v4.events.clone()).unwrap_or_default();
5358

5459
// Destructure the single `None` of the E2EE extension into separate objects
55-
// since that's what the OlmMachine API expects. Passing in the default
56-
// empty maps and vecs for this is completely fine, since the OlmMachine
60+
// since that's what the `OlmMachine` API expects. Passing in the default
61+
// empty maps and vecs for this is completely fine, since the `OlmMachine`
5762
// assumes empty maps/vecs mean no change in the one-time key counts.
63+
64+
// We declare default values that can be referenced hereinbelow. When we try to
65+
// extract values from `e2ee`, that would be unfortunate to clone the
66+
// value just to pass them (to remove them `e2ee`) as a reference later.
67+
let device_one_time_keys_count = BTreeMap::<DeviceKeyAlgorithm, UInt>::default();
68+
let device_unused_fallback_key_types = None;
69+
5870
let (device_lists, device_one_time_keys_count, device_unused_fallback_key_types) = e2ee
71+
.as_ref()
5972
.map(|e2ee| {
6073
(
61-
e2ee.device_lists,
62-
e2ee.device_one_time_keys_count,
63-
e2ee.device_unused_fallback_key_types,
74+
e2ee.device_lists.clone(),
75+
&e2ee.device_one_time_keys_count,
76+
&e2ee.device_unused_fallback_key_types,
6477
)
6578
})
66-
.unwrap_or_default();
79+
.unwrap_or_else(|| {
80+
(
81+
DeviceLists::default(),
82+
&device_one_time_keys_count,
83+
&device_unused_fallback_key_types,
84+
)
85+
});
6786

6887
info!(
6988
to_device_events = to_device_events.len(),
@@ -80,7 +99,7 @@ impl BaseClient {
8099
self.preprocess_to_device_events(
81100
to_device_events,
82101
&device_lists,
83-
&device_one_time_keys_count,
102+
device_one_time_keys_count,
84103
device_unused_fallback_key_types.as_deref(),
85104
)
86105
.await?
@@ -98,14 +117,14 @@ impl BaseClient {
98117

99118
let mut new_rooms = Rooms::default();
100119

101-
for (room_id, room_data) in rooms.into_iter() {
120+
for (room_id, room_data) in rooms {
102121
if !room_data.invite_state.is_empty() {
103122
let invite_states = &room_data.invite_state;
104-
let room = store.get_or_create_stripped_room(&room_id).await;
123+
let room = store.get_or_create_stripped_room(room_id).await;
105124
let mut room_info = room.clone_info();
106125
room_info.mark_state_partially_synced();
107126

108-
if let Some(r) = store.get_room(&room_id) {
127+
if let Some(r) = store.get_room(room_id) {
109128
let mut room_info = r.clone_info();
110129
room_info.mark_as_invited(); // FIXME: this might not be accurate
111130
room_info.mark_state_partially_synced();
@@ -119,7 +138,7 @@ impl BaseClient {
119138
v3::InvitedRoom::from(v3::InviteState::from(invite_states.clone())),
120139
);
121140
} else {
122-
let room = store.get_or_create_room(&room_id, RoomType::Joined).await;
141+
let room = store.get_or_create_room(room_id, RoomType::Joined).await;
123142
let mut room_info = room.clone_info();
124143
room_info.mark_as_joined(); // FIXME: this might not be accurate
125144
room_info.mark_state_partially_synced();
@@ -153,8 +172,8 @@ impl BaseClient {
153172
// }
154173

155174
let room_account_data = if let Some(inner_account_data) = &account_data {
156-
if let Some(events) = inner_account_data.rooms.get(&room_id) {
157-
self.handle_room_account_data(&room_id, events, &mut changes).await;
175+
if let Some(events) = inner_account_data.rooms.get(room_id) {
176+
self.handle_room_account_data(room_id, events, &mut changes).await;
158177
Some(events.to_vec())
159178
} else {
160179
None
@@ -171,8 +190,8 @@ impl BaseClient {
171190
.handle_timeline(
172191
&room,
173192
room_data.limited,
174-
room_data.timeline,
175-
room_data.prev_batch,
193+
room_data.timeline.clone(),
194+
room_data.prev_batch.clone(),
176195
&push_rules,
177196
&mut user_ids,
178197
&mut room_info,
@@ -188,8 +207,8 @@ impl BaseClient {
188207
// The room turned on encryption in this sync, we need
189208
// to also get all the existing users and mark them for
190209
// tracking.
191-
let joined = store.get_joined_user_ids(&room_id).await?;
192-
let invited = store.get_invited_user_ids(&room_id).await?;
210+
let joined = store.get_joined_user_ids(room_id).await?;
211+
let invited = store.get_invited_user_ids(room_id).await?;
193212

194213
let user_ids: Vec<&UserId> =
195214
joined.iter().chain(&invited).map(Deref::deref).collect();
@@ -246,15 +265,15 @@ impl BaseClient {
246265
debug!("applied changes");
247266

248267
let device_one_time_keys_count =
249-
device_one_time_keys_count.into_iter().map(|(k, v)| (k, v.into())).collect();
268+
device_one_time_keys_count.iter().map(|(k, v)| (k.clone(), (*v).into())).collect();
250269

251270
Ok(SyncResponse {
252271
rooms: new_rooms,
253272
ambiguity_changes: AmbiguityChanges { changes: ambiguity_cache.changes },
254273
notifications: changes.notifications,
255274
// FIXME not yet supported by sliding sync.
256275
presence: Default::default(),
257-
account_data: account_data.map(|a| a.global).unwrap_or_default(),
276+
account_data: account_data.as_ref().map(|a| a.global.clone()).unwrap_or_default(),
258277
to_device_events,
259278
device_lists,
260279
device_one_time_keys_count,

crates/matrix-sdk/src/sliding_sync/client.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,12 @@ impl Client {
1414
#[instrument(skip(self, response))]
1515
pub(crate) async fn process_sliding_sync(
1616
&self,
17-
response: v4::Response,
17+
response: &v4::Response,
1818
) -> Result<SyncResponse> {
1919
let response = self.base_client().process_sliding_sync(response).await?;
2020
debug!("done processing on base_client");
2121
self.handle_sync_response(&response).await?;
22+
2223
Ok(response)
2324
}
2425
}

crates/matrix-sdk/src/sliding_sync/mod.rs

Lines changed: 27 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -975,28 +975,39 @@ impl SlidingSync {
975975
self.rooms.read().unwrap().values().cloned().collect()
976976
}
977977

978+
/// Handle the HTTP response.
978979
#[instrument(skip_all, fields(views = views.len()))]
979980
async fn handle_response(
980981
&self,
981-
resp: v4::Response,
982+
sliding_sync_response: v4::Response,
982983
extensions: Option<ExtensionsConfig>,
983984
views: &mut BTreeMap<String, SlidingSyncViewRequestGenerator>,
984985
) -> Result<UpdateSummary, crate::Error> {
985-
let mut processed = self.client.process_sliding_sync(resp.clone()).await?;
986-
debug!("main client processed.");
987-
Observable::set(&mut self.pos.write().unwrap(), Some(resp.pos));
988-
Observable::set(&mut self.delta_token.write().unwrap(), resp.delta_token);
986+
// Handle and transform a Sliding Sync Response to a `SyncResponse`.
987+
//
988+
// We may not need the `sync_response` in the future (once `SyncResponse` will
989+
// move to Sliding Sync, i.e. to `v4::Response`), but processing the
990+
// `sliding_sync_response` is vital, so it must be done somewhere; for now it
991+
// happens here.
992+
let mut sync_response = self.client.process_sliding_sync(&sliding_sync_response).await?;
989993

990-
let update = {
994+
debug!("sliding sync response has been processed");
995+
996+
Observable::set(&mut self.pos.write().unwrap(), Some(sliding_sync_response.pos));
997+
Observable::set(&mut self.delta_token.write().unwrap(), sliding_sync_response.delta_token);
998+
999+
let update_summary = {
9911000
let mut rooms = Vec::new();
9921001
let mut rooms_map = self.rooms.write().unwrap();
993-
for (id, mut room_data) in resp.rooms.into_iter() {
994-
let timeline = if let Some(joined_room) = processed.rooms.join.remove(&id) {
1002+
1003+
for (id, mut room_data) in sliding_sync_response.rooms.into_iter() {
1004+
// `sync_response` contains the rooms with decrypted events if any, so look at
1005+
// the timeline events here first if the room exists.
1006+
// Otherwise, let's look at the timeline inside the `sliding_sync_response`.
1007+
let timeline = if let Some(joined_room) = sync_response.rooms.join.remove(&id) {
9951008
joined_room.timeline.events
9961009
} else {
997-
let events = room_data.timeline.into_iter().map(Into::into).collect();
998-
room_data.timeline = vec![];
999-
events
1010+
room_data.timeline.drain(..).map(Into::into).collect()
10001011
};
10011012

10021013
if let Some(mut room) = rooms_map.remove(&id) {
@@ -1018,7 +1029,7 @@ impl SlidingSync {
10181029

10191030
let mut updated_views = Vec::new();
10201031

1021-
for (name, updates) in resp.lists {
1032+
for (name, updates) in sliding_sync_response.lists {
10221033
let Some(generator) = views.get_mut(&name) else {
10231034
error!("Response for view {name} - unknown to us. skipping");
10241035
continue
@@ -1031,7 +1042,9 @@ impl SlidingSync {
10311042
}
10321043

10331044
// Update the `to-device` next-batch if found.
1034-
if let Some(to_device_since) = resp.extensions.to_device.map(|t| t.next_batch) {
1045+
if let Some(to_device_since) =
1046+
sliding_sync_response.extensions.to_device.map(|t| t.next_batch)
1047+
{
10351048
self.update_to_device_since(to_device_since)
10361049
}
10371050

@@ -1046,7 +1059,7 @@ impl SlidingSync {
10461059

10471060
self.cache_to_storage().await?;
10481061

1049-
Ok(update)
1062+
Ok(update_summary)
10501063
}
10511064

10521065
async fn sync_once(

crates/matrix-sdk/src/sliding_sync/room.rs

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -41,12 +41,9 @@ impl SlidingSyncRoom {
4141
pub(super) fn new(
4242
client: Client,
4343
room_id: OwnedRoomId,
44-
mut inner: v4::SlidingSyncRoom,
44+
inner: v4::SlidingSyncRoom,
4545
timeline: Vec<SyncTimelineEvent>,
4646
) -> Self {
47-
// we overwrite to only keep one copy
48-
inner.timeline = vec![];
49-
5047
let mut timeline_queue = ObservableVector::new();
5148
timeline_queue.append(timeline.into_iter().collect());
5249

0 commit comments

Comments
 (0)