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

Remove trailing slashes from outbound federation requests #4840

Merged
merged 42 commits into from
Mar 21, 2019

Conversation

anoadragon453
Copy link
Member

@anoadragon453 anoadragon453 commented Mar 8, 2019

Client portion of #4793 and second portion of a solution towards #3622

TODO:

  • Have Synapse send out federation requests without trailing slashes
  • Have Synapse retry a federation request with a trailing slash if it received a 404
  • I think the server portion may need to be merged first before CI will be happy here.

@codecov
Copy link

codecov bot commented Mar 8, 2019

Codecov Report

Merging #4840 into develop will increase coverage by 0.64%.
The diff coverage is 94.73%.

@@             Coverage Diff             @@
##           develop    #4840      +/-   ##
===========================================
+ Coverage    75.34%   75.99%   +0.64%     
===========================================
  Files          340      327      -13     
  Lines        34924    36941    +2017     
  Branches      5718     6485     +767     
===========================================
+ Hits         26315    28072    +1757     
- Misses        6996     7083      +87     
- Partials      1613     1786     +173

@anoadragon453 anoadragon453 requested a review from a team March 8, 2019 18:26
@anoadragon453 anoadragon453 marked this pull request as ready for review March 8, 2019 18:26
@anoadragon453 anoadragon453 removed the request for review from a team March 8, 2019 18:41
@anoadragon453 anoadragon453 requested a review from a team March 12, 2019 14:52
Copy link
Member

@richvdh richvdh left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah. The main problem here is that these endpoints don't actually return a 404 on synapse 0.99.2 if you hit them without a trailing slash. Empirically, they seem to return a 400 with { "errcode": "M_UNRECOGNIZED" }, which is something you could check for -- though I urge you to check that each endpoint actually does that before taking my word for it (again).

@@ -473,7 +479,8 @@ def put_json(self, destination, path, args={}, data={},
json_data_callback=None,
long_retries=False, timeout=None,
ignore_backoff=False,
backoff_on_404=False):
backoff_on_404=False,
try_trailing_slash_on_404=False):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
try_trailing_slash_on_404=False):
try_trailing_slash_on_404=False,
):

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

flake unfortunately complains about visual indentations if we do this.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

/me shakes fist

@@ -212,6 +213,11 @@ def _send_request(

backoff_on_404 (bool): Back off if we get a 404

try_trailing_slash_on_404 (bool): True if on a 404 response we
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it might be worth adding a note on why this is a useful thing to do ("workaround for #3622 in Synapse 0.99.2 and earlier" ?)

@anoadragon453
Copy link
Member Author

@richvdh Hrm, they seem to all do it. I've left in the check for 404 as well just in case this is new behaviour.

@anoadragon453 anoadragon453 dismissed richvdh’s stale review March 13, 2019 12:39

Use 400 method as well as 404. Lint change did not make flake happy.

Copy link
Member

@richvdh richvdh left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

honestly I would be inclined not to do this on 404s. I am like 99% sure that no version of synapse will return a 404, and trying to support 404s in this way complicates things somewhat.

(of course, that also means renaming the options and fixing the comments/docstrings)

# Re-enable backoff if enabled
send_request_args["backoff_on_404"] = backoff_on_404

response = yield self.get_json(**send_request_args)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why do we switch to get_json here?

# or if a 400 with "M_UNRECOGNIZED" which some endpoints return
if (try_trailing_slash_on_404 and
(response.code == 404
or (response.code == 400
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You've tested this, have you?


# If enabled, retry with a trailing slash if we received a 404
if try_trailing_slash_on_404 and response.code == 404:
args["path"] += "/"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

are you sure this is the right thing to do?

response = yield self._send_request(**send_request_args)

# If enabled, retry with a trailing slash if we received a 404
if try_trailing_slash_on_404 and response.code == 404:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you seem to have missed the 400 case here, which brings me to:

how about implementing this with a wrapper which you can use in both cases?

def _send_request_with_optional_trailing_slash(request, try_trailing_slash_on_404=False, **kwargs):
    self._send_request(request, **kwargs)
    if that_worked:
        return
    fiddle_with(request)
    self._send_request(request, **kwargs)

Copy link
Member

@richvdh richvdh left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it's coming together, I still has suggestions though!

request,
try_trailing_slash_on_400=False,
backoff_on_404=False,
send_request_args={},
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd suggest making this a **kwargs so that you don't need to build a dict in the calling code.

try_trailing_slash_on_400 (bool): Whether on receiving a 400
'M_UNRECOGNIZED' from the server to retry the request with a
trailing slash appended to the request path.
404_backoff (bool): Whether to backoff on 404 when making a
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it's not called that

'M_UNRECOGNIZED' from the server to retry the request with a
trailing slash appended to the request path.
404_backoff (bool): Whether to backoff on 404 when making a
request with a trailing slash (only affects request if
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why do we only do this on the retry? surely it is just as applicable for the first one?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mm, good point. When we originally thought we were going to get a 404 on missing a trailing slash rather than a 400, it made sense to not backoff forever before trying again with a trailing slash.

Now there's no need not to do it for best, which consequently also mades the code simpler.

synapse/http/matrixfederationclient.py Show resolved Hide resolved
if not try_trailing_slash_on_400:
# Received an error >= 300. Raise unless we're retrying
raise e
except Exception as e:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is a no-op

except HttpResponseException as e:
if not try_trailing_slash_on_400:
# Received an error >= 300. Raise unless we're retrying
raise e
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
raise e
raise

response = yield self._send_request(**send_request_args)

# Check if it's necessary to retry with a trailing slash
body = yield _handle_json_response(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think this (or the other instance need to be in here). The exception, if it happens, will get thrown by _send_request. Suggest having _send_request_with_optional_trailing_slash return the response, and leaving the calls to _handle_json_response where they were.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It will be necessary if we're checking the body for M_UNRECOGNIZED, which we need to do again anyways.

try:
response = yield self._send_request(**send_request_args)

# Check if it's necessary to retry with a trailing slash
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure what this comment means

tests/http/test_fedclient.py Show resolved Hide resolved
Copy link
Member

@richvdh richvdh left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can you clean up backoff_on_404?

self,
request,
try_trailing_slash_on_400=False,
backoff_on_404=False,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think there's any need for this now. You can elide it and just let send_request_args pick it up.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(if there are things that rely on passing it as a positional, rather than keyword, arg, then add a *args or, better, fix the callers to use the arg name)

@@ -519,17 +578,15 @@ def put_json(self, destination, path, args={}, data={},
json=data,
)

response = yield self._send_request(
request,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: it's probably best to leave it as one arg on each line - it gets a bit impenetrable otherwise.

Copy link
Member

@richvdh richvdh left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm!

@anoadragon453 anoadragon453 merged commit 7bef97d into develop Mar 21, 2019
@anoadragon453 anoadragon453 deleted the anoa/trailing_slashes_client branch March 21, 2019 15:07
@turt2live
Copy link
Member

ftr I don't think the backoff is working correctly here, but not enough to warrant a new issue. I'm seeing a stead 2.5Hz of requests without a trailing slash, and because I haven't updated yet it means that's 2.5Hz of failing requests.

@richvdh
Copy link
Member

richvdh commented Apr 23, 2019

we didn't implement a backoff...

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants