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

Commit c4cf0c0

Browse files
authored
Attempt to pull from the legacy spaces summary API over federation. (#10583)
If the new /hierarchy API does not exist on all destinations, fallback to querying the /spaces API and translating the results. This is a backwards compatibility hack since not all of the federated homeservers will update at the same time.
1 parent 5f7b1e1 commit c4cf0c0

File tree

2 files changed

+56
-9
lines changed

2 files changed

+56
-9
lines changed

changelog.d/10583.feature

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Add pagination to the spaces summary based on updates to [MSC2946](https://github.com/matrix-org/matrix-doc/pull/2946).

synapse/federation/federation_client.py

Lines changed: 55 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1364,13 +1364,59 @@ async def send_request(
13641364

13651365
return room, children, inaccessible_children
13661366

1367-
# TODO Fallback to the old federation API and translate the results.
1368-
return await self._try_destination_list(
1369-
"fetch room hierarchy",
1370-
destinations,
1371-
send_request,
1372-
failover_on_unknown_endpoint=True,
1373-
)
1367+
try:
1368+
return await self._try_destination_list(
1369+
"fetch room hierarchy",
1370+
destinations,
1371+
send_request,
1372+
failover_on_unknown_endpoint=True,
1373+
)
1374+
except SynapseError as e:
1375+
# Fallback to the old federation API and translate the results if
1376+
# no servers implement the new API.
1377+
#
1378+
# The algorithm below is a bit inefficient as it only attempts to
1379+
# get information for the requested room, but the legacy API may
1380+
# return additional layers.
1381+
if e.code == 502:
1382+
legacy_result = await self.get_space_summary(
1383+
destinations,
1384+
room_id,
1385+
suggested_only,
1386+
max_rooms_per_space=None,
1387+
exclude_rooms=[],
1388+
)
1389+
1390+
# Find the requested room in the response (and remove it).
1391+
for _i, room in enumerate(legacy_result.rooms):
1392+
if room.get("room_id") == room_id:
1393+
break
1394+
else:
1395+
# The requested room was not returned, nothing we can do.
1396+
raise
1397+
requested_room = legacy_result.rooms.pop(_i)
1398+
1399+
# Find any children events of the requested room.
1400+
children_events = []
1401+
children_room_ids = set()
1402+
for event in legacy_result.events:
1403+
if event.room_id == room_id:
1404+
children_events.append(event.data)
1405+
children_room_ids.add(event.state_key)
1406+
# And add them under the requested room.
1407+
requested_room["children_state"] = children_events
1408+
1409+
# Find the children rooms.
1410+
children = []
1411+
for room in legacy_result.rooms:
1412+
if room.get("room_id") in children_room_ids:
1413+
children.append(room)
1414+
1415+
# It isn't clear from the response whether some of the rooms are
1416+
# not accessible.
1417+
return requested_room, children, ()
1418+
1419+
raise
13741420

13751421

13761422
@attr.s(frozen=True, slots=True, auto_attribs=True)
@@ -1430,7 +1476,7 @@ def from_json_dict(cls, d: JsonDict) -> "FederationSpaceSummaryEventResult":
14301476
class FederationSpaceSummaryResult:
14311477
"""Represents the data returned by a successful get_space_summary call."""
14321478

1433-
rooms: Sequence[JsonDict]
1479+
rooms: List[JsonDict]
14341480
events: Sequence[FederationSpaceSummaryEventResult]
14351481

14361482
@classmethod
@@ -1444,7 +1490,7 @@ def from_json_dict(cls, d: JsonDict) -> "FederationSpaceSummaryResult":
14441490
ValueError if d is not a valid /spaces/ response
14451491
"""
14461492
rooms = d.get("rooms")
1447-
if not isinstance(rooms, Sequence):
1493+
if not isinstance(rooms, List):
14481494
raise ValueError("'rooms' must be a list")
14491495
if any(not isinstance(r, dict) for r in rooms):
14501496
raise ValueError("Invalid room in 'rooms' list")

0 commit comments

Comments
 (0)