/sync: Fix edge-case in calculating the "device_lists" response (#16949)

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.
This commit is contained in:
Richard van der Hoff 2024-03-14 17:34:19 +00:00 committed by GitHub
parent 6d5bafb2c8
commit 52f456a822
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 10 additions and 2 deletions

1
changelog.d/16949.bugfix Normal file
View File

@ -0,0 +1 @@
Fix various long-standing bugs which could cause incorrect state to be returned from `/sync` in certain situations.

View File

@ -2837,7 +2837,7 @@ class SyncResultBuilder:
if self.since_token: if self.since_token:
for joined_sync in self.joined: for joined_sync in self.joined:
it = itertools.chain( it = itertools.chain(
joined_sync.timeline.events, joined_sync.state.values() joined_sync.state.values(), joined_sync.timeline.events
) )
for event in it: for event in it:
if event.type == EventTypes.Member: if event.type == EventTypes.Member:
@ -2849,13 +2849,20 @@ class SyncResultBuilder:
newly_joined_or_invited_or_knocked_users.add( newly_joined_or_invited_or_knocked_users.add(
event.state_key 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: else:
prev_content = event.unsigned.get("prev_content", {}) prev_content = event.unsigned.get("prev_content", {})
prev_membership = prev_content.get("membership", None) prev_membership = prev_content.get("membership", None)
if prev_membership == Membership.JOIN: if prev_membership == Membership.JOIN:
newly_left_users.add(event.state_key) 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 return newly_joined_or_invited_or_knocked_users, newly_left_users