From 86bc97911c61365ea90603b68fb28e4e4f3b062d Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Thu, 21 May 2026 17:55:35 +0200 Subject: [PATCH] feat(sdk): Allow to reset an `EventFocusedCache`. This patch updates `ResetCaches` to handle the event-focused caches. --- .../event_cache/caches/event_focused/mod.rs | 31 +++++++++- .../matrix-sdk/src/event_cache/caches/mod.rs | 57 ++++++++++++++++--- 2 files changed, 79 insertions(+), 9 deletions(-) diff --git a/crates/matrix-sdk/src/event_cache/caches/event_focused/mod.rs b/crates/matrix-sdk/src/event_cache/caches/event_focused/mod.rs index 5ecccc9a2..2005c2e0c 100644 --- a/crates/matrix-sdk/src/event_cache/caches/event_focused/mod.rs +++ b/crates/matrix-sdk/src/event_cache/caches/event_focused/mod.rs @@ -31,6 +31,7 @@ use std::sync::Arc; +use eyeball_im::VectorDiff; use matrix_sdk_base::{ deserialized_responses::TimelineEvent, event_cache::{Event, Gap}, @@ -90,7 +91,7 @@ pub(crate) enum EventFocusedPaginationMode { }, } -struct EventFocusedCacheState { +pub(super) struct EventFocusedCacheState { /// The room owning this event-focused cache. room: WeakRoom, @@ -503,6 +504,24 @@ impl EventFocusedCacheState { Ok((result.chunk, result.next_batch_token)) } + + /// Reset this data structure as if it were brand new. + /// + /// Return a single diff update that is a clear of all events; as a + /// result, the caller may override any pending diff updates + /// with the result of this function. + pub fn reset(&mut self) -> Result>> { + self.chunk.reset(); + self.propagate_changes(); + + let diff_updates = self.chunk.updates_as_vector_diffs(); + + // Ensure the contract defined in the doc comment is true: + debug_assert_eq!(diff_updates.len(), 1); + debug_assert!(matches!(diff_updates[0], VectorDiff::Clear)); + + Ok(diff_updates) + } } /// A cache for an event-focused timeline. @@ -543,6 +562,16 @@ impl EventFocusedCache { } } + /// Return a reference to the state. + pub(super) fn state(&self) -> &Arc> { + &self.inner + } + + /// Get a reference to the _update sender_. + pub(super) async fn update_sender(&self) -> EventFocusedCacheUpdateSender { + self.inner.read().await.sender.clone() + } + /// Subscribe to updates from this event-focused timeline. pub async fn subscribe(&self) -> (Vec, Receiver) { let inner = self.inner.read().await; diff --git a/crates/matrix-sdk/src/event_cache/caches/mod.rs b/crates/matrix-sdk/src/event_cache/caches/mod.rs index c4f59f742..277619f37 100644 --- a/crates/matrix-sdk/src/event_cache/caches/mod.rs +++ b/crates/matrix-sdk/src/event_cache/caches/mod.rs @@ -430,6 +430,13 @@ pub(super) struct ResetCaches<'c> { pinned_events::PinnedEventsCacheStateLockWriteGuard<'c>, pinned_events::PinnedEventsCacheUpdateSender, )>, + event_focused_lock: OwnedRwLockWriteGuard< + HashMap, + >, + event_focused_locks: Vec<( + OwnedRwLockWriteGuard, + event_focused::EventFocusedCacheUpdateSender, + )>, } impl<'c> ResetCaches<'c> { @@ -459,11 +466,26 @@ impl<'c> ResetCaches<'c> { None }; - // TODO (in next commits). - let _ = event_focused; - todo!(); + // Acquire an exclusive access to the event-focused caches. + // Then, for each event-focused, acquire an exclusive access to its state. + let event_focused_lock = event_focused.clone().write_owned().await; + let mut event_focused_locks = Vec::new(); - Ok(Self { room_lock, threads_lock, thread_locks, pinned_events_lock }) + for event_focused in event_focused_lock.values() { + event_focused_locks.push(( + event_focused.state().clone().write_owned().await, + event_focused.update_sender().await, + )); + } + + Ok(Self { + room_lock, + threads_lock, + thread_locks, + pinned_events_lock, + event_focused_lock, + event_focused_locks, + }) } /// Reset all the event caches, and broadcast the [`TimelineVectorDiffs`]. @@ -473,7 +495,14 @@ impl<'c> ResetCaches<'c> { /// /// It can fail if resetting an event cache fails. pub async fn reset_all(self) -> Result<()> { - let Self { room_lock, threads_lock, thread_locks, pinned_events_lock } = self; + let Self { + room_lock, + threads_lock, + thread_locks, + pinned_events_lock, + event_focused_lock, + event_focused_locks, + } = self; // Room. { @@ -491,9 +520,7 @@ impl<'c> ResetCaches<'c> { // Threads. { - for thread_lock in thread_locks { - let (mut thread_state, thread_update_sender) = thread_lock; - + for (mut thread_state, thread_update_sender) in thread_locks { let updates_as_vector_diffs = thread_state.reset().await?; thread_update_sender.send( TimelineVectorDiffs { @@ -522,6 +549,20 @@ impl<'c> ResetCaches<'c> { } } + // Event-focused. + { + for (mut event_focused_state, event_focused_update_sender) in event_focused_locks { + let updates_as_vector_diffs = event_focused_state.reset()?; + let _ = event_focused_update_sender.send(TimelineVectorDiffs { + diffs: updates_as_vector_diffs, + origin: EventsOrigin::Cache, + }); + } + + // Now we can release the exclusive access over the event-focused caches. + drop(event_focused_lock); + } + Ok(()) } }