-
Notifications
You must be signed in to change notification settings - Fork 452
feat(sdk): Flatten the hierarchy of caches in the Event Cache, part 3: Event-focused #6603
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Hywan
merged 14 commits into
matrix-org:features/event-cache-refactoring
from
Hywan:features/event-cache-refactoring-flatten-event-focused
May 22, 2026
Merged
Changes from all commits
Commits
Show all changes
14 commits
Select commit
Hold shift + click to select a range
a7d3b0e
refactor(sdk): Move `EventFocusedCacheKey` from `room` to `event_focu…
Hywan 2079e3e
feat(sdk): `EventFocusedCacheKey` implements `Debug`.
Hywan 6259d07
chore(sdk): Save the creation of a `WeakRoom` from scratch since one …
Hywan 1049a61
fix(sdk): Remove the `room` argument of `EventFocusedCache::start_from`.
Hywan 37740e0
feat(sdk): Add `EventCache::event_focused`.
Hywan 46cd98d
refactor(sdk): Rename `focused` to `focused_event_id` in `EventFocuse…
Hywan f37e331
chore(ui): `TimelineController::new` uses `EventCache::event_focused`.
Hywan b26cf67
refactor(sdk): R2D2 uses `Caches` directly to resolve UTD on various …
Hywan 010d320
chore(sdk): Remove `EventFocusedCache` from `RoomEventCache`.
Hywan 12e48d7
test(sdk): Update the tests.
Hywan 916bbe6
chore(sdk): Reorganise imports.
Hywan 7735f4e
refactor(sdk): Rename `EventFocusedCacheInner` to `EventFocusedCacheS…
Hywan 0a23fb3
feat(sdk): Allow to reset an `EventFocusedCache`.
Hywan 420c093
doc(sdk): Fix a typo in the documentation of `Caches::all_events`.
Hywan File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -42,9 +42,30 @@ pub mod thread; | |
| /// A type to hold all the caches for a given room. | ||
| #[derive(Debug)] | ||
| pub(super) struct Caches { | ||
| /// The one and only [`RoomEventCache`]. | ||
| /// | ||
| /// [`RoomEventCache`]: room::RoomEventCache | ||
| pub room: room::RoomEventCache, | ||
|
|
||
| /// All the lazily-loaded [`ThreadEventCache`]. | ||
| /// | ||
| /// [`ThreadEventCache`]: thread::ThreadEventCache | ||
| // An `Arc` is used to get an owned lock. | ||
| pub threads: Arc<RwLock<HashMap<OwnedEventId, thread::ThreadEventCache>>>, | ||
|
|
||
| /// The one and only [`PinnedEventsCache`]. | ||
| /// | ||
| /// [`PinnedEventsCache`]: pinned_events::PinnedEventsCache | ||
| pub pinned_events: OnceCell<pinned_events::PinnedEventsCache>, | ||
|
|
||
| /// All the lazily-loaded [`EventFocusedCache`]. | ||
| /// | ||
| /// [`EventFocusedCache`]: event_focused::EventFocusedCache | ||
| // An `Arc` is used to get an owned lock. | ||
| pub event_focused: | ||
| Arc<RwLock<HashMap<event_focused::EventFocusedCacheKey, event_focused::EventFocusedCache>>>, | ||
|
|
||
| /// Internals data, used to lazily create caches. | ||
| internals: CachesInternals, | ||
| } | ||
|
|
||
|
|
@@ -127,6 +148,7 @@ impl Caches { | |
| room: room_event_cache, | ||
| threads: Arc::new(RwLock::new(HashMap::new())), | ||
| pinned_events: OnceCell::new(), | ||
| event_focused: Arc::new(RwLock::new(HashMap::new())), | ||
| internals: CachesInternals { store, linked_chunk_update_sender, room_version_rules }, | ||
| }) | ||
| } | ||
|
|
@@ -201,19 +223,52 @@ impl Caches { | |
| }) | ||
| } | ||
|
|
||
| /// Get a [`PinnedEventsCache`] if it has been initialised. | ||
| /// Get or create a [`EventFocusedCache`]. | ||
| /// | ||
| /// [`PinnedEventsCache`]: pinned_events::PinnedEventsCache | ||
| #[cfg(feature = "e2e-encryption")] | ||
| pub(super) fn pinned_events_without_initialisation( | ||
| /// [`EventFocusedCache`]: event_focused::EventFocusedCache | ||
| pub async fn event_focused( | ||
| &self, | ||
| ) -> Option<&pinned_events::PinnedEventsCache> { | ||
| self.pinned_events.get() | ||
| event_id: OwnedEventId, | ||
| thread_mode: event_focused::EventFocusThreadMode, | ||
| number_of_initial_events: u16, | ||
| ) -> Result< | ||
| OwnedRwLockReadGuard< | ||
| HashMap<event_focused::EventFocusedCacheKey, event_focused::EventFocusedCache>, | ||
| event_focused::EventFocusedCache, | ||
| >, | ||
| > { | ||
| let key = event_focused::EventFocusedCacheKey { focused_event_id: event_id, thread_mode }; | ||
|
|
||
| Ok( | ||
| match OwnedRwLockWriteGuard::try_downgrade_map( | ||
| self.event_focused.clone().write_owned().await, | ||
| |event_focused_caches| event_focused_caches.get(&key), | ||
| ) { | ||
| // Event-focused cache exists. | ||
| Ok(locked_cache) => locked_cache, | ||
| // Event-focused cache does not exist, let's create it. | ||
| Err(mut event_focused_caches) => { | ||
| let cache = event_focused::EventFocusedCache::new( | ||
| self.room.weak_room().clone(), | ||
| key.focused_event_id.clone(), | ||
| self.internals.linked_chunk_update_sender.clone(), | ||
| ); | ||
| cache.start_from(number_of_initial_events, thread_mode).await?; | ||
|
|
||
| event_focused_caches.insert(key.clone(), cache); | ||
|
|
||
| OwnedRwLockWriteGuard::downgrade_map( | ||
| event_focused_caches, | ||
| |event_focused_caches| event_focused_caches.get(&key).unwrap(), | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I guess it's safe to
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Correct! |
||
| ) | ||
| } | ||
| }, | ||
| ) | ||
| } | ||
|
|
||
| /// Update all the event caches with a [`JoinedRoomUpdate`]. | ||
| pub(super) async fn handle_joined_room_update(&self, updates: JoinedRoomUpdate) -> Result<()> { | ||
| let Self { room, threads, pinned_events, internals } = &self; | ||
| let Self { room, threads, pinned_events, event_focused, internals } = &self; | ||
|
|
||
| // Room. | ||
| { | ||
|
|
@@ -264,12 +319,19 @@ impl Caches { | |
| pinned_events.handle_joined_room_update(updates).await?; | ||
| } | ||
|
|
||
| // Event-focused. | ||
| { | ||
| // An event-focused cache isn't listening to live update. Consequently, it is | ||
| // not interested by this kind of update. | ||
| let _ = event_focused; | ||
| } | ||
|
|
||
| Ok(()) | ||
| } | ||
|
|
||
| /// Update all the event caches with a [`LeftRoomUpdate`]. | ||
| pub(super) async fn handle_left_room_update(&self, updates: LeftRoomUpdate) -> Result<()> { | ||
| let Self { room, threads, pinned_events, internals } = &self; | ||
| let Self { room, threads, pinned_events, event_focused, internals } = &self; | ||
|
|
||
| // Room. | ||
| { | ||
|
|
@@ -320,6 +382,13 @@ impl Caches { | |
| pinned_events.handle_left_room_update(updates).await?; | ||
| } | ||
|
|
||
| // Event-focused. | ||
| { | ||
| // An event-focused cache isn't listening to live update. Consequently, it is | ||
| // not interested by this kind of update. | ||
| let _ = event_focused; | ||
| } | ||
|
|
||
| Ok(()) | ||
| } | ||
|
|
||
|
|
@@ -334,7 +403,7 @@ impl Caches { | |
| ResetCaches::new(self).await | ||
| } | ||
|
|
||
| /// Get all events from all the event caches manged by this [`Cacches`]. | ||
| /// Get all events from all the event caches manged by this [`Caches`]. | ||
| /// | ||
| /// Events can be duplicated if present in different event caches. | ||
| #[cfg(feature = "e2e-encryption")] | ||
|
|
@@ -361,14 +430,21 @@ pub(super) struct ResetCaches<'c> { | |
| pinned_events::PinnedEventsCacheStateLockWriteGuard<'c>, | ||
| pinned_events::PinnedEventsCacheUpdateSender, | ||
| )>, | ||
| event_focused_lock: OwnedRwLockWriteGuard< | ||
| HashMap<event_focused::EventFocusedCacheKey, event_focused::EventFocusedCache>, | ||
| >, | ||
| event_focused_locks: Vec<( | ||
| OwnedRwLockWriteGuard<event_focused::EventFocusedCacheState>, | ||
| event_focused::EventFocusedCacheUpdateSender, | ||
| )>, | ||
| } | ||
|
|
||
| impl<'c> ResetCaches<'c> { | ||
| /// Create a new [`ResetCaches`]. | ||
| /// | ||
| /// It can fail if acquiring an exclusive lock fails. | ||
| async fn new( | ||
| Caches { room, threads, pinned_events, internals: _ }: &'c mut Caches, | ||
| Caches { room, threads, pinned_events, event_focused, internals: _ }: &'c mut Caches, | ||
| ) -> Result<Self> { | ||
| // Acquire an exclusive access to the state of the room. | ||
| let room_lock = (room.state().write().await?, room.update_sender().clone()); | ||
|
|
@@ -390,7 +466,26 @@ impl<'c> ResetCaches<'c> { | |
| None | ||
| }; | ||
|
|
||
| Ok(Self { room_lock, threads_lock, thread_locks, pinned_events_lock }) | ||
| // 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(); | ||
|
|
||
| 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`]. | ||
|
|
@@ -400,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. | ||
| { | ||
|
|
@@ -418,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 { | ||
|
|
@@ -449,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(()) | ||
| } | ||
| } | ||
|
|
||
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.