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

Commit 6d4f43a

Browse files
committed
Failover during calls to /make_join & /send_join when particular errors occur.
1 parent 228decf commit 6d4f43a

File tree

2 files changed

+40
-4
lines changed

2 files changed

+40
-4
lines changed

changelog.d/10447.feature

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
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.

synapse/federation/federation_client.py

Lines changed: 39 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
Awaitable,
2323
Callable,
2424
Collection,
25+
Container,
2526
Dict,
2627
Iterable,
2728
List,
@@ -513,6 +514,7 @@ async def _try_destination_list(
513514
description: str,
514515
destinations: Iterable[str],
515516
callback: Callable[[str], Awaitable[T]],
517+
failover_errcodes: Optional[Container[str]] = None,
516518
failover_on_unknown_endpoint: bool = False,
517519
) -> T:
518520
"""Try an operation on a series of servers, until it succeeds
@@ -533,6 +535,9 @@ async def _try_destination_list(
533535
next server tried. Normally the stacktrace is logged but this is
534536
suppressed if the exception is an InvalidResponseError.
535537
538+
failover_errcodes: Error codes (specific to this endpoint) which should
539+
cause a failover.
540+
536541
failover_on_unknown_endpoint: if True, we will try other servers if it looks
537542
like a server doesn't support the endpoint. This is typically useful
538543
if the endpoint in question is new or experimental.
@@ -544,6 +549,9 @@ async def _try_destination_list(
544549
SynapseError if the chosen remote server returns a 300/400 code, or
545550
no servers were reachable.
546551
"""
552+
if failover_errcodes is None:
553+
failover_errcodes = ()
554+
547555
for destination in destinations:
548556
if destination == self.server_name:
549557
continue
@@ -558,11 +566,17 @@ async def _try_destination_list(
558566
synapse_error = e.to_synapse_error()
559567
failover = False
560568

561-
# Failover on an internal server error, or if the destination
562-
# doesn't implemented the endpoint for some reason.
569+
# Failover should occur:
570+
#
571+
# * On internal server errors.
572+
# * If the destination responds that it cannot complete the request.
573+
# * If the destination doesn't implemented the endpoint for some reason.
563574
if 500 <= e.code < 600:
564575
failover = True
565576

577+
elif e.code == 400 and synapse_error.errcode in failover_errcodes:
578+
failover = True
579+
566580
elif failover_on_unknown_endpoint and self._is_unknown_endpoint(
567581
e, synapse_error
568582
):
@@ -678,8 +692,20 @@ async def send_request(destination: str) -> Tuple[str, EventBase, RoomVersion]:
678692

679693
return destination, ev, room_version
680694

695+
# MSC3083 defines additional error codes for room joins. Unfortunately
696+
# we do not yet know the room version, assume these will only be returned
697+
# by valid room versions.
698+
failover_errcodes = (
699+
(Codes.UNABLE_AUTHORISE_JOIN, Codes.UNABLE_TO_GRANT_JOIN)
700+
if membership == Membership.JOIN
701+
else None
702+
)
703+
681704
return await self._try_destination_list(
682-
"make_" + membership, destinations, send_request
705+
"make_" + membership,
706+
destinations,
707+
send_request,
708+
failover_errcodes=failover_errcodes,
683709
)
684710

685711
async def send_join(
@@ -818,7 +844,14 @@ async def _execute(pdu: EventBase) -> None:
818844
origin=destination,
819845
)
820846

847+
# MSC3083 defines additional error codes for room joins.
848+
failover_errcodes = None
821849
if room_version.msc3083_join_rules:
850+
failover_errcodes = (
851+
Codes.UNABLE_AUTHORISE_JOIN,
852+
Codes.UNABLE_TO_GRANT_JOIN,
853+
)
854+
822855
# If the join is being authorised via allow rules, we need to send
823856
# the /send_join back to the same server that was originally used
824857
# with /make_join.
@@ -827,7 +860,9 @@ async def _execute(pdu: EventBase) -> None:
827860
get_domain_from_id(pdu.content["join_authorised_via_users_server"])
828861
]
829862

830-
return await self._try_destination_list("send_join", destinations, send_request)
863+
return await self._try_destination_list(
864+
"send_join", destinations, send_request, failover_errcodes=failover_errcodes
865+
)
831866

832867
async def _do_send_join(
833868
self, room_version: RoomVersion, destination: str, pdu: EventBase

0 commit comments

Comments
 (0)