From de316acc11fa52715e4aa833ea8c22eb7c6027c6 Mon Sep 17 00:00:00 2001 From: Benjamin Bouvier Date: Sat, 13 Jan 2024 02:04:32 +0100 Subject: [PATCH] read receipts: don't get confused when receiving multiple times the same event This is a workaround because the proxy may send the same event multiple times in a sync timeline. When that happens and we had the read receipt on the duplicated event, it may cause some events to be counted twice, resulting in invalid counts. This patch fixes it by resetting the count *every* time we see the matching event. --- crates/matrix-sdk-base/src/read_receipts.rs | 36 ++++++++++++++++++--- 1 file changed, 32 insertions(+), 4 deletions(-) diff --git a/crates/matrix-sdk-base/src/read_receipts.rs b/crates/matrix-sdk-base/src/read_receipts.rs index 3340b07f0..28471228b 100644 --- a/crates/matrix-sdk-base/src/read_receipts.rs +++ b/crates/matrix-sdk-base/src/read_receipts.rs @@ -149,17 +149,24 @@ impl RoomReadReceipts { let mut counting_receipts = false; for event in events { - if counting_receipts { - self.account_event(event, user_id); - } else if let Some(event_id) = event.event_id() { + // The sliding sync proxy sometimes sends the same event multiple times, so it + // can be at the beginning and end of a batch, for instance. In that + // case, just reset every time we see the event matching the + // receipt. NOTE: SS proxy workaround. + if let Some(event_id) = event.event_id() { if event_id == receipt_event_id { // Bingo! Switch over to the counting state, after resetting the // previous counts. trace!("Found the event the receipt was referring to! Starting to count."); self.reset(); counting_receipts = true; + continue; } } + + if counting_receipts { + self.account_event(event, user_id); + } } counting_receipts @@ -681,7 +688,7 @@ mod tests { } #[test] - fn test_find_and_count_events() { + fn test_find_and_account_events() { let ev0 = event_id!("$0"); let user_id = user_id!("@alice:example.org"); @@ -786,6 +793,27 @@ mod tests { fn for_room(&self, _room_id: &ruma::RoomId) -> Vector { self.clone() } + // Even if duplicates are present in the new events list, the count is correct. + let mut receipts = RoomReadReceipts { + num_unread: 42, + num_notifications: 13, + num_mentions: 37, + ..Default::default() + }; + assert!(receipts.find_and_account_events( + ev0, + user_id, + &[ + make_event(ev0), + make_event(event_id!("$1")), + make_event(ev0), + make_event(event_id!("$2")), + make_event(event_id!("$3")) + ], + )); + assert_eq!(receipts.num_unread, 2); + assert_eq!(receipts.num_notifications, 0); + assert_eq!(receipts.num_mentions, 0); } fn sync_timeline_message(