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

Commit

Permalink
Ignore backoff history for invites, aliases, and roomdirs
Browse files Browse the repository at this point in the history
Add a param to the federation client which lets us ignore historical backoff
data for federation queries, and set it for a handful of operations.
  • Loading branch information
richvdh committed Mar 23, 2017
1 parent 4bd597d commit 5a16cb4
Show file tree
Hide file tree
Showing 6 changed files with 52 additions and 14 deletions.
7 changes: 5 additions & 2 deletions synapse/federation/federation_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ def start_get_pdu_cache(self):

@log_function
def make_query(self, destination, query_type, args,
retry_on_dns_fail=False):
retry_on_dns_fail=False, ignore_backoff=False):
"""Sends a federation Query to a remote homeserver of the given type
and arguments.
Expand All @@ -98,6 +98,8 @@ def make_query(self, destination, query_type, args,
handler name used in register_query_handler().
args (dict): Mapping of strings to strings containing the details
of the query request.
ignore_backoff (bool): true to ignore the historical backoff data
and try the request anyway.
Returns:
a Deferred which will eventually yield a JSON object from the
Expand All @@ -106,7 +108,8 @@ def make_query(self, destination, query_type, args,
sent_queries_counter.inc(query_type)

return self.transport_layer.make_query(
destination, query_type, args, retry_on_dns_fail=retry_on_dns_fail
destination, query_type, args, retry_on_dns_fail=retry_on_dns_fail,
ignore_backoff=ignore_backoff,
)

@log_function
Expand Down
6 changes: 5 additions & 1 deletion synapse/federation/transport/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,8 @@ def send_transaction(self, transaction, json_data_callback=None):

@defer.inlineCallbacks
@log_function
def make_query(self, destination, query_type, args, retry_on_dns_fail):
def make_query(self, destination, query_type, args, retry_on_dns_fail,
ignore_backoff=False):
path = PREFIX + "/query/%s" % query_type

content = yield self.client.get_json(
Expand All @@ -184,6 +185,7 @@ def make_query(self, destination, query_type, args, retry_on_dns_fail):
args=args,
retry_on_dns_fail=retry_on_dns_fail,
timeout=10000,
ignore_backoff=ignore_backoff,
)

defer.returnValue(content)
Expand Down Expand Up @@ -243,6 +245,7 @@ def send_invite(self, destination, room_id, event_id, content):
destination=destination,
path=path,
data=content,
ignore_backoff=True,
)

defer.returnValue(response)
Expand Down Expand Up @@ -270,6 +273,7 @@ def get_public_rooms(self, remote_server, limit, since_token,
destination=remote_server,
path=path,
args=args,
ignore_backoff=True,
)

defer.returnValue(response)
Expand Down
1 change: 1 addition & 0 deletions synapse/handlers/directory.py
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,7 @@ def get_association(self, room_alias):
"room_alias": room_alias.to_string(),
},
retry_on_dns_fail=False,
ignore_backoff=True,
)
except CodeMessageException as e:
logging.warn("Error retrieving alias")
Expand Down
6 changes: 4 additions & 2 deletions synapse/handlers/profile.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,8 @@ def get_displayname(self, target_user):
args={
"user_id": target_user.to_string(),
"field": "displayname",
}
},
ignore_backoff=True,
)
except CodeMessageException as e:
if e.code != 404:
Expand Down Expand Up @@ -99,7 +100,8 @@ def get_avatar_url(self, target_user):
args={
"user_id": target_user.to_string(),
"field": "avatar_url",
}
},
ignore_backoff=True,
)
except CodeMessageException as e:
if e.code != 404:
Expand Down
33 changes: 26 additions & 7 deletions synapse/http/matrixfederationclient.py
Original file line number Diff line number Diff line change
Expand Up @@ -106,12 +106,16 @@ def _create_url(self, destination, path_bytes, param_bytes, query_bytes):
def _request(self, destination, method, path,
body_callback, headers_dict={}, param_bytes=b"",
query_bytes=b"", retry_on_dns_fail=True,
timeout=None, long_retries=False, backoff_on_404=False):
timeout=None, long_retries=False,
ignore_backoff=False,
backoff_on_404=False):
""" Creates and sends a request to the given server
Args:
destination (str): The remote server to send the HTTP request to.
method (str): HTTP method
path (str): The HTTP path
ignore_backoff (bool): true to ignore the historical backoff data
and try the request anyway.
backoff_on_404 (bool): Back off if we get a 404
Returns:
Expand All @@ -127,6 +131,7 @@ def _request(self, destination, method, path,
self.clock,
self._store,
backoff_on_404=backoff_on_404,
ignore_backoff=ignore_backoff,
)

destination = destination.encode("ascii")
Expand Down Expand Up @@ -271,7 +276,9 @@ def sign_request(self, destination, method, url_bytes, headers_dict,

@defer.inlineCallbacks
def put_json(self, destination, path, data={}, json_data_callback=None,
long_retries=False, timeout=None, backoff_on_404=False):
long_retries=False, timeout=None,
ignore_backoff=False,
backoff_on_404=False):
""" Sends the specifed json data using PUT
Args:
Expand All @@ -286,6 +293,8 @@ def put_json(self, destination, path, data={}, json_data_callback=None,
retry for a short or long time.
timeout(int): How long to try (in ms) the destination for before
giving up. None indicates no timeout.
ignore_backoff (bool): true to ignore the historical backoff data
and try the request anyway.
backoff_on_404 (bool): True if we should count a 404 response as
a failure of the server (and should therefore back off future
requests)
Expand Down Expand Up @@ -319,6 +328,7 @@ def body_callback(method, url_bytes, headers_dict):
headers_dict={"Content-Type": ["application/json"]},
long_retries=long_retries,
timeout=timeout,
ignore_backoff=ignore_backoff,
backoff_on_404=backoff_on_404,
)

Expand All @@ -331,7 +341,7 @@ def body_callback(method, url_bytes, headers_dict):

@defer.inlineCallbacks
def post_json(self, destination, path, data={}, long_retries=False,
timeout=None):
timeout=None, ignore_backoff=False):
""" Sends the specifed json data using POST
Args:
Expand All @@ -344,7 +354,8 @@ def post_json(self, destination, path, data={}, long_retries=False,
retry for a short or long time.
timeout(int): How long to try (in ms) the destination for before
giving up. None indicates no timeout.
ignore_backoff (bool): true to ignore the historical backoff data and
try the request anyway.
Returns:
Deferred: Succeeds when we get a 2xx HTTP response. The result
will be the decoded JSON body. On a 4xx or 5xx error response a
Expand All @@ -368,6 +379,7 @@ def body_callback(method, url_bytes, headers_dict):
headers_dict={"Content-Type": ["application/json"]},
long_retries=long_retries,
timeout=timeout,
ignore_backoff=ignore_backoff,
)

if 200 <= response.code < 300:
Expand All @@ -380,7 +392,7 @@ def body_callback(method, url_bytes, headers_dict):

@defer.inlineCallbacks
def get_json(self, destination, path, args={}, retry_on_dns_fail=True,
timeout=None):
timeout=None, ignore_backoff=False):
""" GETs some json from the given host homeserver and path
Args:
Expand All @@ -392,6 +404,8 @@ def get_json(self, destination, path, args={}, retry_on_dns_fail=True,
timeout (int): How long to try (in ms) the destination for before
giving up. None indicates no timeout and that the request will
be retried.
ignore_backoff (bool): true to ignore the historical backoff data
and try the request anyway.
Returns:
Deferred: Succeeds when we get *any* HTTP response.
Expand Down Expand Up @@ -424,6 +438,7 @@ def body_callback(method, url_bytes, headers_dict):
body_callback=body_callback,
retry_on_dns_fail=retry_on_dns_fail,
timeout=timeout,
ignore_backoff=ignore_backoff,
)

if 200 <= response.code < 300:
Expand All @@ -436,13 +451,16 @@ def body_callback(method, url_bytes, headers_dict):

@defer.inlineCallbacks
def get_file(self, destination, path, output_stream, args={},
retry_on_dns_fail=True, max_size=None):
retry_on_dns_fail=True, max_size=None,
ignore_backoff=False):
"""GETs a file from a given homeserver
Args:
destination (str): The remote server to send the HTTP request to.
path (str): The HTTP path to GET.
output_stream (file): File to write the response body to.
args (dict): Optional dictionary used to create the query string.
ignore_backoff (bool): true to ignore the historical backoff data
and try the request anyway.
Returns:
Deferred: resolves with an (int,dict) tuple of the file length and
a dict of the response headers.
Expand Down Expand Up @@ -473,7 +491,8 @@ def body_callback(method, url_bytes, headers_dict):
path,
query_bytes=query_bytes,
body_callback=body_callback,
retry_on_dns_fail=retry_on_dns_fail
retry_on_dns_fail=retry_on_dns_fail,
ignore_backoff=ignore_backoff,
)

headers = dict(response.headers.getAllRawHeaders())
Expand Down
13 changes: 11 additions & 2 deletions synapse/util/retryutils.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,14 +35,23 @@ def __init__(self, retry_last_ts, retry_interval, destination):


@defer.inlineCallbacks
def get_retry_limiter(destination, clock, store, **kwargs):
def get_retry_limiter(destination, clock, store, ignore_backoff=False,
**kwargs):
"""For a given destination check if we have previously failed to
send a request there and are waiting before retrying the destination.
If we are not ready to retry the destination, this will raise a
NotRetryingDestination exception. Otherwise, will return a Context Manager
that will mark the destination as down if an exception is thrown (excluding
CodeMessageException with code < 500)
Args:
destination (str): name of homeserver
clock (synapse.util.clock): timing source
store (synapse.storage.transactions.TransactionStore): datastore
ignore_backoff (bool): true to ignore the historical backoff data and
try the request anyway. We will still update the next
retry_interval on success/failure.
Example usage:
try:
Expand All @@ -66,7 +75,7 @@ def get_retry_limiter(destination, clock, store, **kwargs):

now = int(clock.time_msec())

if retry_last_ts + retry_interval > now:
if not ignore_backoff and retry_last_ts + retry_interval > now:
raise NotRetryingDestination(
retry_last_ts=retry_last_ts,
retry_interval=retry_interval,
Expand Down

0 comments on commit 5a16cb4

Please sign in to comment.