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

Commit d84e661

Browse files
H-ShayMathieu Veltenerikjohnston
authored
Allow for the configuration of max request retries and min/max retry delays in the matrix federation client (#12504)
Co-authored-by: Mathieu Velten <[email protected]> Co-authored-by: Erik Johnston <[email protected]>
1 parent f6321e3 commit d84e661

File tree

5 files changed

+68
-10
lines changed

5 files changed

+68
-10
lines changed

changelog.d/12504.misc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Allow for the configuration of max request retries and min/max retry delays in the matrix federation client.

docs/usage/configuration/config_documentation.md

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1196,6 +1196,32 @@ Example configuration:
11961196
allow_device_name_lookup_over_federation: true
11971197
```
11981198
---
1199+
### `federation`
1200+
1201+
The federation section defines some sub-options related to federation.
1202+
1203+
The following options are related to configuring timeout and retry logic for one request,
1204+
independently of the others.
1205+
Short retry algorithm is used when something or someone will wait for the request to have an
1206+
answer, while long retry is used for requests that happen in the background,
1207+
like sending a federation transaction.
1208+
1209+
* `client_timeout`: timeout for the federation requests in seconds. Default to 60s.
1210+
* `max_short_retry_delay`: maximum delay to be used for the short retry algo in seconds. Default to 2s.
1211+
* `max_long_retry_delay`: maximum delay to be used for the short retry algo in seconds. Default to 60s.
1212+
* `max_short_retries`: maximum number of retries for the short retry algo. Default to 3 attempts.
1213+
* `max_long_retries`: maximum number of retries for the long retry algo. Default to 10 attempts.
1214+
1215+
Example configuration:
1216+
```yaml
1217+
federation:
1218+
client_timeout: 180
1219+
max_short_retry_delay: 7
1220+
max_long_retry_delay: 100
1221+
max_short_retries: 5
1222+
max_long_retries: 20
1223+
```
1224+
---
11991225
## Caching
12001226

12011227
Options related to caching.

synapse/config/federation.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ class FederationConfig(Config):
2222
section = "federation"
2323

2424
def read_config(self, config: JsonDict, **kwargs: Any) -> None:
25+
federation_config = config.setdefault("federation", {})
26+
2527
# FIXME: federation_domain_whitelist needs sytests
2628
self.federation_domain_whitelist: Optional[dict] = None
2729
federation_domain_whitelist = config.get("federation_domain_whitelist", None)
@@ -49,5 +51,13 @@ def read_config(self, config: JsonDict, **kwargs: Any) -> None:
4951
"allow_device_name_lookup_over_federation", False
5052
)
5153

54+
# Allow for the configuration of timeout, max request retries
55+
# and min/max retry delays in the matrix federation client.
56+
self.client_timeout = federation_config.get("client_timeout", 60)
57+
self.max_long_retry_delay = federation_config.get("max_long_retry_delay", 60)
58+
self.max_short_retry_delay = federation_config.get("max_short_retry_delay", 2)
59+
self.max_long_retries = federation_config.get("max_long_retries", 10)
60+
self.max_short_retries = federation_config.get("max_short_retries", 3)
61+
5262

5363
_METRICS_FOR_DOMAINS_SCHEMA = {"type": "array", "items": {"type": "string"}}

synapse/http/matrixfederationclient.py

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -95,8 +95,6 @@
9595
)
9696

9797

98-
MAX_LONG_RETRIES = 10
99-
MAX_SHORT_RETRIES = 3
10098
MAXINT = sys.maxsize
10199

102100

@@ -406,7 +404,12 @@ def __init__(
406404
self.clock = hs.get_clock()
407405
self._store = hs.get_datastores().main
408406
self.version_string_bytes = hs.version_string.encode("ascii")
409-
self.default_timeout = 60
407+
self.default_timeout = hs.config.federation.client_timeout
408+
409+
self.max_long_retry_delay = hs.config.federation.max_long_retry_delay
410+
self.max_short_retry_delay = hs.config.federation.max_short_retry_delay
411+
self.max_long_retries = hs.config.federation.max_long_retries
412+
self.max_short_retries = hs.config.federation.max_short_retries
410413

411414
self._cooperator = Cooperator(scheduler=_make_scheduler(self.reactor))
412415

@@ -583,9 +586,9 @@ async def _send_request(
583586
# XXX: Would be much nicer to retry only at the transaction-layer
584587
# (once we have reliable transactions in place)
585588
if long_retries:
586-
retries_left = MAX_LONG_RETRIES
589+
retries_left = self.max_long_retries
587590
else:
588-
retries_left = MAX_SHORT_RETRIES
591+
retries_left = self.max_short_retries
589592

590593
url_bytes = request.uri
591594
url_str = url_bytes.decode("ascii")
@@ -730,12 +733,12 @@ async def _send_request(
730733

731734
if retries_left and not timeout:
732735
if long_retries:
733-
delay = 4 ** (MAX_LONG_RETRIES + 1 - retries_left)
734-
delay = min(delay, 60)
736+
delay = 4 ** (self.max_long_retries + 1 - retries_left)
737+
delay = min(delay, self.max_long_retry_delay)
735738
delay *= random.uniform(0.8, 1.4)
736739
else:
737-
delay = 0.5 * 2 ** (MAX_SHORT_RETRIES - retries_left)
738-
delay = min(delay, 2)
740+
delay = 0.5 * 2 ** (self.max_short_retries - retries_left)
741+
delay = min(delay, self.max_short_retry_delay)
739742
delay *= random.uniform(0.8, 1.4)
740743

741744
logger.debug(

tests/http/test_matrixfederationclient.py

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@
4040
from synapse.util import Clock
4141

4242
from tests.server import FakeTransport
43-
from tests.unittest import HomeserverTestCase
43+
from tests.unittest import HomeserverTestCase, override_config
4444

4545

4646
def check_logcontext(context: LoggingContextOrSentinel) -> None:
@@ -640,3 +640,21 @@ def test_build_auth_headers_rejects_falsey_destinations(self) -> None:
640640
self.cl.build_auth_headers(
641641
b"", b"GET", b"https://example.com", destination_is=b""
642642
)
643+
644+
@override_config(
645+
{
646+
"federation": {
647+
"client_timeout": 180,
648+
"max_long_retry_delay": 100,
649+
"max_short_retry_delay": 7,
650+
"max_long_retries": 20,
651+
"max_short_retries": 5,
652+
}
653+
}
654+
)
655+
def test_configurable_retry_and_delay_values(self) -> None:
656+
self.assertEqual(self.cl.default_timeout, 180)
657+
self.assertEqual(self.cl.max_long_retry_delay, 100)
658+
self.assertEqual(self.cl.max_short_retry_delay, 7)
659+
self.assertEqual(self.cl.max_long_retries, 20)
660+
self.assertEqual(self.cl.max_short_retries, 5)

0 commit comments

Comments
 (0)