Navigation Menu

Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve implementation of respect_retry_after_header #1607

Merged
merged 8 commits into from Jun 4, 2019

Conversation

jmeickle
Copy link
Contributor

@jmeickle jmeickle commented May 14, 2019

respect_retry_after_header is accepted as an argument to Retry, but it isn't propagated on Retry.new(). This means that after the first retry is incremented, this setting will be lost.

Additionally, this setting isn't properly applied in cases where the retry_after header is present, but the intent is not to respect it. This edge case can occur if you explicitly allow retries for the same codes as RETRY_AFTER_STATUS_CODES = frozenset([413, 429, 503]), but don't respect the value in the header, and instead fall back to your Retry's exponential backoff settings. In our case, we're dealing with an API that returns a large static value in this header even though we can actually try again much sooner because rate limits are governed by a token bucket.

I've attached a patch that addresses these two cases and adds a test case for one of them. However, I can't get the test suite to run locally (at all), I'm afraid.

@jmeickle
Copy link
Contributor Author

I took a glance at the test failures, looks spurious?

@pquentin
Copy link
Member

Right, they're not related to your changes and happen in other pull requests too.

@sethmlarson sethmlarson reopened this May 15, 2019
@codecov-io
Copy link

codecov-io commented May 15, 2019

Codecov Report

Merging #1607 into master will decrease coverage by <.01%.
The diff coverage is 100%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master    #1607      +/-   ##
==========================================
- Coverage   99.47%   99.47%   -0.01%     
==========================================
  Files          22       22              
  Lines        1915     1900      -15     
==========================================
- Hits         1905     1890      -15     
  Misses         10       10
Impacted Files Coverage Δ
src/urllib3/util/retry.py 100% <100%> (ø) ⬆️
src/urllib3/connection.py 93.75% <0%> (-0.09%) ⬇️
src/urllib3/util/url.py 99.1% <0%> (-0.04%) ⬇️
src/urllib3/util/timeout.py 100% <0%> (ø) ⬆️
src/urllib3/response.py 100% <0%> (ø) ⬆️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 52c8275...52b82db. Read the comment docs.

@sethmlarson
Copy link
Member

Cycling to get an automatic rebase for CI

@jmeickle
Copy link
Contributor Author

Looks like it passed this time. Is this mergeable? Do I need any additional tests, contributor agreement, signature in blood, etc.? :)

Copy link
Member

@sethmlarson sethmlarson left a comment

Choose a reason for hiding this comment

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

Thanks for this, just a few comments on this PR. Could we add a changelog entry for this change? Also looks like you need to resolve some conflicts after some other PRs were merged.

@@ -192,7 +192,8 @@ def new(self, **kw):
raise_on_redirect=self.raise_on_redirect,
raise_on_status=self.raise_on_status,
history=self.history,
remove_headers_on_redirect=self.remove_headers_on_redirect
remove_headers_on_redirect=self.remove_headers_on_redirect,
respect_retry_after_header=self.respect_retry_after_header
Copy link
Member

Choose a reason for hiding this comment

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

Nice catch here!

@@ -274,7 +275,7 @@ def sleep(self, response=None):
this method will return immediately.
"""

if response:
if self.respect_retry_after_header and response:
Copy link
Member

Choose a reason for hiding this comment

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

Could we add a new unit test that hits this condition?

@jmeickle
Copy link
Contributor Author

jmeickle commented Jun 3, 2019

@sethmlarson I did this:

  • rebased with current master (post-black)
  • moved the unit tests for this header from util.py to retry.py to centralize them
  • added an additional unit test
  • applied black to the modified files

What's the appropriate way for a changelog bump? Does this become a new tagged release by itself, or is there a "on master but not released" place to put changelogs?

Copy link
Member

@sethmlarson sethmlarson left a comment

Choose a reason for hiding this comment

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

This is looking good, one more comment!

For unreleased changes we typically have this header:

dev (master)
------------

along with the change, PR, issue number etc. Until we prepare a release it'll be unreleased on master. :) If you haven't added yourself already to CONTRIBUTORS.txt you should.

with pytest.raises(InvalidHeader):
retry.parse_retry_after(value)

@pytest.mark.parametrize(
Copy link
Member

Choose a reason for hiding this comment

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

Can we add a test case for an http-date formatted Retry-After value? May require mocking time.time() to get a consistent result.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Added four cases here (whether the time is in the future or not X whether we're respecting the header or not).

@jmeickle
Copy link
Contributor Author

jmeickle commented Jun 3, 2019

@sethmlarson added the above, how's that look?

)
)

with mock.patch("time.sleep") as sleep_mock, mock.patch(
Copy link
Member

Choose a reason for hiding this comment

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

TIL about this construction! Thanks for showing me this. :)

@sethmlarson
Copy link
Member

sethmlarson commented Jun 3, 2019

This PR is only failing for Python 3.8 due to reasons not related to this PR. Once I resolve those issues I'll cycle CI and merge. Thank you so much for this! :)

If you've got more time and want to help out more there are plenty of issues marked "Contributor Friendly" that need eyes on them.

@sethmlarson sethmlarson closed this Jun 4, 2019
@sethmlarson sethmlarson reopened this Jun 4, 2019
@sethmlarson sethmlarson merged commit 728d924 into urllib3:master Jun 4, 2019
@sethmlarson
Copy link
Member

sethmlarson commented Jun 4, 2019

Thanks for this!

Dobatymo pushed a commit to Dobatymo/urllib3 that referenced this pull request Mar 16, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants