From 992217d644cbd73e91ab1d5b62003d6095fd5ded Mon Sep 17 00:00:00 2001 From: Ginger Date: Wed, 5 Nov 2025 14:05:33 -0500 Subject: [PATCH] chore(sync/v3): Fix clippy lints --- src/api/client/sync/v3/joined.rs | 66 +++++++++++++------------- src/api/client/sync/v3/mod.rs | 4 ++ src/api/client/sync/v3/state.rs | 80 +++++++++++++++++--------------- 3 files changed, 82 insertions(+), 68 deletions(-) diff --git a/src/api/client/sync/v3/joined.rs b/src/api/client/sync/v3/joined.rs index 16ebcfe7..a925e8c2 100644 --- a/src/api/client/sync/v3/joined.rs +++ b/src/api/client/sync/v3/joined.rs @@ -200,37 +200,41 @@ pub(super) async fn load_joined_room( let lazily_loaded_members = prepare_lazily_loaded_members(services, sync_context, room_id, timeline.senders()).await; - /* - compute the state delta between the previous sync and this sync. if this is an initial sync - *or* we just joined this room, `build_state_initial` will be used, otherwise `build_state_incremental` - will be used. - */ - let state_events = if let Some(last_sync_end_count) = last_sync_end_count - && let Some(last_sync_end_shortstatehash) = last_sync_end_shortstatehash - && !full_state - { - build_state_incremental( - services, - syncing_user, - room_id, - PduCount::Normal(last_sync_end_count), - last_sync_end_shortstatehash, - timeline_start_shortstatehash, - current_shortstatehash, - &timeline, - lazily_loaded_members.as_ref(), - ) - .boxed() - .await? - } else { - build_state_initial( - services, - syncing_user, - timeline_start_shortstatehash, - lazily_loaded_members.as_ref(), - ) - .boxed() - .await? + // compute the state delta between the previous sync and this sync. + let state_events = match (last_sync_end_count, last_sync_end_shortstatehash) { + /* + if `last_sync_end_count` is Some (meaning this is an incremental sync), and `last_sync_end_shortstatehash` + is Some (meaning the syncing user didn't just join this room for the first time ever), and `full_state` is false, + then use `build_state_incremental`. + */ + | (Some(last_sync_end_count), Some(last_sync_end_shortstatehash)) if !full_state => + build_state_incremental( + services, + syncing_user, + room_id, + PduCount::Normal(last_sync_end_count), + last_sync_end_shortstatehash, + timeline_start_shortstatehash, + current_shortstatehash, + &timeline, + lazily_loaded_members.as_ref(), + ) + .boxed() + .await?, + /* + otherwise use `build_state_initial`. note that this branch will be taken if the user joined this room since the last sync + for the first time ever, because in that case we have no `last_sync_end_shortstatehash` and can't correctly calculate + the state using the incremental sync algorithm. + */ + | _ => + build_state_initial( + services, + syncing_user, + timeline_start_shortstatehash, + lazily_loaded_members.as_ref(), + ) + .boxed() + .await?, }; // for incremental syncs, calculate updates to E2EE device lists diff --git a/src/api/client/sync/v3/mod.rs b/src/api/client/sync/v3/mod.rs index 1ca9e027..1995d931 100644 --- a/src/api/client/sync/v3/mod.rs +++ b/src/api/client/sync/v3/mod.rs @@ -449,6 +449,10 @@ async fn process_presence_updates( .await } +/// Using the provided sync context and an iterator of user IDs in the +/// `timeline`, return a HashSet of user IDs whose membership events should be +/// sent to the client if lazy-loading is enabled. +#[allow(clippy::let_and_return)] async fn prepare_lazily_loaded_members( services: &Services, sync_context: SyncContext<'_>, diff --git a/src/api/client/sync/v3/state.rs b/src/api/client/sync/v3/state.rs index 83136cc8..4799c884 100644 --- a/src/api/client/sync/v3/state.rs +++ b/src/api/client/sync/v3/state.rs @@ -100,11 +100,17 @@ pub(super) async fn build_state_incremental<'a>( timeline: &TimelinePdus, lazily_loaded_members: Option<&'a MemberSet>, ) -> Result> { - // NB: a limited sync is one where `timeline.limited == true`. Synapse calls - // this a "gappy" sync internally. + /* + NB: a limited sync is one where `timeline.limited == true`. Synapse calls this a "gappy" sync internally. + + The algorithm implemented in this function is, currently, quite different from the algorithm vaguely described + by the Matrix specification. This is because the specification's description of the `state` property does not accurately + reflect how Synapse behaves, and therefore how client SDKs behave. + */ /* - the state events returned from an incremental sync which isn't limited are usually empty. + the `state` property of an incremental sync which isn't limited are _usually_ empty. + (note: the specification says that the `state` property is _always_ empty for limited syncs, which is incorrect.) however, if an event in the timeline (`timeline.pdus`) merges a split in the room's DAG (i.e. has multiple `prev_events`), the state at the _end_ of the timeline may include state events which were merged in and don't exist in the state at the _start_ of the timeline. because this is uncommon, we check here to see if any events in the timeline @@ -153,43 +159,43 @@ pub(super) async fn build_state_incremental<'a>( // if there are no splits in the DAG and the timeline isn't limited, then // `state` will always be empty unless lazy loading is enabled. - if let Some(lazily_loaded_members) = lazily_loaded_members - && !timeline.pdus.is_empty() - { - // lazy loading is enabled, so we return the membership events which were - // requested by the caller. - let lazy_membership_events: Vec<_> = lazily_loaded_members - .iter() - .stream() - .broad_filter_map(|user_id| async move { - if user_id == sender_user { - return None; - } + if let Some(lazily_loaded_members) = lazily_loaded_members { + if !timeline.pdus.is_empty() { + // lazy loading is enabled, so we return the membership events which were + // requested by the caller. + let lazy_membership_events: Vec<_> = lazily_loaded_members + .iter() + .stream() + .broad_filter_map(|user_id| async move { + if user_id == sender_user { + return None; + } - services - .rooms - .state_accessor - .state_get( - timeline_start_shortstatehash, - &StateEventType::RoomMember, - user_id.as_str(), - ) - .ok() - .await - }) - .collect() - .await; + services + .rooms + .state_accessor + .state_get( + timeline_start_shortstatehash, + &StateEventType::RoomMember, + user_id.as_str(), + ) + .ok() + .await + }) + .collect() + .await; - if !lazy_membership_events.is_empty() { - trace!( - "syncing lazy membership events for members: {:?}", - lazy_membership_events - .iter() - .map(|pdu| pdu.state_key().unwrap()) - .collect::>() - ); + if !lazy_membership_events.is_empty() { + trace!( + "syncing lazy membership events for members: {:?}", + lazy_membership_events + .iter() + .map(|pdu| pdu.state_key().unwrap()) + .collect::>() + ); + } + return Ok(lazy_membership_events); } - return Ok(lazy_membership_events); } // lazy loading is disabled, `state` is empty.