forked from MirrorHub/synapse
Cache the result of fetching the room hierarchy over federation. (#10647)
This commit is contained in:
parent
b45cc1530b
commit
5548fe0978
2 changed files with 63 additions and 36 deletions
1
changelog.d/10647.misc
Normal file
1
changelog.d/10647.misc
Normal file
|
@ -0,0 +1 @@
|
||||||
|
Improve the performance of the `/hierarchy` API (from [MSC2946](https://github.com/matrix-org/matrix-doc/pull/2946)) by caching responses received over federation.
|
|
@ -111,6 +111,23 @@ class FederationClient(FederationBase):
|
||||||
reset_expiry_on_get=False,
|
reset_expiry_on_get=False,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# A cache for fetching the room hierarchy over federation.
|
||||||
|
#
|
||||||
|
# Some stale data over federation is OK, but must be refreshed
|
||||||
|
# periodically since the local server is in the room.
|
||||||
|
#
|
||||||
|
# It is a map of (room ID, suggested-only) -> the response of
|
||||||
|
# get_room_hierarchy.
|
||||||
|
self._get_room_hierarchy_cache: ExpiringCache[
|
||||||
|
Tuple[str, bool], Tuple[JsonDict, Sequence[JsonDict], Sequence[str]]
|
||||||
|
] = ExpiringCache(
|
||||||
|
cache_name="get_room_hierarchy_cache",
|
||||||
|
clock=self._clock,
|
||||||
|
max_len=1000,
|
||||||
|
expiry_ms=5 * 60 * 1000,
|
||||||
|
reset_expiry_on_get=False,
|
||||||
|
)
|
||||||
|
|
||||||
def _clear_tried_cache(self):
|
def _clear_tried_cache(self):
|
||||||
"""Clear pdu_destination_tried cache"""
|
"""Clear pdu_destination_tried cache"""
|
||||||
now = self._clock.time_msec()
|
now = self._clock.time_msec()
|
||||||
|
@ -1324,6 +1341,10 @@ class FederationClient(FederationBase):
|
||||||
remote servers
|
remote servers
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
cached_result = self._get_room_hierarchy_cache.get((room_id, suggested_only))
|
||||||
|
if cached_result:
|
||||||
|
return cached_result
|
||||||
|
|
||||||
async def send_request(
|
async def send_request(
|
||||||
destination: str,
|
destination: str,
|
||||||
) -> Tuple[JsonDict, Sequence[JsonDict], Sequence[str]]:
|
) -> Tuple[JsonDict, Sequence[JsonDict], Sequence[str]]:
|
||||||
|
@ -1370,20 +1391,23 @@ class FederationClient(FederationBase):
|
||||||
return room, children, inaccessible_children
|
return room, children, inaccessible_children
|
||||||
|
|
||||||
try:
|
try:
|
||||||
return await self._try_destination_list(
|
result = 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:
|
except SynapseError as e:
|
||||||
|
# If an unexpected error occurred, re-raise it.
|
||||||
|
if e.code != 502:
|
||||||
|
raise
|
||||||
|
|
||||||
# Fallback to the old federation API and translate the results if
|
# Fallback to the old federation API and translate the results if
|
||||||
# no servers implement the new API.
|
# no servers implement the new API.
|
||||||
#
|
#
|
||||||
# The algorithm below is a bit inefficient as it only attempts to
|
# The algorithm below is a bit inefficient as it only attempts to
|
||||||
# get information for the requested room, but the legacy API may
|
# parse information for the requested room, but the legacy API may
|
||||||
# return additional layers.
|
# return additional layers.
|
||||||
if e.code == 502:
|
|
||||||
legacy_result = await self.get_space_summary(
|
legacy_result = await self.get_space_summary(
|
||||||
destinations,
|
destinations,
|
||||||
room_id,
|
room_id,
|
||||||
|
@ -1419,9 +1443,11 @@ class FederationClient(FederationBase):
|
||||||
|
|
||||||
# It isn't clear from the response whether some of the rooms are
|
# It isn't clear from the response whether some of the rooms are
|
||||||
# not accessible.
|
# not accessible.
|
||||||
return requested_room, children, ()
|
result = (requested_room, children, ())
|
||||||
|
|
||||||
raise
|
# Cache the result to avoid fetching data over federation every time.
|
||||||
|
self._get_room_hierarchy_cache[(room_id, suggested_only)] = result
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
@attr.s(frozen=True, slots=True, auto_attribs=True)
|
@attr.s(frozen=True, slots=True, auto_attribs=True)
|
||||||
|
|
Loading…
Reference in a new issue