From 9f5302663e51933132b1fe71bd6608943699a184 Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Wed, 21 Aug 2024 13:41:03 +0200 Subject: [PATCH] fix(sdk): Clear all sliding sync room subscriptions when session expires. This patch clears all sliding sync room subscriptions when a session expires. Indeed, we might not want to request all room subscriptions when the session restarts. Imagine if the client has subscribed to 400 rooms and the session expires: once the session restarts, it will ask for 400 room subscriptions, which is a lot and will result in a quite slow response. --- crates/matrix-sdk/src/sliding_sync/mod.rs | 76 +++++++++++++++++++++-- 1 file changed, 70 insertions(+), 6 deletions(-) diff --git a/crates/matrix-sdk/src/sliding_sync/mod.rs b/crates/matrix-sdk/src/sliding_sync/mod.rs index 20cfdf68584..7d006de08ad 100644 --- a/crates/matrix-sdk/src/sliding_sync/mod.rs +++ b/crates/matrix-sdk/src/sliding_sync/mod.rs @@ -756,7 +756,7 @@ impl SlidingSync { Ok(self.inner.internal_channel_send(SlidingSyncInternalMessage::SyncLoopStop)?) } - /// Expire the current Sliding Sync session. + /// Expire the current Sliding Sync session on the client-side. /// /// Expiring a Sliding Sync session means: resetting `pos`. It also resets /// sticky parameters. @@ -782,8 +782,13 @@ impl SlidingSync { } } - // Force invalidation of all the sticky parameters. - let _ = self.inner.sticky.write().unwrap().data_mut(); + { + let mut sticky = self.inner.sticky.write().unwrap(); + + // Clear all room subscriptions: we don't want to resend all room subscriptions + // when the session will restart. + sticky.data_mut().room_subscriptions.clear(); + } self.inner.lists.read().await.values().for_each(|list| list.invalidate_sticky_data()); } @@ -1143,9 +1148,68 @@ mod tests { let sticky = sliding_sync.inner.sticky.read().unwrap(); let room_subscriptions = &sticky.data().room_subscriptions; - assert!(room_subscriptions.contains_key(&room_id_0.to_owned())); - assert!(room_subscriptions.contains_key(&room_id_1.to_owned())); - assert!(!room_subscriptions.contains_key(&room_id_2.to_owned())); + assert!(room_subscriptions.contains_key(room_id_0)); + assert!(room_subscriptions.contains_key(room_id_1)); + assert!(!room_subscriptions.contains_key(room_id_2)); + } + + Ok(()) + } + + #[async_test] + async fn test_room_subscriptions_are_reset_when_session_expires() -> Result<()> { + let (_server, sliding_sync) = new_sliding_sync(vec![SlidingSyncList::builder("foo") + .sync_mode(SlidingSyncMode::new_selective().add_range(0..=10))]) + .await?; + + let room_id_0 = room_id!("!r0:bar.org"); + let room_id_1 = room_id!("!r1:bar.org"); + let room_id_2 = room_id!("!r2:bar.org"); + + // Subscribe to two rooms. + sliding_sync.subscribe_to_rooms(&[room_id_0, room_id_1], None); + + { + let sticky = sliding_sync.inner.sticky.read().unwrap(); + let room_subscriptions = &sticky.data().room_subscriptions; + + assert!(room_subscriptions.contains_key(room_id_0)); + assert!(room_subscriptions.contains_key(room_id_1)); + assert!(room_subscriptions.contains_key(room_id_2).not()); + } + + // Subscribe to one more room. + sliding_sync.subscribe_to_rooms(&[room_id_2], None); + + { + let sticky = sliding_sync.inner.sticky.read().unwrap(); + let room_subscriptions = &sticky.data().room_subscriptions; + + assert!(room_subscriptions.contains_key(room_id_0)); + assert!(room_subscriptions.contains_key(room_id_1)); + assert!(room_subscriptions.contains_key(room_id_2)); + } + + // Suddenly, the session expires! + sliding_sync.expire_session().await; + + { + let sticky = sliding_sync.inner.sticky.read().unwrap(); + let room_subscriptions = &sticky.data().room_subscriptions; + + assert!(room_subscriptions.is_empty()); + } + + // Subscribe to one room again. + sliding_sync.subscribe_to_rooms(&[room_id_2], None); + + { + let sticky = sliding_sync.inner.sticky.read().unwrap(); + let room_subscriptions = &sticky.data().room_subscriptions; + + assert!(room_subscriptions.contains_key(room_id_0).not()); + assert!(room_subscriptions.contains_key(room_id_1).not()); + assert!(room_subscriptions.contains_key(room_id_2)); } Ok(())