-
Notifications
You must be signed in to change notification settings - Fork 1.1k
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
Add ability to set max retry attempts #1260
Conversation
@@ -70,6 +70,7 @@ def create_client(self, service_name, region_name, is_secure=True, | |||
service_model, region_name, is_secure, endpoint_url, | |||
verify, credentials, scoped_config, client_config, endpoint_bridge) | |||
service_client = cls(**client_args) | |||
self._register_retries(service_client) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Might be worth double checking that moving when the retries gets registered is fine. Now, it is now getting registered to the client's event emitter after the client is created instead of on any service model load and to the client creator's event emitter. I made the change because it is technically more correct (in terms of what event emitter the handler should be registered to), the code flow was better (we are using the computed client config instead of what is provided directly to the create_client()
call), and it should not affect any of the other registered handlers.
Hmm looks like there is a bad patch somewhere as an unrelated test is failing. Going to have to figure that out as I use a context manager for the patches I use. |
Even prior to this feature, when a retry config was built if a service had specific configurations it would mutate the cached retry model. So for example if a user created a dynamodb client and then an s3 client, the s3 client would inherit the max attempts of 10 from the dynamodb client. Tests were also added for checking that the max attempts provided to the session can be overriden at the client level.
Codecov Report
@@ Coverage Diff @@
## develop #1260 +/- ##
===========================================
- Coverage 98.04% 96.62% -1.42%
===========================================
Files 45 45
Lines 7361 7382 +21
===========================================
- Hits 7217 7133 -84
- Misses 144 249 +105
Continue to review full report at Codecov.
|
Alright tests now pass. Also, I found a bug in our retry config logic. So I fixed that while I was looking into the failures as they were related. Should be good to look at. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You should make sure it doesn't get clobbered by this. That only gets called through the CLI, which you aren't supporting right now, but still. Might be worth seeing if that can be removed.
@@ -157,6 +173,12 @@ def _validate_s3_configuration(self, s3): | |||
raise InvalidS3AddressingStyleError( | |||
s3_addressing_style=addressing_style) | |||
|
|||
def _validate_retry_configuration(self, retries): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should probably also validate somewhere that max_attempts
is >= 0.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sounds good. I can add that.
I checked for that handler. I did not see it being used when I sent it up the PR. I will look to see if I can remove it. It should be legacy code as that bit of code has roots to when botocore was based on services and operations and not just clients. |
Renamed a validation error to include Error at the end and throw validation errors for max_attempts that are smaller than 0.
botocore/exceptions.py
Outdated
"""Error when invalid retry configuration is specified""" | ||
fmt = ( | ||
'Cannot provide retry configuration for "{retry_config_option}". ' | ||
'Valid retry configuration options are: \'max_attempts\'' | ||
) | ||
|
||
|
||
class InvalidMaxRetryAttemptsError(BotoCoreError): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should probably subclass from InvalidRetryConfigurationError
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure that's fine with me.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks straightforward to me. Just had a few questions.
botocore/exceptions.py
Outdated
"""Error when invalid retry configuration is specified""" | ||
fmt = ( | ||
'Value provided to "max_attempts": {provided_max_attempts} must ' | ||
'be an integer greater than zero.' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
greater than or equal to.
# retry model has no chance of getting mutated when the service specific | ||
# configuration or client retry config is merged in. | ||
final_retry_config = { | ||
'__default__': copy.deepcopy(retry_model.get('__default__', {})) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So was this deepcopy always a bug then that we just never ran into in practice until now?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah there was a bug. The only time it would be executed though is if you created a dynamodb client and then created other types of clients after as the other clients would inherit the 10 max_attempts of dynamodb. I added the test_service_specific_defaults_do_not_clobber
to make sure that does not happen again.
tests/functional/test_retry.py
Outdated
# for this service. | ||
self.assert_will_retry_n_times(client.list_repositories, 4) | ||
|
||
def test_service_specific_defaults_do_not_clobber(self): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you explain what this is actually testing? It looks like it's just verifying we're able to load service specific config. I don't really get the clobbering part.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is to test the case:
c = session.create_client('dynamodb')
c2 = session.create_client('ec2')
The second client for ec2 would actually have the max retries of dynamodb, even though it is configured for 5 max_attempts.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I also see what I can do to make the name clearer.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yeah or just a comment or something to explain it.
botocore/translate.py
Outdated
# most. So to translate this number from the client config, one is | ||
# added to convert it to the maximum number request that will be made | ||
# by including the initial request. | ||
retry_config['__default__'][ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We don't support this now, but if we ever support max_attempts
at the operation level, we'll need to revisit how we do this. Might be worth adding a note about that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I can do that.
Mainly added comments, renamed some methods, and changed the inheritance of an exception class
There is an issue with sts `import boto3 s = Session() def assumerole(arn): Python/2.7.10 |
Originally [a hack was put in place to disable automatic Lambda retries](boto/boto3#1104) because boto3 lacked support for this. Unfortunately this hack no longer works with the latest boto3 code because it touches internal variables that apparently have been removed or renamed. Fortunately, though, [support for disabling automatic retries has been added](boto/botocore#1260).
This adds the ability for users to set the max retry attempts for any client call through the
botocore.config.Config
object. So for example:It addresses the following issues:
Fixes #482
Fixes #882
Fixes boto/boto3#1104
There are a couple of related PR's for this as well:
#1236
#891
I think I would prefer to go with the approach proposed in this PR because it exposes a little less of the implementation details of how retries work in botocore (so we can swap the strategy out potentially in the future if needed) and allows for retry configuration to be expanded by making a general
retries
parameter in theConfig
object.