@@ -40,8 +40,8 @@ impl Deduplicator {
40
40
/// will learn over time by using a Bloom filter which events are
41
41
/// duplicates or not.
42
42
///
43
- /// When the persistent storage is enabled by default, this constructor
44
- /// (and the associated variant) will be removed.
43
+ /// When the persistent storage of the event cache is enabled by default,
44
+ /// this constructor (and the associated variant) will be removed.
45
45
pub fn new_memory_based ( ) -> Self {
46
46
Self :: InMemory ( BloomFilterDeduplicator :: new ( ) )
47
47
}
@@ -51,9 +51,9 @@ impl Deduplicator {
51
51
///
52
52
/// This deduplicator is stateless.
53
53
///
54
- /// When the persistent storage is enabled by default, this will become the
55
- /// default, and [`Deduplicator`] will be replaced with
56
- /// [`StoreDeduplicator`].
54
+ /// When the persistent storage of the event cache is enabled by default,
55
+ /// this will become the default, and [`Deduplicator`] will be replaced
56
+ /// with [`StoreDeduplicator`].
57
57
pub fn new_store_based ( room_id : OwnedRoomId , store : EventCacheStoreLock ) -> Self {
58
58
Self :: PersistentStore ( StoreDeduplicator { room_id, store } )
59
59
}
@@ -76,7 +76,7 @@ impl Deduplicator {
76
76
/// A deduplication mechanism based on the persistent storage associated to the
77
77
/// event cache.
78
78
///
79
- /// It will use queries to the persistent storage to figure where events are
79
+ /// It will use queries to the persistent storage to figure when events are
80
80
/// duplicates or not, making it entirely stateless.
81
81
pub struct StoreDeduplicator {
82
82
/// The room this deduplicator applies to.
@@ -433,4 +433,80 @@ mod tests {
433
433
dedups. push ( dedup) ;
434
434
}
435
435
}
436
+
437
+ #[ cfg( not( target_arch = "wasm32" ) ) ] // This uses the cross-process lock, so needs time support.
438
+ #[ matrix_sdk_test:: async_test]
439
+ async fn test_storage_deduplication ( ) {
440
+ use std:: sync:: Arc ;
441
+
442
+ use matrix_sdk_base:: {
443
+ event_cache:: store:: { EventCacheStore as _, MemoryStore } ,
444
+ linked_chunk:: { ChunkIdentifier , Position , Update } ,
445
+ } ;
446
+ use matrix_sdk_test:: { ALICE , BOB } ;
447
+ use ruma:: { event_id, room_id, serde:: Raw } ;
448
+
449
+ let room_id = room_id ! ( "!galette:saucisse.bzh" ) ;
450
+ let f = EventFactory :: new ( ) . room ( room_id) . sender ( user_id ! ( "@ben:saucisse.bzh" ) ) ;
451
+
452
+ let event_cache_store = Arc :: new ( MemoryStore :: new ( ) ) ;
453
+
454
+ let eid1 = event_id ! ( "$1" ) ;
455
+ let eid2 = event_id ! ( "$2" ) ;
456
+ let eid3 = event_id ! ( "$3" ) ;
457
+
458
+ let ev1 = f. text_msg ( "hello world" ) . sender ( * ALICE ) . event_id ( eid1) . into_event ( ) ;
459
+ let ev2 = f. text_msg ( "how's it going" ) . sender ( * BOB ) . event_id ( eid2) . into_event ( ) ;
460
+ let ev3 = f. text_msg ( "wassup" ) . sender ( * ALICE ) . event_id ( eid3) . into_event ( ) ;
461
+ // An invalid event (doesn't have an event id.).
462
+ let ev4 = TimelineEvent :: new ( Raw :: from_json_string ( "{}" . to_owned ( ) ) . unwrap ( ) ) ;
463
+
464
+ // Prefill the store with ev1 and ev2.
465
+ event_cache_store
466
+ . handle_linked_chunk_updates (
467
+ room_id,
468
+ vec ! [
469
+ // Non empty items chunk.
470
+ Update :: NewItemsChunk {
471
+ previous: None ,
472
+ new: ChunkIdentifier :: new( 0 ) ,
473
+ next: None ,
474
+ } ,
475
+ Update :: PushItems {
476
+ at: Position :: new( ChunkIdentifier :: new( 0 ) , 0 ) ,
477
+ items: vec![ ev1. clone( ) ] ,
478
+ } ,
479
+ // And another items chunk, non-empty again.
480
+ Update :: NewItemsChunk {
481
+ previous: Some ( ChunkIdentifier :: new( 0 ) ) ,
482
+ new: ChunkIdentifier :: new( 1 ) ,
483
+ next: None ,
484
+ } ,
485
+ Update :: PushItems {
486
+ at: Position :: new( ChunkIdentifier :: new( 1 ) , 0 ) ,
487
+ items: vec![ ev2. clone( ) ] ,
488
+ } ,
489
+ ] ,
490
+ )
491
+ . await
492
+ . unwrap ( ) ;
493
+
494
+ // Wrap the store into its lock.
495
+ let event_cache_store = EventCacheStoreLock :: new ( event_cache_store, "hodor" . to_owned ( ) ) ;
496
+
497
+ let deduplicator =
498
+ StoreDeduplicator { room_id : room_id. to_owned ( ) , store : event_cache_store } ;
499
+
500
+ let ( valid_events, duplicates) =
501
+ deduplicator. filter_duplicate_events ( vec ! [ ev1, ev2, ev3, ev4] ) . await . unwrap ( ) ;
502
+
503
+ assert_eq ! ( valid_events. len( ) , 3 ) ;
504
+ assert_eq ! ( valid_events[ 0 ] . event_id( ) . as_deref( ) , Some ( eid1) ) ;
505
+ assert_eq ! ( valid_events[ 1 ] . event_id( ) . as_deref( ) , Some ( eid2) ) ;
506
+ assert_eq ! ( valid_events[ 2 ] . event_id( ) . as_deref( ) , Some ( eid3) ) ;
507
+
508
+ assert_eq ! ( duplicates. len( ) , 2 ) ;
509
+ assert_eq ! ( duplicates[ 0 ] , eid1) ;
510
+ assert_eq ! ( duplicates[ 1 ] , eid2) ;
511
+ }
436
512
}
0 commit comments