Skip to content

Commit

Permalink
fix(sdk): Clear all sliding sync room subscriptions when session expi…
Browse files Browse the repository at this point in the history
…res.

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.
  • Loading branch information
Hywan committed Aug 21, 2024
1 parent f6b21e6 commit 574147c
Showing 1 changed file with 68 additions and 2 deletions.
70 changes: 68 additions & 2 deletions crates/matrix-sdk/src/sliding_sync/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -783,7 +783,14 @@ 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();
let data = sticky.data_mut();

// Clear all room subscriptions: we don't want to resend all room subscriptions
// when the session will restart.
data.room_subscriptions.clear();
}

self.inner.lists.read().await.values().for_each(|list| list.invalidate_sticky_data());
}
Expand Down Expand Up @@ -1151,6 +1158,65 @@ mod tests {
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.to_owned()));
assert!(room_subscriptions.contains_key(&room_id_1.to_owned()));
assert!(room_subscriptions.contains_key(&room_id_2.to_owned()).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.to_owned()));
assert!(room_subscriptions.contains_key(&room_id_1.to_owned()));
assert!(room_subscriptions.contains_key(&room_id_2.to_owned()));
}

// 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.to_owned()).not());
assert!(room_subscriptions.contains_key(&room_id_1.to_owned()).not());
assert!(room_subscriptions.contains_key(&room_id_2.to_owned()));
}

Ok(())
}

#[async_test]
async fn test_to_device_token_properly_cached() -> Result<()> {
let (_server, sliding_sync) = new_sliding_sync(vec![SlidingSyncList::builder("foo")
Expand Down

0 comments on commit 574147c

Please sign in to comment.