Skip to content
This repository was archived by the owner on Apr 26, 2024. It is now read-only.

Commit 6b241f5

Browse files
authored
Make pagination of rooms in admin api stable (#11737)
Always add state.room_id after the configurable ORDER BY. Otherwise, for any sort, certain pages can contain results from other pages. (Especially when sorting by creator, since there may be many rooms by the same creator) * Document different order direction of numerical fields "joined_members", "joined_local_members", "version" and "state_events" are ordered in descending direction by default (dir=f). Added a note in tests to explain the differences in ordering. Signed-off-by: Daniël Sonck <[email protected]>
1 parent e7da1ce commit 6b241f5

File tree

3 files changed

+38
-28
lines changed

3 files changed

+38
-28
lines changed

changelog.d/11737.bugfix

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Make the list rooms admin api sort stable. Contributed by Daniël Sonck.

synapse/storage/databases/main/room.py

+9-9
Original file line numberDiff line numberDiff line change
@@ -551,24 +551,24 @@ async def get_rooms_paginate(
551551
FROM room_stats_state state
552552
INNER JOIN room_stats_current curr USING (room_id)
553553
INNER JOIN rooms USING (room_id)
554-
%s
555-
ORDER BY %s %s
554+
{where}
555+
ORDER BY {order_by} {direction}, state.room_id {direction}
556556
LIMIT ?
557557
OFFSET ?
558-
""" % (
559-
where_statement,
560-
order_by_column,
561-
"ASC" if order_by_asc else "DESC",
558+
""".format(
559+
where=where_statement,
560+
order_by=order_by_column,
561+
direction="ASC" if order_by_asc else "DESC",
562562
)
563563

564564
# Use a nested SELECT statement as SQL can't count(*) with an OFFSET
565565
count_sql = """
566566
SELECT count(*) FROM (
567567
SELECT room_id FROM room_stats_state state
568-
%s
568+
{where}
569569
) AS get_room_ids
570-
""" % (
571-
where_statement,
570+
""".format(
571+
where=where_statement,
572572
)
573573

574574
def _get_rooms_paginate_txn(

tests/rest/admin/test_room.py

+28-19
Original file line numberDiff line numberDiff line change
@@ -1089,6 +1089,8 @@ def test_list_rooms(self) -> None:
10891089
)
10901090
room_ids.append(room_id)
10911091

1092+
room_ids.sort()
1093+
10921094
# Request the list of rooms
10931095
url = "/_synapse/admin/v1/rooms"
10941096
channel = self.make_request(
@@ -1360,6 +1362,12 @@ def _order_test(
13601362
room_id_2 = self.helper.create_room_as(self.admin_user, tok=self.admin_user_tok)
13611363
room_id_3 = self.helper.create_room_as(self.admin_user, tok=self.admin_user_tok)
13621364

1365+
# Also create a list sorted by IDs for properties that are equal (and thus sorted by room_id)
1366+
sorted_by_room_id_asc = [room_id_1, room_id_2, room_id_3]
1367+
sorted_by_room_id_asc.sort()
1368+
sorted_by_room_id_desc = sorted_by_room_id_asc.copy()
1369+
sorted_by_room_id_desc.reverse()
1370+
13631371
# Set room names in alphabetical order. room 1 -> A, 2 -> B, 3 -> C
13641372
self.helper.send_state(
13651373
room_id_1,
@@ -1405,41 +1413,42 @@ def _order_test(
14051413
_order_test("canonical_alias", [room_id_1, room_id_2, room_id_3])
14061414
_order_test("canonical_alias", [room_id_3, room_id_2, room_id_1], reverse=True)
14071415

1416+
# Note: joined_member counts are sorted in descending order when dir=f
14081417
_order_test("joined_members", [room_id_3, room_id_2, room_id_1])
14091418
_order_test("joined_members", [room_id_1, room_id_2, room_id_3], reverse=True)
14101419

1420+
# Note: joined_local_member counts are sorted in descending order when dir=f
14111421
_order_test("joined_local_members", [room_id_3, room_id_2, room_id_1])
14121422
_order_test(
14131423
"joined_local_members", [room_id_1, room_id_2, room_id_3], reverse=True
14141424
)
14151425

1416-
_order_test("version", [room_id_1, room_id_2, room_id_3])
1417-
_order_test("version", [room_id_1, room_id_2, room_id_3], reverse=True)
1426+
# Note: versions are sorted in descending order when dir=f
1427+
_order_test("version", sorted_by_room_id_asc, reverse=True)
1428+
_order_test("version", sorted_by_room_id_desc)
14181429

1419-
_order_test("creator", [room_id_1, room_id_2, room_id_3])
1420-
_order_test("creator", [room_id_1, room_id_2, room_id_3], reverse=True)
1430+
_order_test("creator", sorted_by_room_id_asc)
1431+
_order_test("creator", sorted_by_room_id_desc, reverse=True)
14211432

1422-
_order_test("encryption", [room_id_1, room_id_2, room_id_3])
1423-
_order_test("encryption", [room_id_1, room_id_2, room_id_3], reverse=True)
1433+
_order_test("encryption", sorted_by_room_id_asc)
1434+
_order_test("encryption", sorted_by_room_id_desc, reverse=True)
14241435

1425-
_order_test("federatable", [room_id_1, room_id_2, room_id_3])
1426-
_order_test("federatable", [room_id_1, room_id_2, room_id_3], reverse=True)
1436+
_order_test("federatable", sorted_by_room_id_asc)
1437+
_order_test("federatable", sorted_by_room_id_desc, reverse=True)
14271438

1428-
_order_test("public", [room_id_1, room_id_2, room_id_3])
1429-
# Different sort order of SQlite and PostreSQL
1430-
# _order_test("public", [room_id_3, room_id_2, room_id_1], reverse=True)
1439+
_order_test("public", sorted_by_room_id_asc)
1440+
_order_test("public", sorted_by_room_id_desc, reverse=True)
14311441

1432-
_order_test("join_rules", [room_id_1, room_id_2, room_id_3])
1433-
_order_test("join_rules", [room_id_1, room_id_2, room_id_3], reverse=True)
1442+
_order_test("join_rules", sorted_by_room_id_asc)
1443+
_order_test("join_rules", sorted_by_room_id_desc, reverse=True)
14341444

1435-
_order_test("guest_access", [room_id_1, room_id_2, room_id_3])
1436-
_order_test("guest_access", [room_id_1, room_id_2, room_id_3], reverse=True)
1445+
_order_test("guest_access", sorted_by_room_id_asc)
1446+
_order_test("guest_access", sorted_by_room_id_desc, reverse=True)
14371447

1438-
_order_test("history_visibility", [room_id_1, room_id_2, room_id_3])
1439-
_order_test(
1440-
"history_visibility", [room_id_1, room_id_2, room_id_3], reverse=True
1441-
)
1448+
_order_test("history_visibility", sorted_by_room_id_asc)
1449+
_order_test("history_visibility", sorted_by_room_id_desc, reverse=True)
14421450

1451+
# Note: state_event counts are sorted in descending order when dir=f
14431452
_order_test("state_events", [room_id_3, room_id_2, room_id_1])
14441453
_order_test("state_events", [room_id_1, room_id_2, room_id_3], reverse=True)
14451454

0 commit comments

Comments
 (0)