-
-
Notifications
You must be signed in to change notification settings - Fork 2.1k
Query legacy spaces federation API if the hierarchy API is unavailable. #10583
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
Add pagination to the spaces summary based on updates to [MSC2946](https://github.com/matrix-org/matrix-doc/pull/2946). |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -1364,13 +1364,59 @@ async def send_request( | |
|
||
return room, children, inaccessible_children | ||
|
||
# TODO Fallback to the old federation API and translate the results. | ||
return await self._try_destination_list( | ||
"fetch room hierarchy", | ||
destinations, | ||
send_request, | ||
failover_on_unknown_endpoint=True, | ||
) | ||
try: | ||
return await self._try_destination_list( | ||
"fetch room hierarchy", | ||
destinations, | ||
send_request, | ||
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, () | ||
Comment on lines
+1415
to
+1417
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Will this produce odd results on the client-side where one may believe they can access a room, but will find they are unable to? Mostly a question out of curiosity, as I don't know any way that the situation could be improved (and this is a legacy API so meh). There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It shouldn't, this is before any filtering is done on whether a room is accessible or not, it pretty much is just about changing API shapes from the old The overall algorithm is:
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Aha, I see. Thanks for explaining it so clearly. |
||
|
||
raise | ||
|
||
|
||
@attr.s(frozen=True, slots=True, auto_attribs=True) | ||
|
@@ -1430,7 +1476,7 @@ def from_json_dict(cls, d: JsonDict) -> "FederationSpaceSummaryEventResult": | |
class FederationSpaceSummaryResult: | ||
"""Represents the data returned by a successful get_space_summary call.""" | ||
|
||
rooms: Sequence[JsonDict] | ||
rooms: List[JsonDict] | ||
events: Sequence[FederationSpaceSummaryEventResult] | ||
|
||
@classmethod | ||
|
@@ -1444,7 +1490,7 @@ def from_json_dict(cls, d: JsonDict) -> "FederationSpaceSummaryResult": | |
ValueError if d is not a valid /spaces/ response | ||
""" | ||
rooms = d.get("rooms") | ||
if not isinstance(rooms, Sequence): | ||
if not isinstance(rooms, List): | ||
raise ValueError("'rooms' must be a list") | ||
if any(not isinstance(r, dict) for r in rooms): | ||
raise ValueError("Invalid room in 'rooms' list") | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does Synapse not return a
400, M_UNRECOGNIZED
for endpoints it fails to understand, rather than a 502?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is from
synapse/synapse/federation/federation_client.py
Line 600 in 4b1722a
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
aha, thanks!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The goal is only to run this if we were unable to fetch data from all destinations, not just if we were unable to fetch it from the first destination. (This is different than our fallback of v2 -> v1 for e.g.
send_join
, which we do on a per-destination basis).