Skip to content

Commit 7ac153f

Browse files
authored
Merge pull request #3282 from matrix-org/andybalaam/memorystore-tracked-users-map
memorystore: Fix bug where duplicate tracked users are stored
2 parents ac0bc95 + 3113114 commit 7ac153f

File tree

2 files changed

+29
-19
lines changed

2 files changed

+29
-19
lines changed

crates/matrix-sdk-crypto/src/store/memorystore.rs

Lines changed: 23 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ pub struct MemoryStore {
5656
inbound_group_sessions: GroupSessionStore,
5757
outbound_group_sessions: StdRwLock<BTreeMap<OwnedRoomId, OutboundGroupSession>>,
5858
private_identity: StdRwLock<Option<PrivateCrossSigningIdentity>>,
59-
tracked_users: StdRwLock<Vec<TrackedUser>>,
59+
tracked_users: StdRwLock<HashMap<OwnedUserId, TrackedUser>>,
6060
olm_hashes: StdRwLock<HashMap<String, HashSet<String>>>,
6161
devices: DeviceStore,
6262
identities: StdRwLock<HashMap<OwnedUserId, ReadOnlyUserIdentities>>,
@@ -324,12 +324,13 @@ impl CryptoStore for MemoryStore {
324324
}
325325

326326
async fn load_tracked_users(&self) -> Result<Vec<TrackedUser>> {
327-
Ok(self.tracked_users.read().unwrap().clone())
327+
Ok(self.tracked_users.read().unwrap().values().cloned().collect())
328328
}
329329

330330
async fn save_tracked_users(&self, tracked_users: &[(&UserId, bool)]) -> Result<()> {
331331
self.tracked_users.write().unwrap().extend(tracked_users.iter().map(|(user_id, dirty)| {
332-
TrackedUser { user_id: user_id.to_owned().into(), dirty: *dirty }
332+
let user_id: OwnedUserId = user_id.to_owned().into();
333+
(user_id.clone(), TrackedUser { user_id, dirty: *dirty })
333334
}));
334335
Ok(())
335336
}
@@ -559,23 +560,29 @@ mod tests {
559560
}
560561

561562
#[async_test]
562-
async fn test_tracked_users_store() {
563-
// Given some tracked users
564-
let tracked_users =
565-
&[(user_id!("@dirty_user:s"), true), (user_id!("@clean_user:t"), false)];
566-
567-
// When we save them to the store
563+
async fn test_tracked_users_are_stored_once_per_user_id() {
564+
// Given a store containing 2 tracked users, both dirty
565+
let user1 = user_id!("@user1:s");
566+
let user2 = user_id!("@user2:s");
567+
let user3 = user_id!("@user3:s");
568568
let store = MemoryStore::new();
569-
store.save_tracked_users(tracked_users).await.unwrap();
569+
store.save_tracked_users(&[(user1, true), (user2, true)]).await.unwrap();
570+
571+
// When we mark one as clean and add another
572+
store.save_tracked_users(&[(user2, false), (user3, false)]).await.unwrap();
570573

571-
// Then we can get them out again
574+
// Then we can get them out again and their dirty flags are correct
572575
let loaded_tracked_users =
573576
store.load_tracked_users().await.expect("failed to load tracked users");
574-
assert_eq!(loaded_tracked_users[0].user_id, user_id!("@dirty_user:s"));
575-
assert!(loaded_tracked_users[0].dirty);
576-
assert_eq!(loaded_tracked_users[1].user_id, user_id!("@clean_user:t"));
577-
assert!(!loaded_tracked_users[1].dirty);
578-
assert_eq!(loaded_tracked_users.len(), 2);
577+
578+
let tracked_contains = |user_id, dirty| {
579+
loaded_tracked_users.iter().any(|u| u.user_id == user_id && u.dirty == dirty)
580+
};
581+
582+
assert!(tracked_contains(user1, true));
583+
assert!(tracked_contains(user2, false));
584+
assert!(tracked_contains(user3, false));
585+
assert_eq!(loaded_tracked_users.len(), 3);
579586
}
580587

581588
#[async_test]

crates/matrix-sdk-crypto/src/store/traits.rs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -133,11 +133,14 @@ pub trait CryptoStore: AsyncTraitDeps {
133133
room_id: &RoomId,
134134
) -> Result<Option<OutboundGroupSession>, Self::Error>;
135135

136-
/// Load the list of users whose devices we are keeping track of.
136+
/// Provide the list of users whose devices we are keeping track of, and
137+
/// whether they are considered dirty/outdated.
137138
async fn load_tracked_users(&self) -> Result<Vec<TrackedUser>, Self::Error>;
138139

139-
/// Save a list of users and their respective dirty/outdated flags to the
140-
/// store.
140+
/// Update the list of users whose devices we are keeping track of, and
141+
/// whether they are considered dirty/outdated.
142+
///
143+
/// Replaces any existing entry with a matching user ID.
141144
async fn save_tracked_users(&self, users: &[(&UserId, bool)]) -> Result<(), Self::Error>;
142145

143146
/// Get the device for the given user with the given device ID.

0 commit comments

Comments
 (0)