Skip to content

Implement updated retry behavior gated behind an internal flag#3678

Open
ubaskota wants to merge 6 commits intoboto:developfrom
ubaskota:update_retries_2_1
Open

Implement updated retry behavior gated behind an internal flag#3678
ubaskota wants to merge 6 commits intoboto:developfrom
ubaskota:update_retries_2_1

Conversation

@ubaskota
Copy link
Copy Markdown
Contributor

⚠️ This change is internal-only. External users are not affected and should not depend on the gated behavior.

Description of changes:
Implements the updated retry behavior for standard retry mode. Changes include updated exponential backoff with service specific scale factors, revised retry quota costs (14 for non-throttling, 5 for throttling), DynamoDB-specific max attempts (4) and base backoff (25ms), long-polling operation backoff on quota exhaustion, and x-amz-retry-after header support. All changes are gated behind a STANDARD_RETRY_MODE_VERSION flag imported from an internal customization, ensuring no behavior change for external users. The default retry mode is also updated to standard for internal users via the same flag.

Tests:

  • Added tests to verify the updated retry behavior behind the gated flag works as expected. All new tests pass.
  • Verified that existing tests for the current retry behavior continue to pass.

By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.

@codecov-commenter
Copy link
Copy Markdown

codecov-commenter commented Apr 21, 2026

⚠️ Please install the 'codecov app svg image' to ensure uploads and comments are reliably processed by Codecov.

Codecov Report

❌ Patch coverage is 90.52632% with 9 lines in your changes missing coverage. Please review.
✅ Project coverage is 92.56%. Comparing base (ee748e4) to head (11c05c2).
⚠️ Report is 164 commits behind head on develop.

Files with missing lines Patch % Lines
botocore/retries/standard.py 89.02% 9 Missing ⚠️
❗ Your organization needs to install the Codecov GitHub app to enable full functionality.
Additional details and impacted files
@@             Coverage Diff             @@
##           develop    #3678      +/-   ##
===========================================
- Coverage    92.59%   92.56%   -0.04%     
===========================================
  Files           68       68              
  Lines        15634    15767     +133     
===========================================
+ Hits         14477    14595     +118     
- Misses        1157     1172      +15     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Comment thread botocore/retries/standard.py Outdated
Comment thread botocore/retries/standard.py
Comment thread botocore/retries/standard.py
Comment thread botocore/retries/standard.py Outdated
Comment thread botocore/retries/standard.py Outdated
Comment thread botocore/retries/standard.py Outdated
Comment thread botocore/configprovider.py Outdated
Comment on lines +431 to +446
class TestNewRetriesEnvironmentVariable(unittest.TestCase):
@mock.patch.dict(os.environ, {'AWS_NEW_RETRIES_2026': 'true'})
def test_env_var_true_enables_new_retries(self):
importlib.reload(configprovider)
self.assertTrue(configprovider.NEW_RETRIES_ENABLED)

@mock.patch.dict(os.environ, {'AWS_NEW_RETRIES_2026': 'false'})
def test_env_var_false_disables_new_retries(self):
importlib.reload(configprovider)
self.assertFalse(configprovider.NEW_RETRIES_ENABLED)

@mock.patch.dict(os.environ, {}, clear=False)
def test_no_env_var_uses_default(self):
os.environ.pop('AWS_NEW_RETRIES_2026', None)
importlib.reload(configprovider)
self.assertFalse(configprovider.NEW_RETRIES_ENABLED)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Suggested change
class TestNewRetriesEnvironmentVariable(unittest.TestCase):
@mock.patch.dict(os.environ, {'AWS_NEW_RETRIES_2026': 'true'})
def test_env_var_true_enables_new_retries(self):
importlib.reload(configprovider)
self.assertTrue(configprovider.NEW_RETRIES_ENABLED)
@mock.patch.dict(os.environ, {'AWS_NEW_RETRIES_2026': 'false'})
def test_env_var_false_disables_new_retries(self):
importlib.reload(configprovider)
self.assertFalse(configprovider.NEW_RETRIES_ENABLED)
@mock.patch.dict(os.environ, {}, clear=False)
def test_no_env_var_uses_default(self):
os.environ.pop('AWS_NEW_RETRIES_2026', None)
importlib.reload(configprovider)
self.assertFalse(configprovider.NEW_RETRIES_ENABLED)
class TestNewRetriesEnvironmentVariable(unittest.TestCase):
@mock.patch.dict(os.environ, {'AWS_NEW_RETRIES_2026': 'true'})
def test_env_var_true_enables_new_retries(self):
self.assertTrue(configprovider._resolve_new_retries())
@mock.patch.dict(os.environ, {'AWS_NEW_RETRIES_2026': 'false'})
def test_env_var_false_disables_new_retries(self):
self.assertFalse(configprovider._resolve_new_retries())
def test_no_env_var_uses_default(self):
with mock.patch.dict(os.environ, {}, clear=False):
os.environ.pop('AWS_NEW_RETRIES_2026', None)
self.assertFalse(configprovider._resolve_new_retries())

Fact check me here, but I think this will fix the failing CI along with my other suggestion since this doesn't rely on the global module state.

Copy link
Copy Markdown
Contributor

@SamRemis SamRemis left a comment

Choose a reason for hiding this comment

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

My bad, it still wasn't working. Found some similar tests that use BaseEnvVar, and confirmed this worked on my fork.

Comment thread tests/unit/retries/test_standard_retry_v2_1.py Outdated
Comment on lines +431 to +446
class TestNewRetriesEnvironmentVariable(unittest.TestCase):
@mock.patch.dict(os.environ, {'AWS_NEW_RETRIES_2026': 'true'})
def test_env_var_true_enables_new_retries(self):
importlib.reload(configprovider)
self.assertTrue(configprovider.NEW_RETRIES_ENABLED)

@mock.patch.dict(os.environ, {'AWS_NEW_RETRIES_2026': 'false'})
def test_env_var_false_disables_new_retries(self):
importlib.reload(configprovider)
self.assertFalse(configprovider.NEW_RETRIES_ENABLED)

@mock.patch.dict(os.environ, {}, clear=False)
def test_no_env_var_uses_default(self):
os.environ.pop('AWS_NEW_RETRIES_2026', None)
importlib.reload(configprovider)
self.assertFalse(configprovider.NEW_RETRIES_ENABLED)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Suggested change
class TestNewRetriesEnvironmentVariable(unittest.TestCase):
@mock.patch.dict(os.environ, {'AWS_NEW_RETRIES_2026': 'true'})
def test_env_var_true_enables_new_retries(self):
importlib.reload(configprovider)
self.assertTrue(configprovider.NEW_RETRIES_ENABLED)
@mock.patch.dict(os.environ, {'AWS_NEW_RETRIES_2026': 'false'})
def test_env_var_false_disables_new_retries(self):
importlib.reload(configprovider)
self.assertFalse(configprovider.NEW_RETRIES_ENABLED)
@mock.patch.dict(os.environ, {}, clear=False)
def test_no_env_var_uses_default(self):
os.environ.pop('AWS_NEW_RETRIES_2026', None)
importlib.reload(configprovider)
self.assertFalse(configprovider.NEW_RETRIES_ENABLED)
class TestNewRetriesEnvironmentVariable(BaseEnvVar):
def test_env_var_true_enables_new_retries(self):
self.environ['AWS_NEW_RETRIES_2026'] = 'true'
self.assertTrue(configprovider._resolve_new_retries())
def test_env_var_false_disables_new_retries(self):
self.environ['AWS_NEW_RETRIES_2026'] = 'false'
self.assertFalse(configprovider._resolve_new_retries())
def test_no_env_var_uses_default(self):
self.assertFalse(configprovider._resolve_new_retries())

Comment on lines +10 to +11
import importlib
import os
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Suggested change
import importlib
import os

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.

3 participants