Prevent join->join membership transitions changing member count (#7977)

`StatsHandler` handles updates to the `current_state_delta_stream`, and updates room stats such as the amount of state events, joined users, etc.

However, it counts every new join membership as a new user entering a room (and that user being in another room), whereas it's possible for a user's membership status to go from join -> join, for instance when they change their per-room profile information.

This PR adds a check for join->join membership transitions, and bails out early, as none of the further checks are necessary at that point.

Due to this bug, membership stats in many rooms have ended up being wildly larger than their true values. I am not sure if we also want to include a migration step which recalculates these statistics (possibly using the `_populate_stats_process_rooms` bg update).

Bug introduced in the initial implementation https://github.com/matrix-org/synapse/pull/4338.
This commit is contained in:
Andrew Morgan 2020-08-03 13:54:24 -07:00 committed by GitHub
parent 6812509807
commit 5d92a1428c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 126 additions and 13 deletions

View file

@ -54,7 +54,7 @@ class StatsRoomTests(unittest.HomeserverTestCase):
self.store.db.simple_insert(
"background_updates",
{
"update_name": "populate_stats_process_rooms",
"update_name": "populate_stats_process_rooms_2",
"progress_json": "{}",
"depends_on": "populate_stats_prepare",
},
@ -66,7 +66,7 @@ class StatsRoomTests(unittest.HomeserverTestCase):
{
"update_name": "populate_stats_process_users",
"progress_json": "{}",
"depends_on": "populate_stats_process_rooms",
"depends_on": "populate_stats_process_rooms_2",
},
)
)
@ -219,7 +219,10 @@ class StatsRoomTests(unittest.HomeserverTestCase):
self.get_success(
self.store.db.simple_insert(
"background_updates",
{"update_name": "populate_stats_process_rooms", "progress_json": "{}"},
{
"update_name": "populate_stats_process_rooms_2",
"progress_json": "{}",
},
)
)
self.get_success(
@ -228,7 +231,7 @@ class StatsRoomTests(unittest.HomeserverTestCase):
{
"update_name": "populate_stats_cleanup",
"progress_json": "{}",
"depends_on": "populate_stats_process_rooms",
"depends_on": "populate_stats_process_rooms_2",
},
)
)
@ -346,6 +349,37 @@ class StatsRoomTests(unittest.HomeserverTestCase):
self.assertEqual(r1stats_post["total_events"] - r1stats_ante["total_events"], 1)
def test_updating_profile_information_does_not_increase_joined_members_count(self):
"""
Check that the joined_members count does not increase when a user changes their
profile information (which is done by sending another join membership event into
the room.
"""
self._perform_background_initial_update()
# Create a user and room
u1 = self.register_user("u1", "pass")
u1token = self.login("u1", "pass")
r1 = self.helper.create_room_as(u1, tok=u1token)
# Get the current room stats
r1stats_ante = self._get_current_stats("room", r1)
# Send a profile update into the room
new_profile = {"displayname": "bob"}
self.helper.change_membership(
r1, u1, u1, "join", extra_data=new_profile, tok=u1token
)
# Get the new room stats
r1stats_post = self._get_current_stats("room", r1)
# Ensure that the user count did not changed
self.assertEqual(r1stats_post["joined_members"], r1stats_ante["joined_members"])
self.assertEqual(
r1stats_post["local_users_in_room"], r1stats_ante["local_users_in_room"]
)
def test_send_state_event_nonoverwriting(self):
"""
When we send a non-overwriting state event, it increments total_events AND current_state_events
@ -694,7 +728,7 @@ class StatsRoomTests(unittest.HomeserverTestCase):
self.store.db.simple_insert(
"background_updates",
{
"update_name": "populate_stats_process_rooms",
"update_name": "populate_stats_process_rooms_2",
"progress_json": "{}",
"depends_on": "populate_stats_prepare",
},
@ -706,7 +740,7 @@ class StatsRoomTests(unittest.HomeserverTestCase):
{
"update_name": "populate_stats_process_users",
"progress_json": "{}",
"depends_on": "populate_stats_process_rooms",
"depends_on": "populate_stats_process_rooms_2",
},
)
)