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.pull/10631/head
parent
5f7b1e1f27
commit
c4cf0c0473
|
@ -0,0 +1 @@
|
||||||
|
Add pagination to the spaces summary based on updates to [MSC2946](https://github.com/matrix-org/matrix-doc/pull/2946).
|
|
@ -1364,13 +1364,59 @@ class FederationClient(FederationBase):
|
||||||
|
|
||||||
return room, children, inaccessible_children
|
return room, children, inaccessible_children
|
||||||
|
|
||||||
# TODO Fallback to the old federation API and translate the results.
|
try:
|
||||||
return await self._try_destination_list(
|
return await self._try_destination_list(
|
||||||
"fetch room hierarchy",
|
"fetch room hierarchy",
|
||||||
destinations,
|
destinations,
|
||||||
send_request,
|
send_request,
|
||||||
failover_on_unknown_endpoint=True,
|
failover_on_unknown_endpoint=True,
|
||||||
)
|
)
|
||||||
|
except SynapseError as e:
|
||||||
|
# Fallback to the old federation API and translate the results if
|
||||||
|
# no servers implement the new API.
|
||||||
|
#
|
||||||
|
# The algorithm below is a bit inefficient as it only attempts to
|
||||||
|
# get information for the requested room, but the legacy API may
|
||||||
|
# return additional layers.
|
||||||
|
if e.code == 502:
|
||||||
|
legacy_result = await self.get_space_summary(
|
||||||
|
destinations,
|
||||||
|
room_id,
|
||||||
|
suggested_only,
|
||||||
|
max_rooms_per_space=None,
|
||||||
|
exclude_rooms=[],
|
||||||
|
)
|
||||||
|
|
||||||
|
# Find the requested room in the response (and remove it).
|
||||||
|
for _i, room in enumerate(legacy_result.rooms):
|
||||||
|
if room.get("room_id") == room_id:
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
# The requested room was not returned, nothing we can do.
|
||||||
|
raise
|
||||||
|
requested_room = legacy_result.rooms.pop(_i)
|
||||||
|
|
||||||
|
# Find any children events of the requested room.
|
||||||
|
children_events = []
|
||||||
|
children_room_ids = set()
|
||||||
|
for event in legacy_result.events:
|
||||||
|
if event.room_id == room_id:
|
||||||
|
children_events.append(event.data)
|
||||||
|
children_room_ids.add(event.state_key)
|
||||||
|
# And add them under the requested room.
|
||||||
|
requested_room["children_state"] = children_events
|
||||||
|
|
||||||
|
# Find the children rooms.
|
||||||
|
children = []
|
||||||
|
for room in legacy_result.rooms:
|
||||||
|
if room.get("room_id") in children_room_ids:
|
||||||
|
children.append(room)
|
||||||
|
|
||||||
|
# It isn't clear from the response whether some of the rooms are
|
||||||
|
# not accessible.
|
||||||
|
return requested_room, children, ()
|
||||||
|
|
||||||
|
raise
|
||||||
|
|
||||||
|
|
||||||
@attr.s(frozen=True, slots=True, auto_attribs=True)
|
@attr.s(frozen=True, slots=True, auto_attribs=True)
|
||||||
|
@ -1430,7 +1476,7 @@ class FederationSpaceSummaryEventResult:
|
||||||
class FederationSpaceSummaryResult:
|
class FederationSpaceSummaryResult:
|
||||||
"""Represents the data returned by a successful get_space_summary call."""
|
"""Represents the data returned by a successful get_space_summary call."""
|
||||||
|
|
||||||
rooms: Sequence[JsonDict]
|
rooms: List[JsonDict]
|
||||||
events: Sequence[FederationSpaceSummaryEventResult]
|
events: Sequence[FederationSpaceSummaryEventResult]
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
|
@ -1444,7 +1490,7 @@ class FederationSpaceSummaryResult:
|
||||||
ValueError if d is not a valid /spaces/ response
|
ValueError if d is not a valid /spaces/ response
|
||||||
"""
|
"""
|
||||||
rooms = d.get("rooms")
|
rooms = d.get("rooms")
|
||||||
if not isinstance(rooms, Sequence):
|
if not isinstance(rooms, List):
|
||||||
raise ValueError("'rooms' must be a list")
|
raise ValueError("'rooms' must be a list")
|
||||||
if any(not isinstance(r, dict) for r in rooms):
|
if any(not isinstance(r, dict) for r in rooms):
|
||||||
raise ValueError("Invalid room in 'rooms' list")
|
raise ValueError("Invalid room in 'rooms' list")
|
||||||
|
|
Loading…
Reference in New Issue