diff options
author | Erik Johnston <erik@matrix.org> | 2024-07-24 16:13:51 +0100 |
---|---|---|
committer | Erik Johnston <erik@matrix.org> | 2024-07-24 16:13:51 +0100 |
commit | 75f7c01b79b13311d1d0c2f11fcef44b928e8a7d (patch) | |
tree | f886eeb3d1062cdf9fab654043adc04606bc3259 | |
parent | Merge remote-tracking branch 'origin/develop' into erikj/ss_room_store (diff) | |
download | synapse-75f7c01b79b13311d1d0c2f11fcef44b928e8a7d.tar.xz |
Only send rooms with updates down sliding sync
-rw-r--r-- | synapse/handlers/sliding_sync.py | 29 | ||||
-rw-r--r-- | synapse/types/handlers/__init__.py | 8 | ||||
-rw-r--r-- | tests/rest/client/test_sync.py | 63 |
3 files changed, 85 insertions, 15 deletions
diff --git a/synapse/handlers/sliding_sync.py b/synapse/handlers/sliding_sync.py index 69be113117..306c4286e7 100644 --- a/synapse/handlers/sliding_sync.py +++ b/synapse/handlers/sliding_sync.py @@ -617,6 +617,31 @@ class SlidingSyncHandler: # Fetch room data rooms: Dict[str, SlidingSyncResult.RoomResult] = {} + # Filter out rooms that haven't received updates and we've sent down + # previously. + if from_token: + rooms_should_send = set() + for room_id in relevant_room_map: + status = await self.connection_store.have_sent_room( + sync_config, + from_token.connection_position, + room_id, + ) + if status.status != HaveSentRoomFlag.LIVE: + rooms_should_send.add(room_id) + + # We only need to check for any new events and not state changes, as + # state changes can only happen if an event has also been sent. + rooms_that_have_updates = ( + self.store._events_stream_cache.get_entities_changed( + relevant_room_map, from_token.stream_token.room_key.stream + ) + ) + rooms_should_send.update(rooms_that_have_updates) + relevant_room_map = { + r: c for r, c in relevant_room_map.items() if r in rooms_should_send + } + @trace @tag_args async def handle_room(room_id: str) -> None: @@ -631,7 +656,9 @@ class SlidingSyncHandler: to_token=to_token, ) - rooms[room_id] = room_sync_result + # Filter out empty room results. + if room_sync_result: + rooms[room_id] = room_sync_result with start_active_span("sliding_sync.generate_room_entries"): await concurrently_execute(handle_room, relevant_room_map, 10) diff --git a/synapse/types/handlers/__init__.py b/synapse/types/handlers/__init__.py index 7c7fe130cb..58530bba70 100644 --- a/synapse/types/handlers/__init__.py +++ b/synapse/types/handlers/__init__.py @@ -238,6 +238,14 @@ class SlidingSyncResult: notification_count: int highlight_count: int + def __bool__(self) -> bool: + return ( + self.initial + or bool(self.required_state) + or bool(self.timeline_events) + or bool(self.stripped_state) + ) + @attr.s(slots=True, frozen=True, auto_attribs=True) class SlidingWindowList: """ diff --git a/tests/rest/client/test_sync.py b/tests/rest/client/test_sync.py index cbb673df2c..7f3d5907cf 100644 --- a/tests/rest/client/test_sync.py +++ b/tests/rest/client/test_sync.py @@ -3540,19 +3540,7 @@ class SlidingSyncTestCase(SlidingSyncBase): self.assertEqual(channel.code, 200, channel.json_body) # Nothing to see for this banned user in the room in the token range - self.assertIsNone(channel.json_body["rooms"][room_id1].get("timeline")) - # No events returned in the timeline so nothing is "live" - self.assertEqual( - channel.json_body["rooms"][room_id1]["num_live"], - 0, - channel.json_body["rooms"][room_id1], - ) - # There aren't anymore events to paginate to in this range - self.assertEqual( - channel.json_body["rooms"][room_id1]["limited"], - False, - channel.json_body["rooms"][room_id1], - ) + self.assertIsNone(channel.json_body["rooms"].get(room_id1)) def test_rooms_no_required_state(self) -> None: """ @@ -3662,12 +3650,15 @@ class SlidingSyncTestCase(SlidingSyncBase): # This one doesn't exist in the room [EventTypes.Tombstone, ""], ], - "timeline_limit": 0, + "timeline_limit": 1, } } } _, after_room_token = self.do_sync(sync_body, tok=user1_tok) + # Send a message so the room comes down sync. + self.helper.send(room_id1, "msg", tok=user1_tok) + # Make the Sliding Sync request channel = self.make_request( "POST", @@ -4745,6 +4736,50 @@ class SlidingSyncTestCase(SlidingSyncBase): exact=True, ) + def test_rooms_with_no_updates_do_not_come_down_incremental_sync(self) -> None: + """ + Test that rooms with no updates are returned in subsequent incremental + syncs. + """ + + user1_id = self.register_user("user1", "pass") + user1_tok = self.login(user1_id, "pass") + user2_id = self.register_user("user2", "pass") + user2_tok = self.login(user2_id, "pass") + + room_id1 = self.helper.create_room_as(user2_id, tok=user2_tok) + self.helper.join(room_id1, user1_id, tok=user1_tok) + + sync_body = { + "lists": { + "foo-list": { + "ranges": [[0, 1]], + "required_state": [ + [EventTypes.Create, ""], + [EventTypes.RoomHistoryVisibility, ""], + # This one doesn't exist in the room + [EventTypes.Tombstone, ""], + ], + "timeline_limit": 0, + } + } + } + + _, after_room_token = self.do_sync(sync_body, tok=user1_tok) + + # Make the Sliding Sync request + channel = self.make_request( + "POST", + self.sync_endpoint + f"?pos={after_room_token}", + content=sync_body, + access_token=user1_tok, + ) + self.assertEqual(channel.code, 200, channel.json_body) + + # Nothing has happened in the room, so the room should not come down + # /sync. + self.assertIsNone(channel.json_body["rooms"].get(room_id1)) + class SlidingSyncToDeviceExtensionTestCase(SlidingSyncBase): """Tests for the to-device sliding sync extension""" |