mirror of
https://mau.dev/maunium/synapse.git
synced 2024-12-14 10:43:50 +01:00
Improve failover logic for MSC3083 restricted rooms. (#10447)
If the federation client receives an M_UNABLE_TO_AUTHORISE_JOIN or M_UNABLE_TO_GRANT_JOIN response it will attempt another server before giving up completely.
This commit is contained in:
parent
f8c87c65eb
commit
3a541a7daa
2 changed files with 40 additions and 4 deletions
1
changelog.d/10447.feature
Normal file
1
changelog.d/10447.feature
Normal file
|
@ -0,0 +1 @@
|
||||||
|
Update support for [MSC3083](https://github.com/matrix-org/matrix-doc/pull/3083) to consider changes in the MSC around which servers can issue join events.
|
|
@ -22,6 +22,7 @@ from typing import (
|
||||||
Awaitable,
|
Awaitable,
|
||||||
Callable,
|
Callable,
|
||||||
Collection,
|
Collection,
|
||||||
|
Container,
|
||||||
Dict,
|
Dict,
|
||||||
Iterable,
|
Iterable,
|
||||||
List,
|
List,
|
||||||
|
@ -513,6 +514,7 @@ class FederationClient(FederationBase):
|
||||||
description: str,
|
description: str,
|
||||||
destinations: Iterable[str],
|
destinations: Iterable[str],
|
||||||
callback: Callable[[str], Awaitable[T]],
|
callback: Callable[[str], Awaitable[T]],
|
||||||
|
failover_errcodes: Optional[Container[str]] = None,
|
||||||
failover_on_unknown_endpoint: bool = False,
|
failover_on_unknown_endpoint: bool = False,
|
||||||
) -> T:
|
) -> T:
|
||||||
"""Try an operation on a series of servers, until it succeeds
|
"""Try an operation on a series of servers, until it succeeds
|
||||||
|
@ -533,6 +535,9 @@ class FederationClient(FederationBase):
|
||||||
next server tried. Normally the stacktrace is logged but this is
|
next server tried. Normally the stacktrace is logged but this is
|
||||||
suppressed if the exception is an InvalidResponseError.
|
suppressed if the exception is an InvalidResponseError.
|
||||||
|
|
||||||
|
failover_errcodes: Error codes (specific to this endpoint) which should
|
||||||
|
cause a failover when received as part of an HTTP 400 error.
|
||||||
|
|
||||||
failover_on_unknown_endpoint: if True, we will try other servers if it looks
|
failover_on_unknown_endpoint: if True, we will try other servers if it looks
|
||||||
like a server doesn't support the endpoint. This is typically useful
|
like a server doesn't support the endpoint. This is typically useful
|
||||||
if the endpoint in question is new or experimental.
|
if the endpoint in question is new or experimental.
|
||||||
|
@ -544,6 +549,9 @@ class FederationClient(FederationBase):
|
||||||
SynapseError if the chosen remote server returns a 300/400 code, or
|
SynapseError if the chosen remote server returns a 300/400 code, or
|
||||||
no servers were reachable.
|
no servers were reachable.
|
||||||
"""
|
"""
|
||||||
|
if failover_errcodes is None:
|
||||||
|
failover_errcodes = ()
|
||||||
|
|
||||||
for destination in destinations:
|
for destination in destinations:
|
||||||
if destination == self.server_name:
|
if destination == self.server_name:
|
||||||
continue
|
continue
|
||||||
|
@ -558,11 +566,17 @@ class FederationClient(FederationBase):
|
||||||
synapse_error = e.to_synapse_error()
|
synapse_error = e.to_synapse_error()
|
||||||
failover = False
|
failover = False
|
||||||
|
|
||||||
# Failover on an internal server error, or if the destination
|
# Failover should occur:
|
||||||
# doesn't implemented the endpoint for some reason.
|
#
|
||||||
|
# * On internal server errors.
|
||||||
|
# * If the destination responds that it cannot complete the request.
|
||||||
|
# * If the destination doesn't implemented the endpoint for some reason.
|
||||||
if 500 <= e.code < 600:
|
if 500 <= e.code < 600:
|
||||||
failover = True
|
failover = True
|
||||||
|
|
||||||
|
elif e.code == 400 and synapse_error.errcode in failover_errcodes:
|
||||||
|
failover = True
|
||||||
|
|
||||||
elif failover_on_unknown_endpoint and self._is_unknown_endpoint(
|
elif failover_on_unknown_endpoint and self._is_unknown_endpoint(
|
||||||
e, synapse_error
|
e, synapse_error
|
||||||
):
|
):
|
||||||
|
@ -678,8 +692,20 @@ class FederationClient(FederationBase):
|
||||||
|
|
||||||
return destination, ev, room_version
|
return destination, ev, room_version
|
||||||
|
|
||||||
|
# MSC3083 defines additional error codes for room joins. Unfortunately
|
||||||
|
# we do not yet know the room version, assume these will only be returned
|
||||||
|
# by valid room versions.
|
||||||
|
failover_errcodes = (
|
||||||
|
(Codes.UNABLE_AUTHORISE_JOIN, Codes.UNABLE_TO_GRANT_JOIN)
|
||||||
|
if membership == Membership.JOIN
|
||||||
|
else None
|
||||||
|
)
|
||||||
|
|
||||||
return await self._try_destination_list(
|
return await self._try_destination_list(
|
||||||
"make_" + membership, destinations, send_request
|
"make_" + membership,
|
||||||
|
destinations,
|
||||||
|
send_request,
|
||||||
|
failover_errcodes=failover_errcodes,
|
||||||
)
|
)
|
||||||
|
|
||||||
async def send_join(
|
async def send_join(
|
||||||
|
@ -818,7 +844,14 @@ class FederationClient(FederationBase):
|
||||||
origin=destination,
|
origin=destination,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# MSC3083 defines additional error codes for room joins.
|
||||||
|
failover_errcodes = None
|
||||||
if room_version.msc3083_join_rules:
|
if room_version.msc3083_join_rules:
|
||||||
|
failover_errcodes = (
|
||||||
|
Codes.UNABLE_AUTHORISE_JOIN,
|
||||||
|
Codes.UNABLE_TO_GRANT_JOIN,
|
||||||
|
)
|
||||||
|
|
||||||
# If the join is being authorised via allow rules, we need to send
|
# If the join is being authorised via allow rules, we need to send
|
||||||
# the /send_join back to the same server that was originally used
|
# the /send_join back to the same server that was originally used
|
||||||
# with /make_join.
|
# with /make_join.
|
||||||
|
@ -827,7 +860,9 @@ class FederationClient(FederationBase):
|
||||||
get_domain_from_id(pdu.content["join_authorised_via_users_server"])
|
get_domain_from_id(pdu.content["join_authorised_via_users_server"])
|
||||||
]
|
]
|
||||||
|
|
||||||
return await self._try_destination_list("send_join", destinations, send_request)
|
return await self._try_destination_list(
|
||||||
|
"send_join", destinations, send_request, failover_errcodes=failover_errcodes
|
||||||
|
)
|
||||||
|
|
||||||
async def _do_send_join(
|
async def _do_send_join(
|
||||||
self, room_version: RoomVersion, destination: str, pdu: EventBase
|
self, room_version: RoomVersion, destination: str, pdu: EventBase
|
||||||
|
|
Loading…
Reference in a new issue