feat(event cache store): add a method to clear all rooms' linked chunks

This commit is contained in:
Benjamin Bouvier
2024-12-09 14:54:13 +01:00
parent cf178d603c
commit cf02e694f2
5 changed files with 101 additions and 0 deletions

View File

@@ -114,6 +114,9 @@ pub trait EventCacheStoreIntegrationTests {
/// Test that rebuilding a linked chunk from an empty store doesn't return
/// anything.
async fn test_rebuild_empty_linked_chunk(&self);
/// Test that clear all the rooms' linked chunks works.
async fn test_clear_all_rooms_chunks(&self);
}
#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
@@ -372,6 +375,65 @@ impl EventCacheStoreIntegrationTests for DynEventCacheStore {
// When I rebuild a linked chunk from an empty store, it's empty.
assert!(self.reload_linked_chunk(&DEFAULT_TEST_ROOM_ID).await.unwrap().is_none());
}
async fn test_clear_all_rooms_chunks(&self) {
use matrix_sdk_common::linked_chunk::ChunkIdentifier as CId;
let r0 = room_id!("!r0:matrix.org");
let r1 = room_id!("!r1:matrix.org");
// Add updates for the first room.
self.handle_linked_chunk_updates(
r0,
vec![
// new chunk
Update::NewItemsChunk { previous: None, new: CId::new(0), next: None },
// new items on 0
Update::PushItems {
at: Position::new(CId::new(0), 0),
items: vec![make_test_event(r0, "hello"), make_test_event(r0, "world")],
},
],
)
.await
.unwrap();
// Add updates for the second room.
self.handle_linked_chunk_updates(
r1,
vec![
// Empty items chunk.
Update::NewItemsChunk { previous: None, new: CId::new(0), next: None },
// a gap chunk
Update::NewGapChunk {
previous: Some(CId::new(0)),
new: CId::new(1),
next: None,
gap: Gap { prev_token: "bleu d'auvergne".to_owned() },
},
// another items chunk
Update::NewItemsChunk { previous: Some(CId::new(1)), new: CId::new(2), next: None },
// new items on 0
Update::PushItems {
at: Position::new(CId::new(2), 0),
items: vec![make_test_event(r0, "yummy")],
},
],
)
.await
.unwrap();
// Sanity check: both linked chunks can be reloaded.
assert!(self.reload_linked_chunk(r0).await.unwrap().is_some());
assert!(self.reload_linked_chunk(r1).await.unwrap().is_some());
// Clear the chunks.
self.clear_all_rooms_chunks().await.unwrap();
// Both rooms now have no linked chunk.
assert!(self.reload_linked_chunk(r0).await.unwrap().is_none());
assert!(self.reload_linked_chunk(r1).await.unwrap().is_none());
}
}
/// Macro building to allow your `EventCacheStore` implementation to run the
@@ -440,6 +502,13 @@ macro_rules! event_cache_store_integration_tests {
get_event_cache_store().await.unwrap().into_event_cache_store();
event_cache_store.test_rebuild_empty_linked_chunk().await;
}
#[async_test]
async fn test_clear_all_rooms_chunks() {
let event_cache_store =
get_event_cache_store().await.unwrap().into_event_cache_store();
event_cache_store.test_clear_all_rooms_chunks().await;
}
}
};
}

View File

@@ -115,6 +115,11 @@ impl EventCacheStore for MemoryStore {
Ok(result)
}
async fn clear_all_rooms_chunks(&self) -> Result<(), Self::Error> {
self.inner.write().unwrap().events.clear();
Ok(())
}
async fn add_media_content(
&self,
request: &MediaRequestParameters,

View File

@@ -62,6 +62,12 @@ pub trait EventCacheStore: AsyncTraitDeps {
room_id: &RoomId,
) -> Result<Option<LinkedChunk<DEFAULT_CHUNK_CAPACITY, Event, Gap>>, Self::Error>;
/// Clear persisted events for all the rooms.
///
/// This will empty and remove all the linked chunks stored previously,
/// using the above [`Self::handle_linked_chunk_updates`] methods.
async fn clear_all_rooms_chunks(&self) -> Result<(), Self::Error>;
/// Add a media file's content in the media store.
///
/// # Arguments
@@ -188,6 +194,10 @@ impl<T: EventCacheStore> EventCacheStore for EraseEventCacheStoreError<T> {
self.0.reload_linked_chunk(room_id).await.map_err(Into::into)
}
async fn clear_all_rooms_chunks(&self) -> Result<(), Self::Error> {
self.0.clear_all_rooms_chunks().await.map_err(Into::into)
}
async fn add_media_content(
&self,
request: &MediaRequestParameters,

View File

@@ -80,6 +80,12 @@ impl<Item, Gap> RelationalLinkedChunk<Item, Gap> {
Self { chunks: Vec::new(), items: Vec::new() }
}
/// Removes all the chunks and items from this relational linked chunk.
pub fn clear(&mut self) {
self.chunks.clear();
self.items.clear();
}
/// Apply [`Update`]s. That's the only way to write data inside this
/// relational linked chunk.
pub fn apply_updates(&mut self, room_id: &RoomId, updates: Vec<Update<Item, Gap>>) {

View File

@@ -609,6 +609,17 @@ impl EventCacheStore for SqliteEventCacheStore {
})
}
async fn clear_all_rooms_chunks(&self) -> Result<(), Self::Error> {
self.acquire()
.await?
.with_transaction(move |txn| {
// Remove all the chunks, and let cascading do its job.
txn.execute("DELETE FROM linked_chunks", ())
})
.await?;
Ok(())
}
async fn add_media_content(
&self,
request: &MediaRequestParameters,