Fix rooms not being properly excluded from incremental sync (#13408)

This commit is contained in:
Brendan Abolivier 2022-08-04 11:02:29 +02:00 committed by GitHub
parent a648a06d52
commit 845732be45
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 37 additions and 10 deletions

1
changelog.d/13408.bugfix Normal file
View file

@ -0,0 +1 @@
Fix a bug introduced in Synapse 1.57.0 where rooms listed in `exclude_rooms_from_sync` in the configuration file would not be properly excluded from incremental syncs.

View file

@ -1536,15 +1536,13 @@ class SyncHandler:
ignored_users = await self.store.ignored_users(user_id) ignored_users = await self.store.ignored_users(user_id)
if since_token: if since_token:
room_changes = await self._get_rooms_changed( room_changes = await self._get_rooms_changed(
sync_result_builder, ignored_users, self.rooms_to_exclude sync_result_builder, ignored_users
) )
tags_by_room = await self.store.get_updated_tags( tags_by_room = await self.store.get_updated_tags(
user_id, since_token.account_data_key user_id, since_token.account_data_key
) )
else: else:
room_changes = await self._get_all_rooms( room_changes = await self._get_all_rooms(sync_result_builder, ignored_users)
sync_result_builder, ignored_users, self.rooms_to_exclude
)
tags_by_room = await self.store.get_tags_for_user(user_id) tags_by_room = await self.store.get_tags_for_user(user_id)
log_kv({"rooms_changed": len(room_changes.room_entries)}) log_kv({"rooms_changed": len(room_changes.room_entries)})
@ -1623,13 +1621,14 @@ class SyncHandler:
self, self,
sync_result_builder: "SyncResultBuilder", sync_result_builder: "SyncResultBuilder",
ignored_users: FrozenSet[str], ignored_users: FrozenSet[str],
excluded_rooms: List[str],
) -> _RoomChanges: ) -> _RoomChanges:
"""Determine the changes in rooms to report to the user. """Determine the changes in rooms to report to the user.
This function is a first pass at generating the rooms part of the sync response. This function is a first pass at generating the rooms part of the sync response.
It determines which rooms have changed during the sync period, and categorises It determines which rooms have changed during the sync period, and categorises
them into four buckets: "knock", "invite", "join" and "leave". them into four buckets: "knock", "invite", "join" and "leave". It also excludes
from that list any room that appears in the list of rooms to exclude from sync
results in the server configuration.
1. Finds all membership changes for the user in the sync period (from 1. Finds all membership changes for the user in the sync period (from
`since_token` up to `now_token`). `since_token` up to `now_token`).
@ -1655,7 +1654,7 @@ class SyncHandler:
# _have_rooms_changed. We could keep the results in memory to avoid a # _have_rooms_changed. We could keep the results in memory to avoid a
# second query, at the cost of more complicated source code. # second query, at the cost of more complicated source code.
membership_change_events = await self.store.get_membership_changes_for_user( membership_change_events = await self.store.get_membership_changes_for_user(
user_id, since_token.room_key, now_token.room_key, excluded_rooms user_id, since_token.room_key, now_token.room_key, self.rooms_to_exclude
) )
mem_change_events_by_room_id: Dict[str, List[EventBase]] = {} mem_change_events_by_room_id: Dict[str, List[EventBase]] = {}
@ -1862,7 +1861,6 @@ class SyncHandler:
self, self,
sync_result_builder: "SyncResultBuilder", sync_result_builder: "SyncResultBuilder",
ignored_users: FrozenSet[str], ignored_users: FrozenSet[str],
ignored_rooms: List[str],
) -> _RoomChanges: ) -> _RoomChanges:
"""Returns entries for all rooms for the user. """Returns entries for all rooms for the user.
@ -1884,7 +1882,7 @@ class SyncHandler:
room_list = await self.store.get_rooms_for_local_user_where_membership_is( room_list = await self.store.get_rooms_for_local_user_where_membership_is(
user_id=user_id, user_id=user_id,
membership_list=Membership.LIST, membership_list=Membership.LIST,
excluded_rooms=ignored_rooms, excluded_rooms=self.rooms_to_exclude,
) )
room_entries = [] room_entries = []
@ -2150,7 +2148,9 @@ class SyncHandler:
raise Exception("Unrecognized rtype: %r", room_builder.rtype) raise Exception("Unrecognized rtype: %r", room_builder.rtype)
async def get_rooms_for_user_at( async def get_rooms_for_user_at(
self, user_id: str, room_key: RoomStreamToken self,
user_id: str,
room_key: RoomStreamToken,
) -> FrozenSet[str]: ) -> FrozenSet[str]:
"""Get set of joined rooms for a user at the given stream ordering. """Get set of joined rooms for a user at the given stream ordering.
@ -2176,7 +2176,12 @@ class SyncHandler:
# If the membership's stream ordering is after the given stream # If the membership's stream ordering is after the given stream
# ordering, we need to go and work out if the user was in the room # ordering, we need to go and work out if the user was in the room
# before. # before.
# We also need to check whether the room should be excluded from sync
# responses as per the homeserver config.
for joined_room in joined_rooms: for joined_room in joined_rooms:
if joined_room.room_id in self.rooms_to_exclude:
continue
if not joined_room.event_pos.persisted_after(room_key): if not joined_room.event_pos.persisted_after(room_key):
joined_room_ids.add(joined_room.room_id) joined_room_ids.add(joined_room.room_id)
continue continue

View file

@ -948,3 +948,24 @@ class ExcludeRoomTestCase(unittest.HomeserverTestCase):
self.assertNotIn(self.excluded_room_id, channel.json_body["rooms"]["invite"]) self.assertNotIn(self.excluded_room_id, channel.json_body["rooms"]["invite"])
self.assertIn(self.included_room_id, channel.json_body["rooms"]["invite"]) self.assertIn(self.included_room_id, channel.json_body["rooms"]["invite"])
def test_incremental_sync(self) -> None:
"""Tests that activity in the room is properly filtered out of incremental
syncs.
"""
channel = self.make_request("GET", "/sync", access_token=self.tok)
self.assertEqual(channel.code, 200, channel.result)
next_batch = channel.json_body["next_batch"]
self.helper.send(self.excluded_room_id, tok=self.tok)
self.helper.send(self.included_room_id, tok=self.tok)
channel = self.make_request(
"GET",
f"/sync?since={next_batch}",
access_token=self.tok,
)
self.assertEqual(channel.code, 200, channel.result)
self.assertNotIn(self.excluded_room_id, channel.json_body["rooms"]["join"])
self.assertIn(self.included_room_id, channel.json_body["rooms"]["join"])