From c1a4a7e0f1ca3d95dbd1c3dd37cd78fbee38a06d Mon Sep 17 00:00:00 2001 From: Olivier 'reivilibre Date: Fri, 31 Jul 2026 15:58:02 +0100 Subject: [PATCH] Fix state transition table --- synapse/storage/databases/main/events.py | 19 ++++++++++----- tests/handlers/test_profile.py | 31 ++++-------------------- 2 files changed, 18 insertions(+), 32 deletions(-) diff --git a/synapse/storage/databases/main/events.py b/synapse/storage/databases/main/events.py index a54f637691..8211612e2d 100644 --- a/synapse/storage/databases/main/events.py +++ b/synapse/storage/databases/main/events.py @@ -2130,20 +2130,27 @@ class PersistEventsStore: # FIXME: See issue https://github.com/element-hq/synapse/issues/19981 # for concerns around the current implementation of the profile # updates stream. - # Note, we're skipped Membership.BAN, as we would expect there to also - # be a leave event? profile_update_additions = { c.user_id for c in sliding_sync_table_changes.to_insert_membership_snapshots if self.hs.is_mine_id(c.user_id) - and c.membership - in (Membership.JOIN, Membership.KNOCK, Membership.INVITE) + # FIXME: Ideally we would filter out JOIN -> JOIN. See note below. + and c.membership == Membership.JOIN } profile_update_leaves = { c.user_id for c in sliding_sync_table_changes.to_insert_membership_snapshots - if self.hs.is_mine_id(c.user_id) and c.membership == Membership.LEAVE - } + if self.hs.is_mine_id(c.user_id) + # Any transition from JOIN to something else counts as a leave here. + # Even the 'invalid' transitions might effectively happen due to + # state resolution. + and c.membership != Membership.JOIN + } | ( + # We also need to consider users that get fully state reset out of the room. + # These should be treated as 'leave' + set(sliding_sync_table_changes.to_delete_membership_snapshots) + ) + if profile_update_additions: # Write the profile updates for additions to the room, from either # a join, knock, invite, etc. diff --git a/tests/handlers/test_profile.py b/tests/handlers/test_profile.py index b0316eeb95..c53c04fbc8 100644 --- a/tests/handlers/test_profile.py +++ b/tests/handlers/test_profile.py @@ -28,8 +28,6 @@ from twisted.internet.testing import MemoryReactor import synapse.types from synapse.api.constants import ( EventTypes, - JoinRules, - Membership, ProfileFields, ProfileUpdateAction, ) @@ -458,20 +456,12 @@ class ProfileTestCase(unittest.HomeserverTestCase): ], ) - @parameterized.expand( - [ - Membership.JOIN, - Membership.KNOCK, - Membership.INVITE, - ] - ) @override_config({"include_profile_updates_in_sync": True}) def test_membership_addition_to_room_adds_the_right_join_action_to_profile_streams( self, - membership: str, ) -> None: - """Test that a membership event that adds a user as joined, invited or knocked, - to a room, adds the relevant joined action to the profile update stream tables. + """Test that a membership event, which adds a user as joined to a room, + adds the relevant joined action to the profile update stream tables. Here we consider join, knock and invite to all be additions to the room list of members for answering the question "which profiles should we send @@ -483,20 +473,9 @@ class ProfileTestCase(unittest.HomeserverTestCase): room_creator=self.frank.to_string(), tok=self.frank_token, ) - if membership == Membership.JOIN: - self.helper.join(room_id, "@roger:test", tok=roger_token) - elif membership == Membership.INVITE: - self.helper.invite( - room_id, self.frank.to_string(), "@roger:test", tok=self.frank_token - ) - elif membership == Membership.KNOCK: - self.helper.send_state( - room_id, - EventTypes.JoinRules, - {"join_rule": JoinRules.KNOCK}, - tok=self.frank_token, - ) - self.helper.knock(room_id, "@roger:test", tok=roger_token) + + self.helper.join(room_id, "@roger:test", tok=roger_token) + per_user_updates = self.get_success( self.store.get_profile_updates_for_user_and_fields( from_id=0,