From 9dfbd7588508044b3668a2ab8ce11fe2af0c68c7 Mon Sep 17 00:00:00 2001 From: Richard van der Hoff Date: Wed, 21 Feb 2024 15:33:41 +0000 Subject: [PATCH] `/sync`: Fix edge-case in calculating the "device_lists" response Fixes https://github.com/element-hq/synapse/issues/16948. If the `join` and the `leave` are in the same sync response, we need to count them as a "left" user. --- changelog.d/16949.bugfix | 1 + synapse/handlers/sync.py | 11 +++++++++-- 2 files changed, 10 insertions(+), 2 deletions(-) create mode 100644 changelog.d/16949.bugfix diff --git a/changelog.d/16949.bugfix b/changelog.d/16949.bugfix new file mode 100644 index 00000000000..99ed435d75b --- /dev/null +++ b/changelog.d/16949.bugfix @@ -0,0 +1 @@ +Fix various long-standing bugs which could cause incorrect state to be returned from `/sync` in certain situations. diff --git a/synapse/handlers/sync.py b/synapse/handlers/sync.py index 9122a79b4c0..723aa816483 100644 --- a/synapse/handlers/sync.py +++ b/synapse/handlers/sync.py @@ -2746,7 +2746,7 @@ def calculate_user_changes(self) -> Tuple[AbstractSet[str], AbstractSet[str]]: if self.since_token: for joined_sync in self.joined: it = itertools.chain( - joined_sync.timeline.events, joined_sync.state.values() + joined_sync.state.values(), joined_sync.timeline.events ) for event in it: if event.type == EventTypes.Member: @@ -2758,13 +2758,20 @@ def calculate_user_changes(self) -> Tuple[AbstractSet[str], AbstractSet[str]]: newly_joined_or_invited_or_knocked_users.add( event.state_key ) + # If the user left and rejoined in the same batch, they + # count as a newly-joined user, *not* a newly-left user. + newly_left_users.discard(event.state_key) else: prev_content = event.unsigned.get("prev_content", {}) prev_membership = prev_content.get("membership", None) if prev_membership == Membership.JOIN: newly_left_users.add(event.state_key) + # If the user joined and left in the same batch, they + # count as a newly-left user, not a newly-joined user. + newly_joined_or_invited_or_knocked_users.discard( + event.state_key + ) - newly_left_users -= newly_joined_or_invited_or_knocked_users return newly_joined_or_invited_or_knocked_users, newly_left_users