diff --git a/crates/matrix-sdk-base/src/event_cache/store/integration_tests.rs b/crates/matrix-sdk-base/src/event_cache/store/integration_tests.rs index 0c4f36bbb..10651d446 100644 --- a/crates/matrix-sdk-base/src/event_cache/store/integration_tests.rs +++ b/crates/matrix-sdk-base/src/event_cache/store/integration_tests.rs @@ -21,7 +21,9 @@ use matrix_sdk_common::{ AlgorithmInfo, DecryptedRoomEvent, EncryptionInfo, SyncTimelineEvent, TimelineEventKind, VerificationState, }, - linked_chunk::{ChunkContent, Position, Update}, + linked_chunk::{ + ChunkContent, LinkedChunk, LinkedChunkBuilder, Position, RawLinkedChunk, Update, + }, }; use matrix_sdk_test::{event_factory::EventFactory, ALICE, DEFAULT_TEST_ROOM_ID}; use ruma::{ @@ -31,7 +33,7 @@ use ruma::{ use super::DynEventCacheStore; use crate::{ - event_cache::Gap, + event_cache::{Event, Gap}, media::{MediaFormat, MediaRequestParameters, MediaThumbnailSettings}, }; @@ -119,6 +121,12 @@ pub trait EventCacheStoreIntegrationTests { async fn test_clear_all_rooms_chunks(&self); } +fn rebuild_linked_chunk( + raws: Vec>, +) -> Option> { + LinkedChunkBuilder::from_raw_parts(raws).build().unwrap() +} + #[cfg_attr(target_arch = "wasm32", async_trait(?Send))] #[cfg_attr(not(target_arch = "wasm32"), async_trait)] impl EventCacheStoreIntegrationTests for DynEventCacheStore { @@ -332,7 +340,8 @@ impl EventCacheStoreIntegrationTests for DynEventCacheStore { .unwrap(); // The linked chunk is correctly reloaded. - let lc = self.reload_linked_chunk(room_id).await.unwrap().expect("linked chunk not empty"); + let raws = self.reload_linked_chunk(room_id).await.unwrap(); + let lc = rebuild_linked_chunk(raws).expect("linked chunk not empty"); let mut chunks = lc.chunks(); @@ -373,7 +382,8 @@ impl EventCacheStoreIntegrationTests for DynEventCacheStore { async fn test_rebuild_empty_linked_chunk(&self) { // 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()); + let raw_parts = self.reload_linked_chunk(&DEFAULT_TEST_ROOM_ID).await.unwrap(); + assert!(rebuild_linked_chunk(raw_parts).is_none()); } async fn test_clear_all_rooms_chunks(&self) { @@ -424,15 +434,15 @@ impl EventCacheStoreIntegrationTests for DynEventCacheStore { .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()); + assert!(rebuild_linked_chunk(self.reload_linked_chunk(r0).await.unwrap()).is_some()); + assert!(rebuild_linked_chunk(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()); + assert!(rebuild_linked_chunk(self.reload_linked_chunk(r0).await.unwrap()).is_none()); + assert!(rebuild_linked_chunk(self.reload_linked_chunk(r1).await.unwrap()).is_none()); } } diff --git a/crates/matrix-sdk-base/src/event_cache/store/memory_store.rs b/crates/matrix-sdk-base/src/event_cache/store/memory_store.rs index 8f921b580..02aeba58f 100644 --- a/crates/matrix-sdk-base/src/event_cache/store/memory_store.rs +++ b/crates/matrix-sdk-base/src/event_cache/store/memory_store.rs @@ -16,13 +16,13 @@ use std::{collections::HashMap, num::NonZeroUsize, sync::RwLock as StdRwLock, ti use async_trait::async_trait; use matrix_sdk_common::{ - linked_chunk::{relational::RelationalLinkedChunk, LinkedChunk, LinkedChunkBuilder, Update}, + linked_chunk::{relational::RelationalLinkedChunk, RawLinkedChunk, Update}, ring_buffer::RingBuffer, store_locks::memory_store_helper::try_take_leased_lock, }; use ruma::{MxcUri, OwnedMxcUri, RoomId}; -use super::{EventCacheStore, EventCacheStoreError, Result, DEFAULT_CHUNK_CAPACITY}; +use super::{EventCacheStore, EventCacheStoreError, Result}; use crate::{ event_cache::{Event, Gap}, media::{MediaRequestParameters, UniqueKey as _}, @@ -96,23 +96,12 @@ impl EventCacheStore for MemoryStore { async fn reload_linked_chunk( &self, room_id: &RoomId, - ) -> Result>, Self::Error> { + ) -> Result>, Self::Error> { let inner = self.inner.read().unwrap(); - - let mut builder = LinkedChunkBuilder::new(); - inner .events - .reload_chunks(room_id, &mut builder) - .map_err(|err| EventCacheStoreError::InvalidData { details: err })?; - - builder.with_update_history(); - - let result = builder.build().map_err(|err| EventCacheStoreError::InvalidData { - details: format!("when rebuilding a linked chunk: {err}"), - })?; - - Ok(result) + .reload_chunks(room_id) + .map_err(|err| EventCacheStoreError::InvalidData { details: err }) } async fn clear_all_rooms_chunks(&self) -> Result<(), Self::Error> { 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 50707a6dd..4251eb898 100644 --- a/crates/matrix-sdk-base/src/event_cache/store/traits.rs +++ b/crates/matrix-sdk-base/src/event_cache/store/traits.rs @@ -16,7 +16,7 @@ use std::{fmt, sync::Arc}; use async_trait::async_trait; use matrix_sdk_common::{ - linked_chunk::{LinkedChunk, Update}, + linked_chunk::{RawLinkedChunk, Update}, AsyncTraitDeps, }; use ruma::{MxcUri, RoomId}; @@ -29,6 +29,7 @@ use crate::{ /// A default capacity for linked chunks, when manipulating in conjunction with /// an `EventCacheStore` implementation. +// TODO: move back? pub const DEFAULT_CHUNK_CAPACITY: usize = 128; /// An abstract trait that can be used to implement different store backends @@ -56,11 +57,12 @@ pub trait EventCacheStore: AsyncTraitDeps { updates: Vec>, ) -> Result<(), Self::Error>; - /// Reconstruct a full linked chunk by reloading it from storage. + /// Return all the raw components of a linked chunk, so the caller may + /// reconstruct the linked chunk later. async fn reload_linked_chunk( &self, room_id: &RoomId, - ) -> Result>, Self::Error>; + ) -> Result>, Self::Error>; /// Clear persisted events for all the rooms. /// @@ -190,7 +192,7 @@ impl EventCacheStore for EraseEventCacheStoreError { async fn reload_linked_chunk( &self, room_id: &RoomId, - ) -> Result>, Self::Error> { + ) -> Result>, Self::Error> { self.0.reload_linked_chunk(room_id).await.map_err(Into::into) } diff --git a/crates/matrix-sdk-common/src/linked_chunk/builder.rs b/crates/matrix-sdk-common/src/linked_chunk/builder.rs index 16550866c..0bcb3e20f 100644 --- a/crates/matrix-sdk-common/src/linked_chunk/builder.rs +++ b/crates/matrix-sdk-common/src/linked_chunk/builder.rs @@ -21,7 +21,7 @@ use tracing::error; use super::{ Chunk, ChunkContent, ChunkIdentifier, ChunkIdentifierGenerator, Ends, LinkedChunk, - ObservableUpdates, + ObservableUpdates, RawLinkedChunk, }; /// A temporary chunk representation in the [`LinkedChunkBuilder`]. @@ -260,6 +260,22 @@ impl LinkedChunkBuilder { Ok(Some(LinkedChunk { links, chunk_identifier_generator, updates, marker: PhantomData })) } + + /// Fills a linked chunk builder from all the given raw parts. + pub fn from_raw_parts(raws: Vec>) -> Self { + let mut this = Self::new(); + for raw in raws { + match raw.content { + ChunkContent::Gap(gap) => { + this.push_gap(raw.previous, raw.id, raw.next, gap); + } + ChunkContent::Items(vec) => { + this.push_items(raw.previous, raw.id, raw.next, vec); + } + } + } + this + } } #[derive(thiserror::Error, Debug)] diff --git a/crates/matrix-sdk-common/src/linked_chunk/mod.rs b/crates/matrix-sdk-common/src/linked_chunk/mod.rs index 40f3fbb01..a0cb1a820 100644 --- a/crates/matrix-sdk-common/src/linked_chunk/mod.rs +++ b/crates/matrix-sdk-common/src/linked_chunk/mod.rs @@ -1419,6 +1419,22 @@ impl EmptyChunk { } } +/// The raw representation of a linked chunk, as persisted in storage. +#[derive(Debug)] +pub struct RawLinkedChunk { + /// Content section of the linked chunk. + pub content: ChunkContent, + + /// Link to the previous chunk, via its identifier. + pub previous: Option, + + /// Current chunk's identifier. + pub id: ChunkIdentifier, + + /// Link to the next chunk, via its identifier. + pub next: Option, +} + #[cfg(test)] mod tests { use std::{ diff --git a/crates/matrix-sdk-common/src/linked_chunk/relational.rs b/crates/matrix-sdk-common/src/linked_chunk/relational.rs index 27f137406..e823e927c 100644 --- a/crates/matrix-sdk-common/src/linked_chunk/relational.rs +++ b/crates/matrix-sdk-common/src/linked_chunk/relational.rs @@ -17,7 +17,7 @@ use ruma::{OwnedRoomId, RoomId}; -use super::LinkedChunkBuilder; +use super::{ChunkContent, RawLinkedChunk}; use crate::linked_chunk::{ChunkIdentifier, Position, Update}; /// A row of the [`RelationalLinkedChunk::chunks`]. @@ -290,11 +290,12 @@ where /// /// Return an error result if the data was malformed in the struct, with a /// string message explaining details about the error. - pub fn reload_chunks( + pub fn reload_chunks( &self, room_id: &RoomId, - builder: &mut LinkedChunkBuilder, - ) -> Result<(), String> { + ) -> Result>, String> { + let mut result = Vec::new(); + for chunk_row in self.chunks.iter().filter(|chunk| chunk.room_id == room_id) { // Find all items that correspond to the chunk. let mut items = self @@ -309,12 +310,12 @@ where let Some(first) = items.peek() else { // The only possibility is that we created an empty items chunk; mark it as // such, and continue. - builder.push_items( - chunk_row.previous_chunk, - chunk_row.chunk, - chunk_row.next_chunk, - Vec::new(), - ); + result.push(RawLinkedChunk { + content: ChunkContent::Items(Vec::new()), + previous: chunk_row.previous_chunk, + id: chunk_row.chunk, + next: chunk_row.next_chunk, + }); continue; }; @@ -339,12 +340,14 @@ where // Sort them by their position. collected_items.sort_unstable_by_key(|(_item, index)| *index); - builder.push_items( - chunk_row.previous_chunk, - chunk_row.chunk, - chunk_row.next_chunk, - collected_items.into_iter().map(|(item, _index)| item), - ); + result.push(RawLinkedChunk { + content: ChunkContent::Items( + collected_items.into_iter().map(|(item, _index)| item).collect(), + ), + previous: chunk_row.previous_chunk, + id: chunk_row.chunk, + next: chunk_row.next_chunk, + }); } Either::Gap(gap) => { @@ -358,17 +361,17 @@ where )); } - builder.push_gap( - chunk_row.previous_chunk, - chunk_row.chunk, - chunk_row.next_chunk, - gap.clone(), - ); + result.push(RawLinkedChunk { + content: ChunkContent::Gap(gap.clone()), + previous: chunk_row.previous_chunk, + id: chunk_row.chunk, + next: chunk_row.next_chunk, + }); } } } - Ok(()) + Ok(result) } } @@ -383,6 +386,7 @@ mod tests { use ruma::room_id; use super::{ChunkIdentifier as CId, *}; + use crate::linked_chunk::LinkedChunkBuilder; #[test] fn test_new_items_chunk() { @@ -828,25 +832,17 @@ mod tests { } #[test] - fn test_rebuild_empty_linked_chunk() { - let mut builder = LinkedChunkBuilder::<3, _, _>::new(); - + fn test_reload_empty_linked_chunk() { let room_id = room_id!("!r0:matrix.org"); - // When I rebuild a linked chunk from an empty store, + // When I reload the linked chunk components from an empty store, let relational_linked_chunk = RelationalLinkedChunk::::new(); - relational_linked_chunk.reload_chunks(room_id, &mut builder).unwrap(); - - let lc = builder.build().expect("building succeeds"); - - // The builder won't return a linked chunk. - assert!(lc.is_none()); + let result = relational_linked_chunk.reload_chunks(room_id).unwrap(); + assert!(result.is_empty()); } #[test] fn test_reload_linked_chunk_with_empty_items() { - let mut builder = LinkedChunkBuilder::<3, _, _>::new(); - let room_id = room_id!("!r0:matrix.org"); let mut relational_linked_chunk = RelationalLinkedChunk::::new(); @@ -858,9 +854,8 @@ mod tests { ); // It correctly gets reloaded as such. - relational_linked_chunk.reload_chunks(room_id, &mut builder).unwrap(); - - let lc = builder + let raws = relational_linked_chunk.reload_chunks(room_id).unwrap(); + let lc = LinkedChunkBuilder::<3, _, _>::from_raw_parts(raws) .build() .expect("building succeeds") .expect("this leads to a non-empty linked chunk"); @@ -870,8 +865,6 @@ mod tests { #[test] fn test_rebuild_linked_chunk() { - let mut builder = LinkedChunkBuilder::<3, _, _>::new(); - let room_id = room_id!("!r0:matrix.org"); let mut relational_linked_chunk = RelationalLinkedChunk::::new(); @@ -896,9 +889,8 @@ mod tests { ], ); - relational_linked_chunk.reload_chunks(room_id, &mut builder).unwrap(); - - let lc = builder + let raws = relational_linked_chunk.reload_chunks(room_id).unwrap(); + let lc = LinkedChunkBuilder::<3, _, _>::from_raw_parts(raws) .build() .expect("building succeeds") .expect("this leads to a non-empty linked chunk"); diff --git a/crates/matrix-sdk-sqlite/src/event_cache_store.rs b/crates/matrix-sdk-sqlite/src/event_cache_store.rs index 08c8eb584..be255445d 100644 --- a/crates/matrix-sdk-sqlite/src/event_cache_store.rs +++ b/crates/matrix-sdk-sqlite/src/event_cache_store.rs @@ -21,11 +21,8 @@ use std::{borrow::Cow, fmt, path::Path, sync::Arc}; use async_trait::async_trait; use deadpool_sqlite::{Object as SqliteAsyncConn, Pool as SqlitePool, Runtime}; use matrix_sdk_base::{ - event_cache::{ - store::{EventCacheStore, DEFAULT_CHUNK_CAPACITY}, - Event, Gap, - }, - linked_chunk::{ChunkContent, ChunkIdentifier, LinkedChunk, LinkedChunkBuilder, Update}, + event_cache::{store::EventCacheStore, Event, Gap}, + linked_chunk::{ChunkContent, ChunkIdentifier, RawLinkedChunk, Update}, media::{MediaRequestParameters, UniqueKey}, }; use matrix_sdk_store_encryption::StoreCipher; @@ -147,49 +144,11 @@ impl SqliteEventCacheStore { )) } - async fn load_chunks(&self, room_id: &RoomId) -> Result> { - let room_id = room_id.to_owned(); - let hashed_room_id = self.encode_key(keys::LINKED_CHUNKS, &room_id); - - let this = self.clone(); - - let result = self - .acquire() - .await? - .with_transaction(move |txn| -> Result<_> { - let mut items = Vec::new(); - - // Use `ORDER BY id` to get a deterministic ordering for testing purposes. - for data in txn - .prepare( - "SELECT id, previous, next, type FROM linked_chunks WHERE room_id = ? ORDER BY id", - )? - .query_map((&hashed_room_id,), Self::map_row_to_chunk)? - { - let (id, previous, next, chunk_type) = data?; - let new = txn.rebuild_chunk( - &this, - &hashed_room_id, - previous, - id, - next, - chunk_type.as_str(), - )?; - items.push(new); - } - - Ok(items) - }) - .await?; - - Ok(result) - } - async fn load_chunk_with_id( &self, room_id: &RoomId, chunk_id: ChunkIdentifier, - ) -> Result { + ) -> Result> { let hashed_room_id = self.encode_key(keys::LINKED_CHUNKS, room_id); let this = self.clone(); @@ -217,7 +176,7 @@ trait TransactionExtForLinkedChunks { index: u64, next: Option, chunk_type: &str, - ) -> Result; + ) -> Result>; fn load_gap_content( &self, @@ -243,7 +202,7 @@ impl TransactionExtForLinkedChunks for Transaction<'_> { id: u64, next: Option, chunk_type: &str, - ) -> Result { + ) -> Result> { let previous = previous.map(ChunkIdentifier::new); let next = next.map(ChunkIdentifier::new); let id = ChunkIdentifier::new(id); @@ -317,14 +276,6 @@ impl TransactionExtForLinkedChunks for Transaction<'_> { } } -struct RawLinkedChunk { - content: ChunkContent, - - previous: Option, - id: ChunkIdentifier, - next: Option, -} - async fn create_pool(path: &Path) -> Result { fs::create_dir_all(path).await.map_err(OpenStoreError::CreateDir)?; let cfg = deadpool_sqlite::Config::new(path.join("matrix-sdk-event-cache.sqlite3")); @@ -586,27 +537,42 @@ impl EventCacheStore for SqliteEventCacheStore { async fn reload_linked_chunk( &self, room_id: &RoomId, - ) -> Result>, Self::Error> { - let chunks = self.load_chunks(room_id).await?; + ) -> Result>, Self::Error> { + let room_id = room_id.to_owned(); + let hashed_room_id = self.encode_key(keys::LINKED_CHUNKS, &room_id); - let mut builder = LinkedChunkBuilder::new(); + let this = self.clone(); - for c in chunks { - match c.content { - ChunkContent::Gap(gap) => { - builder.push_gap(c.previous, c.id, c.next, gap); + let result = self + .acquire() + .await? + .with_transaction(move |txn| -> Result<_> { + let mut items = Vec::new(); + + // Use `ORDER BY id` to get a deterministic ordering for testing purposes. + for data in txn + .prepare( + "SELECT id, previous, next, type FROM linked_chunks WHERE room_id = ? ORDER BY id", + )? + .query_map((&hashed_room_id,), Self::map_row_to_chunk)? + { + let (id, previous, next, chunk_type) = data?; + let new = txn.rebuild_chunk( + &this, + &hashed_room_id, + previous, + id, + next, + chunk_type.as_str(), + )?; + items.push(new); } - ChunkContent::Items(items) => { - builder.push_items(c.previous, c.id, c.next, items); - } - } - } - builder.with_update_history(); + Ok(items) + }) + .await?; - builder.build().map_err(|err| Error::InvalidData { - details: format!("when rebuilding a linked chunk: {err}"), - }) + Ok(result) } async fn clear_all_rooms_chunks(&self) -> Result<(), Self::Error> { @@ -931,7 +897,7 @@ mod tests { .await .unwrap(); - let mut chunks = store.load_chunks(room_id).await.unwrap(); + let mut chunks = store.reload_linked_chunk(room_id).await.unwrap(); assert_eq!(chunks.len(), 3); @@ -982,7 +948,7 @@ mod tests { .await .unwrap(); - let mut chunks = store.load_chunks(room_id).await.unwrap(); + let mut chunks = store.reload_linked_chunk(room_id).await.unwrap(); assert_eq!(chunks.len(), 1); @@ -1030,7 +996,7 @@ mod tests { .await .unwrap(); - let mut chunks = store.load_chunks(room_id).await.unwrap(); + let mut chunks = store.reload_linked_chunk(room_id).await.unwrap(); assert_eq!(chunks.len(), 2); @@ -1103,7 +1069,7 @@ mod tests { .await .unwrap(); - let mut chunks = store.load_chunks(room_id).await.unwrap(); + let mut chunks = store.reload_linked_chunk(room_id).await.unwrap(); assert_eq!(chunks.len(), 1); @@ -1148,7 +1114,7 @@ mod tests { .await .unwrap(); - let mut chunks = store.load_chunks(room_id).await.unwrap(); + let mut chunks = store.reload_linked_chunk(room_id).await.unwrap(); assert_eq!(chunks.len(), 1); @@ -1207,7 +1173,7 @@ mod tests { .await .unwrap(); - let mut chunks = store.load_chunks(room_id).await.unwrap(); + let mut chunks = store.reload_linked_chunk(room_id).await.unwrap(); assert_eq!(chunks.len(), 1); @@ -1254,7 +1220,7 @@ mod tests { .await .unwrap(); - let mut chunks = store.load_chunks(room_id).await.unwrap(); + let mut chunks = store.reload_linked_chunk(room_id).await.unwrap(); assert_eq!(chunks.len(), 1); @@ -1305,7 +1271,7 @@ mod tests { .await .unwrap(); - let chunks = store.load_chunks(room_id).await.unwrap(); + let chunks = store.reload_linked_chunk(room_id).await.unwrap(); assert!(chunks.is_empty()); } @@ -1359,7 +1325,7 @@ mod tests { .unwrap(); // Check chunks from room 1. - let mut chunks_room1 = store.load_chunks(room1).await.unwrap(); + let mut chunks_room1 = store.reload_linked_chunk(room1).await.unwrap(); assert_eq!(chunks_room1.len(), 1); let c = chunks_room1.remove(0); @@ -1370,7 +1336,7 @@ mod tests { }); // Check chunks from room 2. - let mut chunks_room2 = store.load_chunks(room2).await.unwrap(); + let mut chunks_room2 = store.reload_linked_chunk(room2).await.unwrap(); assert_eq!(chunks_room2.len(), 1); let c = chunks_room2.remove(0); @@ -1415,7 +1381,7 @@ mod tests { // If the updates have been handled transactionally, then no new chunks should // have been added; failure of the second update leads to the first one being // rolled back. - let chunks = store.load_chunks(room_id).await.unwrap(); + let chunks = store.reload_linked_chunk(room_id).await.unwrap(); assert!(chunks.is_empty()); } } diff --git a/crates/matrix-sdk/src/event_cache/room/mod.rs b/crates/matrix-sdk/src/event_cache/room/mod.rs index 57a504a98..ee9586bed 100644 --- a/crates/matrix-sdk/src/event_cache/room/mod.rs +++ b/crates/matrix-sdk/src/event_cache/room/mod.rs @@ -573,8 +573,8 @@ mod private { use matrix_sdk_base::{ deserialized_responses::{SyncTimelineEvent, TimelineEventKind}, - event_cache::store::EventCacheStoreLock, - linked_chunk::Update, + event_cache::store::{EventCacheStoreError, EventCacheStoreLock}, + linked_chunk::{LinkedChunkBuilder, Update}, }; use once_cell::sync::OnceCell; use ruma::{serde::Raw, OwnedRoomId}; @@ -614,8 +614,15 @@ mod private { ) -> Result { let events = if let Some(store) = store.get() { let locked = store.lock().await?; - let chunks = locked.reload_linked_chunk(&room).await?; - RoomEvents::with_initial_chunks(chunks) + let raw_chunks = locked.reload_linked_chunk(&room).await?; + + let mut builder = LinkedChunkBuilder::from_raw_parts(raw_chunks); + builder.with_update_history(); + let linked_chunk = builder.build().map_err(|err| { + EventCacheStoreError::InvalidData { details: err.to_string() } + })?; + + RoomEvents::with_initial_chunks(linked_chunk) } else { RoomEvents::default() }; @@ -998,6 +1005,8 @@ mod tests { #[cfg(not(target_arch = "wasm32"))] // This uses the cross-process lock, so needs time support. #[async_test] async fn test_write_to_storage() { + use matrix_sdk_base::linked_chunk::LinkedChunkBuilder; + let room_id = room_id!("!galette:saucisse.bzh"); let f = EventFactory::new().room(room_id).sender(user_id!("@ben:saucisse.bzh")); @@ -1034,7 +1043,9 @@ mod tests { .await .unwrap(); - let linked_chunk = event_cache_store.reload_linked_chunk(room_id).await.unwrap().unwrap(); + let raws = event_cache_store.reload_linked_chunk(room_id).await.unwrap(); + let linked_chunk = + LinkedChunkBuilder::<3, _, _>::from_raw_parts(raws).build().unwrap().unwrap(); assert_eq!(linked_chunk.chunks().count(), 3); @@ -1065,6 +1076,7 @@ mod tests { #[cfg(not(target_arch = "wasm32"))] // This uses the cross-process lock, so needs time support. #[async_test] async fn test_write_to_storage_strips_bundled_relations() { + use matrix_sdk_base::linked_chunk::LinkedChunkBuilder; use ruma::events::BundledMessageLikeRelations; let room_id = room_id!("!galette:saucisse.bzh"); @@ -1121,7 +1133,9 @@ mod tests { } // The one in storage does not. - let linked_chunk = event_cache_store.reload_linked_chunk(room_id).await.unwrap().unwrap(); + let raws = event_cache_store.reload_linked_chunk(room_id).await.unwrap(); + let linked_chunk = + LinkedChunkBuilder::<3, _, _>::from_raw_parts(raws).build().unwrap().unwrap(); assert_eq!(linked_chunk.chunks().count(), 1); @@ -1144,6 +1158,8 @@ mod tests { #[cfg(not(target_arch = "wasm32"))] // This uses the cross-process lock, so needs time support. #[async_test] async fn test_clear() { + use matrix_sdk_base::linked_chunk::LinkedChunkBuilder; + use crate::{assert_let_timeout, event_cache::RoomEventCacheUpdate}; let room_id = room_id!("!galette:saucisse.bzh"); @@ -1244,11 +1260,13 @@ mod tests { assert!(items.is_empty()); // The event cache store too. - let reloaded = event_cache_store.reload_linked_chunk(room_id).await.unwrap(); + let raws = event_cache_store.reload_linked_chunk(room_id).await.unwrap(); + let linked_chunk = LinkedChunkBuilder::<3, _, _>::from_raw_parts(raws).build().unwrap(); + // Note: while the event cache store could return `None` here, clearing it will // reset it to its initial form, maintaining the invariant that it // contains a single items chunk that's empty. - let linked_chunk = reloaded.unwrap(); + let linked_chunk = linked_chunk.unwrap(); assert_eq!(linked_chunk.num_items(), 0); }