atagen

matrix-rust-sdk

public
Star0
Watch0

Commit 892fd89cfa63

tarball

atagen <boss@atagen.co>2026-10-25 08:58 UTC

2 files changed+28-11
event-cache: load the history candidate once per history operation

history_candidate decrypts every stored chunk under the state write lock, and both a recent load and a fill built it twice, once to read their starting point. The recent anchor now comes from newest_retained_event_id and a fill finds its gap in memory first, falling back to the candidate only when the gap is not loaded. Fetched events are inserted in runs instead of one positional search each.
Modified file: crates/matrix-sdk/src/event_cache/caches/room/history.rs+25 additions−10 deletions
@@ -232,10 +232,7 @@ impl RoomEventCache {
232232 &self,
233233 mut cancellation: watch::Receiver<bool>,
234234 ) -> Result<RecentHistoryOutcome> {
235- let anchor = {
236- let state = self.inner.state.write().await?;
237- state.history_candidate().await?.revents().find_map(|(_, event)| event.event_id())
238- };
235+ let anchor = self.inner.state.write().await?.newest_retained_event_id().await?;
239236 let room = self.inner.weak_room.get().ok_or(EventCacheError::ClientDropped)?;
240237 let mut cursor = None;
241238 let mut visited = Vec::new();
@@ -328,22 +325,25 @@ impl RoomEventCache {
328325 }
329326
330327 let mut inserted = Vec::new();
328+ let mut run = Vec::new();
331329 let mut before = first_arrival.clone();
332330 for event in events.into_iter().rev() {
333331 let id = event.event_id();
334332 if id.as_ref().is_none_or(|id| known.insert(id.clone())) {
335- candidate.insert_history_before(before.as_deref(), vec![event.clone()], None);
336- inserted.push(event);
337- }
338- if id.is_some() {
333+ inserted.push(event.clone());
334+ run.push(event);
335+ } else {
336+ insert_run(&mut candidate, before.as_deref(), &mut run);
339337 before = id;
340338 }
341339 }
340+ insert_run(&mut candidate, before.as_deref(), &mut run);
341+ let before = oldest_fetched.clone().or(first_arrival.clone());
342342
343343 let history = anchor.as_ref().filter(|_| !joined).map(|anchor| HistoryGap {
344344 id: TransactionId::new(),
345345 older_boundary: Some(anchor.clone()),
346- newer_boundary: oldest_fetched.or(first_arrival.clone()),
346+ newer_boundary: before.clone(),
347347 status: if cursor.is_none() {
348348 HistoryGapStatus::Unavailable
349349 } else if stalled {
@@ -487,7 +487,10 @@ impl RoomEventCache {
487487 ) -> Result<HistoryGapFillOutcome> {
488488 let initial = {
489489 let state = self.inner.state.write().await?;
490- find_gap(&state.history_candidate().await?, &gap_id)
490+ match find_gap(state.room_linked_chunk(), &gap_id) {
491+ Some(gap) => Some(gap),
492+ None => find_gap(&state.history_candidate().await?, &gap_id),
493+ }
491494 };
492495 let Some(initial) = initial else {
493496 return Ok(HistoryGapFillOutcome::NotFound);
@@ -543,6 +546,18 @@ impl RoomEventCache {
543546 }
544547 }
545548
549+fn insert_run(
550+ candidate: &mut EventLinkedChunk,
551+ before: Option<&ruma::EventId>,
552+ run: &mut Vec<Event>,
553+) {
554+ if !run.is_empty() {
555+ let mut events = std::mem::take(run);
556+ events.reverse();
557+ candidate.insert_history_before(before, events, None);
558+ }
559+}
560+
546561 fn gaps(candidate: &EventLinkedChunk) -> Vec<HistoryGap> {
547562 candidate
548563 .chunks()
Modified file: crates/matrix-sdk/src/event_cache/caches/room/state.rs+3 additions−1 deletions
@@ -801,7 +801,9 @@ impl<'a> RoomEventCacheStateLockWriteGuard<'a> {
801801 }
802802
803803 /// Memory can hold no events at all, after a shrink to a trailing gap.
804- async fn newest_retained_event_id(&self) -> Result<Option<OwnedEventId>, EventCacheError> {
804+ pub(super) async fn newest_retained_event_id(
805+ &self,
806+ ) -> Result<Option<OwnedEventId>, EventCacheError> {
805807 let chunk = &self.state.room_linked_chunk;
806808 if let Some(id) = chunk.revents().find_map(|(_, event)| event.event_id()) {
807809 return Ok(Some(id));