Skip to content

Improve implementation of respect_retry_after_header#1607

Merged
sethmlarson merged 8 commits intourllib3:masterfrom
jmeickle:retry_fix
Jun 4, 2019
Merged

Improve implementation of respect_retry_after_header#1607
sethmlarson merged 8 commits intourllib3:masterfrom
jmeickle:retry_fix

Conversation

@jmeickle
Copy link
Copy Markdown
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
Copy Markdown
Contributor Author

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

@pquentin
Copy link
Copy Markdown
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
Copy Markdown

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
Copy Markdown
Member

Cycling to get an automatic rebase for CI

@jmeickle
Copy link
Copy Markdown
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
Copy Markdown
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.

Comment thread src/urllib3/util/retry.py Outdated
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
Copy Markdown
Member

Choose a reason for hiding this comment

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

Nice catch here!

Comment thread src/urllib3/util/retry.py
"""

if response:
if self.respect_retry_after_header and response:
Copy link
Copy Markdown
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
Copy Markdown
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
Copy Markdown
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.

Comment thread test/test_retry.py
with pytest.raises(InvalidHeader):
retry.parse_retry_after(value)

@pytest.mark.parametrize(
Copy link
Copy Markdown
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
Copy Markdown
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
Copy Markdown
Contributor Author

jmeickle commented Jun 3, 2019

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

Comment thread test/test_retry.py
)
)

with mock.patch("time.sleep") as sleep_mock, mock.patch(
Copy link
Copy Markdown
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
Copy Markdown
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
Copy Markdown
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.

4 participants