atagen

matrix-rust-sdk

public
Star0
Watch0

Commit 0f816d7f79a6

tarball

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

2 files changed+31-2
event-cache: drop joined gaps persisted by earlier versions

Joined gaps written before joins stopped being persisted stayed in the store unless they sat right after a recent load anchor, and a fill on one kept answering Updated with Joined without removing it. history_candidate now drops every joined gap so the next commit deletes it, and a fill that meets one commits that removal, which makes the documented NotFound for later calls hold.
Modified file: crates/matrix-sdk/src/event_cache/caches/room/history.rs+26 additions−1 deletions
@@ -495,7 +495,15 @@ impl RoomEventCache {
495495 return Ok(HistoryGapFillOutcome::NotFound);
496496 };
497497 let history = initial.history.as_ref().expect("find_gap only returns history gaps");
498- if matches!(history.status, HistoryGapStatus::Joined | HistoryGapStatus::Unavailable) {
498+ if history.status == HistoryGapStatus::Joined {
499+ let mut state = self.inner.state.write().await?;
500+ let candidate = state.history_candidate().await?;
501+ state
502+ .commit_history_candidate(candidate, Vec::new(), HistoryCommitScope::Loaded)
503+ .await?;
504+ return Ok(HistoryGapFillOutcome::Updated { gap: history.clone(), events: 0 });
505+ }
506+ if history.status == HistoryGapStatus::Unavailable {
499507 return Ok(HistoryGapFillOutcome::Updated { gap: history.clone(), events: 0 });
500508 }
501509 let room = self.inner.weak_room.get().ok_or(EventCacheError::ClientDropped)?;
@@ -556,6 +564,23 @@ fn insert_run(
556564 }
557565 }
558566
567+pub(super) fn remove_joined_gaps(candidate: &mut EventLinkedChunk) {
568+ let joined: Vec<_> = candidate
569+ .chunks()
570+ .filter_map(|chunk| match chunk.content() {
571+ ChunkContent::Gap(Gap { history: Some(history), .. })
572+ if history.status == HistoryGapStatus::Joined =>
573+ {
574+ Some(chunk.identifier())
575+ }
576+ _ => None,
577+ })
578+ .collect();
579+ for chunk in joined {
580+ candidate.remove_gap(chunk);
581+ }
582+}
583+
559584 fn gaps(candidate: &EventLinkedChunk) -> Vec<HistoryGap> {
560585 candidate
561586 .chunks()
Modified file: crates/matrix-sdk/src/event_cache/caches/room/state.rs+5 additions−1 deletions
@@ -774,8 +774,12 @@ impl<'a> RoomEventCacheStateLockWriteGuard<'a> {
774774 Ok(diff_updates)
775775 }
776776
777+ /// Joined gaps persisted by earlier versions are dropped here, so the next
778+ /// commit removes them from the store.
777779 pub(super) async fn history_candidate(&self) -> Result<EventLinkedChunk, EventCacheError> {
778- self.load_from_store(None).await
780+ let mut candidate = self.load_from_store(None).await?;
781+ super::history::remove_joined_gaps(&mut candidate);
782+ Ok(candidate)
779783 }
780784
781785 /// Loads stored chunks from the newest back to `first`, or all of them.