From 42133a60c8624206e53cc0a16b34bf9ca8a080fa Mon Sep 17 00:00:00 2001 From: Benjamin Bouvier Date: Tue, 1 Apr 2025 15:53:51 +0200 Subject: [PATCH] fix(ffi): use `EventCache::clear_all_rooms()` to clear the events caches Clearing only the store backend, while not emptying the in-memory linked chunks, will lead to out-of-sync state across the in-memory caches and the database. As a result, it's safer to call the existing `EventCacheInner::clear_all_rooms`, which will clear all the rooms manually. --- bindings/matrix-sdk-ffi/src/client.rs | 13 +++++++------ .../matrix-sdk-base/src/event_cache/store/traits.rs | 4 ++++ crates/matrix-sdk/src/event_cache/mod.rs | 7 +++++++ 3 files changed, 18 insertions(+), 6 deletions(-) diff --git a/bindings/matrix-sdk-ffi/src/client.rs b/bindings/matrix-sdk-ffi/src/client.rs index d7a3783b0..247a9ffb4 100644 --- a/bindings/matrix-sdk-ffi/src/client.rs +++ b/bindings/matrix-sdk-ffi/src/client.rs @@ -1208,13 +1208,14 @@ impl Client { /// retention policy. pub async fn clear_caches(&self) -> Result<(), ClientError> { let closure = async || -> Result<_, EventCacheError> { - let store = self.inner.event_cache_store().lock().await?; - - // Clear all the room chunks. - store.clear_all_rooms_chunks().await?; - // Clean up the media cache according to the current media retention policy. - store.clean_up_media_cache().await?; + self.inner.event_cache_store().lock().await?.clean_up_media_cache().await?; + + // Clear all the room chunks. It's important to *not* call + // `EventCacheStore::clear_all_rooms_chunks` here, because there might be live + // observers of the linked chunks, and that would cause some very bad state + // mismatch. + self.inner.event_cache().clear_all_rooms().await?; Ok(()) }; diff --git a/crates/matrix-sdk-base/src/event_cache/store/traits.rs b/crates/matrix-sdk-base/src/event_cache/store/traits.rs index d7b9ed836..d7062aefa 100644 --- a/crates/matrix-sdk-base/src/event_cache/store/traits.rs +++ b/crates/matrix-sdk-base/src/event_cache/store/traits.rs @@ -101,6 +101,10 @@ pub trait EventCacheStore: AsyncTraitDeps { /// using the above [`Self::handle_linked_chunk_updates`] methods. It /// must *also* delete all the events' content, if they were stored in a /// separate table. + /// + /// ⚠ This is meant only for super specific use cases, where there shouldn't + /// be any live in-memory linked chunks. In general, prefer using + /// `EventCache::clear_all_rooms()` from the common SDK crate. async fn clear_all_rooms_chunks(&self) -> Result<(), Self::Error>; /// Given a set of event IDs, return the duplicated events along with their diff --git a/crates/matrix-sdk/src/event_cache/mod.rs b/crates/matrix-sdk/src/event_cache/mod.rs index 7e55b0508..76026c577 100644 --- a/crates/matrix-sdk/src/event_cache/mod.rs +++ b/crates/matrix-sdk/src/event_cache/mod.rs @@ -361,6 +361,13 @@ impl EventCache { Ok((room, drop_handles)) } + /// Cleanly clear all the rooms' event caches. + /// + /// This will notify any live observers that the room has been cleared. + pub async fn clear_all_rooms(&self) -> Result<()> { + self.inner.clear_all_rooms().await + } + /// Add an initial set of events to the event cache, reloaded from a cache. /// /// TODO: temporary for API compat, as the event cache should take care of