refactor(sdk): R2D2 replaces UTD on PinnedEventsCache without involving RoomEventCache.

This patch updates R2D2 to fetch the `PinnedEventsCache` from
`EventCache` without using `RoomEventCache`.
This commit is contained in:
Ivan Enderlin
2026-05-18 18:47:16 +02:00
parent cac7dcce94
commit 5b756d3c9d
4 changed files with 38 additions and 13 deletions

View File

@@ -201,6 +201,16 @@ impl Caches {
})
}
/// Get a [`PinnedEventsCache`] if it has been initialised.
///
/// [`PinnedEventsCache`]: pinned_events::PinnedEventsCache
#[cfg(feature = "e2e-encryption")]
pub(super) fn pinned_events_without_initialisation(
&self,
) -> Option<&pinned_events::PinnedEventsCache> {
self.pinned_events.get()
}
/// 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;

View File

@@ -530,7 +530,7 @@ impl PinnedEventsCache {
/// list of decrypted events, and replace them, while alerting observers
/// about the update.
#[cfg(feature = "e2e-encryption")]
pub(in crate::event_cache) async fn replace_utds(&self, events: &[ResolvedUtd]) -> Result<()> {
pub(in super::super) async fn replace_utds(&self, events: &[ResolvedUtd]) -> Result<()> {
let mut guard = self.inner.state.write().await?;
if guard.state.chunk.replace_utds(events) {

View File

@@ -402,6 +402,19 @@ impl EventCache {
Ok((caches_for_room.pinned_events()?.clone(), drop_handles))
}
/// Return a pinned-events-specific view over the [`EventCache`] if it has
/// been initialised.
#[cfg(feature = "e2e-encryption")]
async fn pinned_events_without_initialisation(
&self,
room_id: &RoomId,
) -> Result<Option<PinnedEventsCache>> {
let caches_for_room = self.inner.all_caches_for_room(room_id).await?;
Ok(caches_for_room.pinned_events_without_initialisation().cloned())
}
/// Cleanly clear all the rooms' event caches.
///
/// This will notify any live observers that the room has been cleared.

View File

@@ -370,14 +370,14 @@ impl EventCache {
// Phase 1: under the room state write lock, collect cache handles and
// perform all room-linked-chunk mutations. We deliberately do NOT call
// replace_utds() on event-focused/pinned caches here to avoid an ABBA deadlock:
// pagination holds an event-focused cache lock and then tries to acquire the
// room state lock (via `save_events`), while this method would hold the
// room state lock and try to acquire event-focused cache locks.
let (pinned_cache, ef_caches) = {
// replace_utds() on event-focused/pinned-evenst caches here to avoid an ABBA
// deadlock: pagination holds an event-focused cache lock and then tries
// to acquire the room state lock (via `save_events`), while this method
// would hold the room state lock and try to acquire event-focused cache
// locks.
let ef_caches = {
let mut state = room_cache.state().write().await?;
let pinned_cache = state.pinned_events_cache().cloned();
let ef_caches: Vec<_> = state.event_focused_caches().cloned().collect();
// Consider the room linked chunk.
@@ -416,15 +416,17 @@ impl EventCache {
Some(RoomEventCacheGenericUpdate { room_id: room_id.to_owned() }),
);
(pinned_cache, ef_caches)
ef_caches
};
// Room state write lock is dropped here.
// Phase 2: replace UTDs in pinned and event-focused caches WITHOUT
// holding the room state lock. These caches have their own internal
// locks and don't need the room state lock.
if let Some(pinned_cache) = pinned_cache {
pinned_cache.replace_utds(&events).await?;
// Phase 2: replace UTDs in pinned-events and event-focused caches
// WITHOUT holding the room state lock. These caches have their own
// internal locks and don't need the room state lock.
if let Ok(Some(pinned_events_cache)) =
self.pinned_events_without_initialisation(room_id).await
{
pinned_events_cache.replace_utds(&events).await?;
}
// TODO: This ain't great for performance; there shouldn't be that many