fix(sync/v3): Cleanup part 1: mostly fix redundant data in state

This commit is contained in:
Ginger
2025-10-20 17:59:51 -04:00
parent 33c3d23d60
commit 26fa73841b
13 changed files with 466 additions and 426 deletions
+58 -25
View File
@@ -3,12 +3,13 @@ mod v4;
mod v5;
use conduwuit::{
Error, PduCount, Result,
PduCount, Result,
matrix::pdu::PduEvent,
trace,
utils::stream::{BroadbandExt, ReadyExt, TryIgnore},
};
use conduwuit_service::Services;
use futures::{StreamExt, pin_mut};
use futures::StreamExt;
use ruma::{
RoomId, UserId,
events::TimelineEventType::{
@@ -23,43 +24,75 @@ pub(crate) use self::{
pub(crate) const DEFAULT_BUMP_TYPES: &[TimelineEventType; 6] =
&[CallInvite, PollStart, Beacon, RoomEncrypted, RoomMessage, Sticker];
#[derive(Default)]
pub(crate) struct TimelinePdus {
pub pdus: Vec<(PduCount, PduEvent)>,
pub limited: bool,
}
async fn load_timeline(
services: &Services,
sender_user: &UserId,
room_id: &RoomId,
roomsincecount: PduCount,
next_batch: Option<PduCount>,
starting_count: Option<PduCount>,
ending_count: Option<PduCount>,
limit: usize,
) -> Result<(Vec<(PduCount, PduEvent)>, bool), Error> {
) -> Result<TimelinePdus> {
let last_timeline_count = services
.rooms
.timeline
.last_timeline_count(Some(sender_user), room_id)
.await?;
if last_timeline_count <= roomsincecount {
return Ok((Vec::new(), false));
let mut pdus_between_counts = match starting_count {
| Some(starting_count) => {
if last_timeline_count <= starting_count {
return Ok(TimelinePdus::default());
}
// Stream from the DB all PDUs which were sent after `starting_count` but before
// `ending_count`, including both endpoints
services
.rooms
.timeline
.pdus(Some(sender_user), room_id, Some(starting_count))
.ignore_err()
.ready_take_while(|&(pducount, _)| {
pducount <= ending_count.unwrap_or_else(PduCount::max)
})
.boxed()
},
| None => {
// For initial sync, stream from the DB all PDUs before and including
// `ending_count` in reverse order
services
.rooms
.timeline
.pdus_rev(Some(sender_user), room_id, ending_count)
.ignore_err()
.boxed()
},
};
// Return at most `limit` PDUs from the stream
let mut pdus: Vec<_> = pdus_between_counts.by_ref().take(limit).collect().await;
if starting_count.is_none() {
// `pdus_rev` returns PDUs in reverse order. fix that here
pdus.reverse();
}
// The timeline is limited if more than `limit` PDUs exist in the DB after
// `starting_count`
let limited = pdus_between_counts.next().await.is_some();
let non_timeline_pdus = services
.rooms
.timeline
.pdus_rev(Some(sender_user), room_id, None)
.ignore_err()
.ready_skip_while(|&(pducount, _)| pducount > next_batch.unwrap_or_else(PduCount::max))
.ready_take_while(|&(pducount, _)| pducount > roomsincecount);
trace!(
"syncing {:?} timeline pdus from {:?} to {:?} (limited = {:?})",
pdus.len(),
starting_count,
ending_count,
limited,
);
// Take the last events for the timeline
pin_mut!(non_timeline_pdus);
let timeline_pdus: Vec<_> = non_timeline_pdus.by_ref().take(limit).collect().await;
let timeline_pdus: Vec<_> = timeline_pdus.into_iter().rev().collect();
// They /sync response doesn't always return all messages, so we say the output
// is limited unless there are events in non_timeline_pdus
let limited = non_timeline_pdus.next().await.is_some();
Ok((timeline_pdus, limited))
Ok(TimelinePdus { pdus, limited })
}
async fn share_encrypted_room(