From 06e0494bca87cc151642aa1febbb9721e1893061 Mon Sep 17 00:00:00 2001 From: Matthew Hodgson Date: Sat, 8 Aug 2026 22:42:50 +0300 Subject: [PATCH] Tie-break child ordering on the child room id _child_events_comparison_key's final tie-break used the room the m.space.child event lives in, which is the same for every child of a space and so never broke a tie (leaving ties in arbitrary DB order). Use the child room id (the event's state key), per the spec, matching the cached path. --- synapse/handlers/room_summary.py | 10 +++++++--- tests/handlers/test_room_summary.py | 8 +++++++- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/synapse/handlers/room_summary.py b/synapse/handlers/room_summary.py index 8edc04acfd..47733b17a0 100644 --- a/synapse/handlers/room_summary.py +++ b/synapse/handlers/room_summary.py @@ -1351,7 +1351,7 @@ def _child_events_comparison_key( 1. The 'order' key, if it is valid. 2. The 'origin_server_ts' of the 'm.space.child' event. - 3. The 'room_id'. + 3. The child room ID (the event's state key). Args: child: The event for generating a comparison key. @@ -1361,7 +1361,7 @@ def _child_events_comparison_key( False if the ordering is valid. The 'order' field or None if it is not given or invalid. The 'origin_server_ts' field. - The room ID. + The child room ID. """ order = child.content.get("order") # If order is not a string or doesn't meet the requirements, ignore it. @@ -1371,4 +1371,8 @@ def _child_events_comparison_key( order = None # Items without an order come last. - return order is None, order, child.origin_server_ts, child.room_id + # + # NB the final tie-break is the CHILD room id (the state key), not the room + # the event lives in — that is the same for every child of a space, so it + # never actually broke a tie. + return order is None, order, child.origin_server_ts, child.state_key diff --git a/tests/handlers/test_room_summary.py b/tests/handlers/test_room_summary.py index 2fc48c3825..1bb25f3b23 100644 --- a/tests/handlers/test_room_summary.py +++ b/tests/handlers/test_room_summary.py @@ -51,8 +51,14 @@ from tests.unittest import override_config def _create_event( room_id: str, order: Any | None = None, origin_server_ts: int = 0 ) -> mock.Mock: + """Build a fake m.space.child event pointing at `room_id`. + + The child room id is the event's state key (the event itself lives in the + parent space). + """ result = mock.Mock(name=room_id) - result.room_id = room_id + result.state_key = room_id + result.room_id = "!parent:test" result.content = {} result.origin_server_ts = origin_server_ts if order is not None: