fix: Fix left rooms always being sent on initial sync

This commit is contained in:
Ginger 2026-03-04 12:49:32 -05:00
parent da182c162d
commit 7e501cdb09
No known key found for this signature in database
2 changed files with 25 additions and 29 deletions

View file

@ -1,5 +1,5 @@
use conduwuit::{ use conduwuit::{
Event, PduCount, PduEvent, Result, at, debug_warn, Event, PduEvent, Result, at, debug_warn,
pdu::EventHash, pdu::EventHash,
trace, trace,
utils::{self, IterStream, future::ReadyEqExt, stream::WidebandExt as _}, utils::{self, IterStream, future::ReadyEqExt, stream::WidebandExt as _},
@ -68,9 +68,13 @@ pub(super) async fn load_left_room(
return Ok(None); return Ok(None);
} }
// return early if this is an incremental sync, and we've already synced this // return early if:
// leave to the user, and `include_leave` isn't set on the filter. // - this is an initial sync and the room filter doesn't include leaves, or
if !filter.room.include_leave && last_sync_end_count >= Some(left_count) { // - this is an incremental sync, and we've already synced the leave, and the
// room filter doesn't include leaves
if last_sync_end_count.is_none_or(|last_sync_end_count| last_sync_end_count >= left_count)
&& !filter.room.include_leave
{
return Ok(None); return Ok(None);
} }
@ -195,27 +199,13 @@ async fn build_left_state_and_timeline(
leave_shortstatehash: ShortStateHash, leave_shortstatehash: ShortStateHash,
prev_membership_event: PduEvent, prev_membership_event: PduEvent,
) -> Result<(TimelinePdus, Vec<PduEvent>)> { ) -> Result<(TimelinePdus, Vec<PduEvent>)> {
let SyncContext { let SyncContext { syncing_user, filter, .. } = sync_context;
syncing_user,
last_sync_end_count,
filter,
..
} = sync_context;
let timeline_start_count = if let Some(last_sync_end_count) = last_sync_end_count { let timeline_start_count = services
// for incremental syncs, start the timeline after `since` .rooms
PduCount::Normal(last_sync_end_count) .timeline
} else { .get_pdu_count(&prev_membership_event.event_id)
// for initial syncs, start the timeline after the previous membership .await?;
// event. we don't want to include the membership event itself
// because clients get confused when they see a `join`
// membership event in a `leave` room.
services
.rooms
.timeline
.get_pdu_count(&prev_membership_event.event_id)
.await?
};
// end the timeline at the user's leave event // end the timeline at the user's leave event
let timeline_end_count = services let timeline_end_count = services

View file

@ -297,12 +297,18 @@ pub(crate) async fn build_sync_events(
.rooms .rooms
.state_cache .state_cache
.rooms_left(syncing_user) .rooms_left(syncing_user)
.broad_filter_map(|(room_id, leave_pdu)| { .broad_filter_map(|(room_id, leave_pdu)| async {
load_left_room(services, context, room_id.clone(), leave_pdu) let left_room = load_left_room(services, context, room_id.clone(), leave_pdu).await;
.map_ok(move |left_room| (room_id, left_room))
.ok() match left_room {
| Ok(Some(left_room)) => Some((room_id, left_room)),
| Ok(None) => None,
| Err(err) => {
warn!(?err, %room_id, "error loading joined room");
None
},
}
}) })
.ready_filter_map(|(room_id, left_room)| left_room.map(|left_room| (room_id, left_room)))
.collect(); .collect();
let invited_rooms = services let invited_rooms = services