Skip to content

Commit 9366bc8

Browse files
committed
refactor(sdk): Remove FrozenSlidingSync.
This patch removes `FrozenSlidingSync`. Its unique field is supposed to be stored in the crypto store.
1 parent 0c19350 commit 9366bc8

File tree

3 files changed

+60
-252
lines changed

3 files changed

+60
-252
lines changed

crates/matrix-sdk/src/sliding_sync/builder.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -246,8 +246,7 @@ impl SlidingSyncBuilder {
246246
}
247247

248248
// Reload existing state from the cache.
249-
let restored_fields =
250-
restore_sliding_sync_state(&client, &self.storage_key, &lists).await?;
249+
let restored_fields = restore_sliding_sync_state(&client, &self.storage_key).await?;
251250

252251
let pos = if let Some(fields) = restored_fields {
253252
#[cfg(feature = "e2e-encryption")]

crates/matrix-sdk/src/sliding_sync/cache.rs

Lines changed: 51 additions & 208 deletions
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,12 @@
44
//! same cache. It helps to define what it sometimes called a “cold start”, or a
55
//! “fast start”.
66
7-
use std::collections::BTreeMap;
8-
97
use matrix_sdk_base::{StateStore, StoreError};
108
use matrix_sdk_common::timer;
119
use ruma::UserId;
1210
use tracing::{trace, warn};
1311

14-
use super::{
15-
FrozenSlidingSync, FrozenSlidingSyncList, SlidingSync, SlidingSyncList,
16-
SlidingSyncPositionMarkers,
17-
};
12+
use super::{FrozenSlidingSyncList, SlidingSync, SlidingSyncPositionMarkers};
1813
#[cfg(feature = "e2e-encryption")]
1914
use crate::sliding_sync::FrozenSlidingSyncPos;
2015
use crate::{sliding_sync::SlidingSyncListCachePolicy, Client, Result};
@@ -48,30 +43,6 @@ async fn invalidate_cached_list(
4843
let _ = storage.remove_custom_value(storage_key_for_list.as_bytes()).await;
4944
}
5045

51-
/// Clean the storage for everything related to `SlidingSync` and all known
52-
/// lists.
53-
async fn clean_storage(
54-
client: &Client,
55-
storage_key: &str,
56-
lists: &BTreeMap<String, SlidingSyncList>,
57-
) {
58-
let storage = client.state_store();
59-
for list_name in lists.keys() {
60-
invalidate_cached_list(storage, storage_key, list_name).await;
61-
}
62-
let instance_storage_key = format_storage_key_for_sliding_sync(storage_key);
63-
let _ = storage.remove_custom_value(instance_storage_key.as_bytes()).await;
64-
65-
#[cfg(feature = "e2e-encryption")]
66-
if let Some(olm_machine) = &*client.olm_machine().await {
67-
// Invalidate the value stored for the TERRIBLE HACK.
68-
let _ = olm_machine
69-
.store()
70-
.set_custom_value(&instance_storage_key, "".as_bytes().to_vec())
71-
.await;
72-
}
73-
}
74-
7546
/// Store the `SlidingSync`'s state in the storage.
7647
pub(super) async fn store_sliding_sync_state(
7748
sliding_sync: &SlidingSync,
@@ -83,15 +54,6 @@ pub(super) async fn store_sliding_sync_state(
8354
trace!(storage_key, "Saving a `SlidingSync` to the state store");
8455
let storage = sliding_sync.inner.client.state_store();
8556

86-
// Write this `SlidingSync` instance, as a `FrozenSlidingSync` instance, inside
87-
// the store.
88-
storage
89-
.set_custom_value(
90-
instance_storage_key.as_bytes(),
91-
serde_json::to_vec(&FrozenSlidingSync::new())?,
92-
)
93-
.await?;
94-
9557
#[cfg(feature = "e2e-encryption")]
9658
{
9759
let position = _position;
@@ -194,7 +156,6 @@ pub(super) struct RestoredFields {
194156
pub(super) async fn restore_sliding_sync_state(
195157
client: &Client,
196158
storage_key: &str,
197-
lists: &BTreeMap<String, SlidingSyncList>,
198159
) -> Result<Option<RestoredFields>> {
199160
let _timer = timer!(format!("loading sliding sync {storage_key} state from DB"));
200161

@@ -210,61 +171,17 @@ pub(super) async fn restore_sliding_sync_state(
210171
}
211172
}
212173

213-
let storage = client.state_store();
214174
let instance_storage_key = format_storage_key_for_sliding_sync(storage_key);
215175

216176
// Preload the `SlidingSync` object from the cache.
217-
match storage
218-
.get_custom_value(instance_storage_key.as_bytes())
219-
.await?
220-
.map(|custom_value| serde_json::from_slice::<FrozenSlidingSync>(&custom_value))
221-
{
222-
// `SlidingSync` has been found and successfully deserialized.
223-
Some(Ok(FrozenSlidingSync { to_device_since })) => {
224-
trace!("Successfully read the `SlidingSync` from the cache");
225-
// Only update the to-device token if we failed to read it from the crypto store
226-
// above.
227-
if restored_fields.to_device_token.is_none() {
228-
restored_fields.to_device_token = to_device_since;
229-
}
230-
231-
#[cfg(feature = "e2e-encryption")]
232-
{
233-
if let Some(olm_machine) = &*client.olm_machine().await {
234-
if let Ok(Some(blob)) =
235-
olm_machine.store().get_custom_value(&instance_storage_key).await
236-
{
237-
if let Ok(frozen_pos) =
238-
serde_json::from_slice::<FrozenSlidingSyncPos>(&blob)
239-
{
240-
trace!("Successfully read the `Sliding Sync` pos from the crypto store cache");
241-
restored_fields.pos = frozen_pos.pos;
242-
}
243-
}
244-
}
177+
#[cfg(feature = "e2e-encryption")]
178+
if let Some(olm_machine) = &*client.olm_machine().await {
179+
if let Ok(Some(blob)) = olm_machine.store().get_custom_value(&instance_storage_key).await {
180+
if let Ok(frozen_pos) = serde_json::from_slice::<FrozenSlidingSyncPos>(&blob) {
181+
trace!("Successfully read the `Sliding Sync` pos from the crypto store cache");
182+
restored_fields.pos = frozen_pos.pos;
245183
}
246184
}
247-
248-
// `SlidingSync` has been found, but it wasn't possible to deserialize it. It's
249-
// declared as obsolete. The main reason might be that the internal
250-
// representation of a `SlidingSync` might have changed.
251-
// Instead of considering this as a strong error, we remove
252-
// the entry from the cache and keep `SlidingSync` in its initial
253-
// state.
254-
Some(Err(_)) => {
255-
warn!(
256-
"failed to deserialize `SlidingSync` from the cache, it is obsolete; removing the cache entry!"
257-
);
258-
259-
// Let's clear everything and stop here.
260-
clean_storage(client, storage_key, lists).await;
261-
262-
return Ok(None);
263-
}
264-
265-
None => {
266-
trace!("No Sliding Sync object in the cache");
267-
}
268185
}
269186

270187
Ok(Some(restored_fields))
@@ -274,13 +191,12 @@ pub(super) async fn restore_sliding_sync_state(
274191
mod tests {
275192
use std::sync::{Arc, RwLock};
276193

277-
use assert_matches::assert_matches;
278194
use matrix_sdk_test::async_test;
279195

280196
use super::{
281-
clean_storage, format_storage_key_for_sliding_sync,
197+
super::SlidingSyncList, format_storage_key_for_sliding_sync,
282198
format_storage_key_for_sliding_sync_list, format_storage_key_prefix,
283-
restore_sliding_sync_state, store_sliding_sync_state, SlidingSyncList,
199+
restore_sliding_sync_state, store_sliding_sync_state,
284200
};
285201
use crate::{test_utils::logged_in_client, Result};
286202

@@ -291,30 +207,26 @@ mod tests {
291207

292208
let store = client.state_store();
293209

294-
// Store entries don't exist.
295-
assert!(store
296-
.get_custom_value(format_storage_key_for_sliding_sync("hello").as_bytes())
297-
.await?
298-
.is_none());
210+
let sync_id = "test-sync-id";
211+
let storage_key = format_storage_key_prefix(sync_id, client.user_id().unwrap());
299212

213+
// Store entries don't exist.
300214
assert!(store
301215
.get_custom_value(
302-
format_storage_key_for_sliding_sync_list("hello", "list_foo").as_bytes()
216+
format_storage_key_for_sliding_sync_list(&storage_key, "list_foo").as_bytes()
303217
)
304218
.await?
305219
.is_none());
306220

307221
assert!(store
308222
.get_custom_value(
309-
format_storage_key_for_sliding_sync_list("hello", "list_bar").as_bytes()
223+
format_storage_key_for_sliding_sync_list(&storage_key, "list_bar").as_bytes()
310224
)
311225
.await?
312226
.is_none());
313227

314228
// Create a new `SlidingSync` instance, and store it.
315229
let storage_key = {
316-
let sync_id = "test-sync-id";
317-
let storage_key = format_storage_key_prefix(sync_id, client.user_id().unwrap());
318230
let sliding_sync = client
319231
.sliding_sync(sync_id)?
320232
.add_cached_list(SlidingSyncList::builder("list_foo"))
@@ -340,20 +252,15 @@ mod tests {
340252
storage_key
341253
};
342254

343-
// Store entries now exist for the sliding sync object and list_foo.
344-
assert!(store
345-
.get_custom_value(format_storage_key_for_sliding_sync(&storage_key).as_bytes())
346-
.await?
347-
.is_some());
348-
255+
// Store entries now exist for `list_foo`.
349256
assert!(store
350257
.get_custom_value(
351258
format_storage_key_for_sliding_sync_list(&storage_key, "list_foo").as_bytes()
352259
)
353260
.await?
354261
.is_some());
355262

356-
// But not for list_bar.
263+
// But not for `list_bar`.
357264
assert!(store
358265
.get_custom_value(
359266
format_storage_key_for_sliding_sync_list(&storage_key, "list_bar").as_bytes()
@@ -362,83 +269,52 @@ mod tests {
362269
.is_none());
363270

364271
// Create a new `SlidingSync`, and it should be read from the cache.
365-
let storage_key = {
366-
let sync_id = "test-sync-id";
367-
let storage_key = format_storage_key_prefix(sync_id, client.user_id().unwrap());
368-
let max_number_of_room_stream = Arc::new(RwLock::new(None));
369-
let cloned_stream = max_number_of_room_stream.clone();
370-
let sliding_sync = client
371-
.sliding_sync(sync_id)?
372-
.add_cached_list(SlidingSyncList::builder("list_foo").once_built(move |list| {
373-
// In the `once_built()` handler, nothing has been read from the cache yet.
374-
assert_eq!(list.maximum_number_of_rooms(), None);
375-
376-
let mut stream = cloned_stream.write().unwrap();
377-
*stream = Some(list.maximum_number_of_rooms_stream());
378-
list
379-
}))
380-
.await?
381-
.add_list(SlidingSyncList::builder("list_bar"))
382-
.build()
383-
.await?;
384-
385-
// Check the list' state.
386-
{
387-
let lists = sliding_sync.inner.lists.read().await;
388-
389-
// This one was cached.
390-
let list_foo = lists.get("list_foo").unwrap();
391-
assert_eq!(list_foo.maximum_number_of_rooms(), Some(42));
392-
393-
// This one wasn't.
394-
let list_bar = lists.get("list_bar").unwrap();
395-
assert_eq!(list_bar.maximum_number_of_rooms(), None);
396-
}
397-
398-
// The maximum number of rooms reloaded from the cache should have been
399-
// published.
400-
{
401-
let mut stream =
402-
max_number_of_room_stream.write().unwrap().take().expect("stream must be set");
403-
let initial_max_number_of_rooms =
404-
stream.next().await.expect("stream must have emitted something");
405-
assert_eq!(initial_max_number_of_rooms, Some(42));
406-
}
272+
let max_number_of_room_stream = Arc::new(RwLock::new(None));
273+
let cloned_stream = max_number_of_room_stream.clone();
274+
let sliding_sync = client
275+
.sliding_sync(sync_id)?
276+
.add_cached_list(SlidingSyncList::builder("list_foo").once_built(move |list| {
277+
// In the `once_built()` handler, nothing has been read from the cache yet.
278+
assert_eq!(list.maximum_number_of_rooms(), None);
279+
280+
let mut stream = cloned_stream.write().unwrap();
281+
*stream = Some(list.maximum_number_of_rooms_stream());
282+
list
283+
}))
284+
.await?
285+
.add_list(SlidingSyncList::builder("list_bar"))
286+
.build()
287+
.await?;
407288

408-
// Clean the cache.
289+
// Check the list' state.
290+
{
409291
let lists = sliding_sync.inner.lists.read().await;
410-
clean_storage(&client, &storage_key, &lists).await;
411-
storage_key
412-
};
413292

414-
// Store entries don't exist.
415-
assert!(store
416-
.get_custom_value(format_storage_key_for_sliding_sync(&storage_key).as_bytes())
417-
.await?
418-
.is_none());
293+
// This one was cached.
294+
let list_foo = lists.get("list_foo").unwrap();
295+
assert_eq!(list_foo.maximum_number_of_rooms(), Some(42));
419296

420-
assert!(store
421-
.get_custom_value(
422-
format_storage_key_for_sliding_sync_list(&storage_key, "list_foo").as_bytes()
423-
)
424-
.await?
425-
.is_none());
297+
// This one wasn't.
298+
let list_bar = lists.get("list_bar").unwrap();
299+
assert_eq!(list_bar.maximum_number_of_rooms(), None);
300+
}
426301

427-
assert!(store
428-
.get_custom_value(
429-
format_storage_key_for_sliding_sync_list(&storage_key, "list_bar").as_bytes()
430-
)
431-
.await?
432-
.is_none());
302+
// The maximum number of rooms reloaded from the cache should have been
303+
// published.
304+
{
305+
let mut stream =
306+
max_number_of_room_stream.write().unwrap().take().expect("stream must be set");
307+
let initial_max_number_of_rooms =
308+
stream.next().await.expect("stream must have emitted something");
309+
assert_eq!(initial_max_number_of_rooms, Some(42));
310+
}
433311

434312
Ok(())
435313
}
436314

437315
#[cfg(feature = "e2e-encryption")]
438316
#[async_test]
439317
async fn test_sliding_sync_high_level_cache_and_restore() -> Result<()> {
440-
use crate::sliding_sync::FrozenSlidingSync;
441-
442318
let client = logged_in_client(Some("https://foo.bar".to_owned())).await;
443319

444320
let sync_id = "test-sync-id";
@@ -465,21 +341,10 @@ mod tests {
465341
store_sliding_sync_state(&sliding_sync, &position_guard).await?;
466342
}
467343

468-
// The delta token has been correctly written to the state store (but not the
469-
// to_device_since, since it's in the other store).
470-
let state_store = client.state_store();
471-
assert_matches!(
472-
state_store.get_custom_value(full_storage_key.as_bytes()).await?,
473-
Some(bytes) => {
474-
let deserialized: FrozenSlidingSync = serde_json::from_slice(&bytes)?;
475-
assert!(deserialized.to_device_since.is_none());
476-
}
477-
);
478-
479344
// Ok, forget about the sliding sync, let's recreate one from scratch.
480345
drop(sliding_sync);
481346

482-
let restored_fields = restore_sliding_sync_state(&client, &storage_key_prefix, &[].into())
347+
let restored_fields = restore_sliding_sync_state(&client, &storage_key_prefix)
483348
.await?
484349
.expect("must have restored sliding sync fields");
485350

@@ -496,28 +361,6 @@ mod tests {
496361
assert!(olm_machine.store().next_batch_token().await?.is_none());
497362
}
498363

499-
let to_device_token = "to_device_token".to_owned();
500-
501-
// Put that delta-token in the state store.
502-
let state_store = client.state_store();
503-
state_store
504-
.set_custom_value(
505-
full_storage_key.as_bytes(),
506-
serde_json::to_vec(&FrozenSlidingSync {
507-
to_device_since: Some(to_device_token.clone()),
508-
})?,
509-
)
510-
.await?;
511-
512-
let restored_fields = restore_sliding_sync_state(&client, &storage_key_prefix, &[].into())
513-
.await?
514-
.expect("must have restored fields");
515-
516-
// After restoring, the to-device since token, and the stream position could be
517-
// read from the state store.
518-
assert_eq!(restored_fields.to_device_token.unwrap(), to_device_token);
519-
assert_eq!(restored_fields.pos.unwrap(), pos);
520-
521364
Ok(())
522365
}
523366
}

0 commit comments

Comments
 (0)