Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Loading…

DynamoDB: Passing custom retries exceeded handler #1194

Closed
wants to merge 1 commit into from

2 participants

@timmyfury

Passing custom retries exceeded handler to _mexe method in DynamoDB. This method will handle retries exceeded to raise a throughput exceeded error from amazon rather than raising a generic BotoServerError.

@timmyfury timmyfury Passing custom retries exceeded handler to _mexe method in DynamoDB. …
…This method will handle retries exceeded to raise a throughput exceeded error from amazon rather than raising a generic BotoServerError.
4ffaa8e
@jamesls
Owner

Just a thought...the dynamodb client passes in the override_num_retries param, so the _retry_handler knows when it's on the last retry attempt by checking if i > self.NumberRetries. One benefit of doing it this way is that the changes are isolated to the dynamodb client. There's also a chance that the last retry was because of a checksum failure.

@jamesls jamesls closed this in 7ff11e4
@jamesls jamesls referenced this pull request from a commit
@jamesls jamesls Merge branch 'dynamodb-propogate' into develop
Fixes #1226 and #1194.

* dynamodb-propogate:
  Raise specific error when throughput is exceeded
  Remove debug comments
5b5d688
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Dec 7, 2012
  1. @timmyfury

    Passing custom retries exceeded handler to _mexe method in DynamoDB. …

    timmyfury authored
    …This method will handle retries exceeded to raise a throughput exceeded error from amazon rather than raising a generic BotoServerError.
This page is out of date. Refresh to see the latest.
View
7 boto/connection.py
@@ -796,7 +796,7 @@ def get_proxy_auth_header(self):
return {'Proxy-Authorization': 'Basic %s' % auth}
def _mexe(self, request, sender=None, override_num_retries=None,
- retry_handler=None):
+ retry_handler=None, retry_exhausted_handler=None):
"""
mexe - Multi-execute inside a loop, retrying multiple times to handle
transient Internet errors by simply trying again.
@@ -889,7 +889,10 @@ def _mexe(self, request, sender=None, override_num_retries=None,
# use it to raise an exception.
# Otherwise, raise the exception that must have already h#appened.
if response:
- raise BotoServerError(response.status, response.reason, body)
+ if callable(retry_exhausted_handler):
+ retry_exhausted_handler(response)
+ else:
+ raise BotoServerError(response.status, response.reason, body)
elif e:
raise e
else:
View
8 boto/dynamodb/exceptions.py
@@ -45,3 +45,11 @@ class DynamoDBValidationError(DynamoDBResponseError):
has exceeded the 64Kb size limit.
"""
pass
+
+
+class DynamoDBThroughputExceededError(BotoServerError):
+ """
+ Raised when a ProvisionedThroughputExceededException response is receive.
+ This happens after retries have been exceeded.
+ """
+ pass
View
15 boto/dynamodb/layer1.py
@@ -25,7 +25,7 @@
import boto
from boto.connection import AWSAuthConnection
-from boto.exception import DynamoDBResponseError
+from boto.exception import DynamoDBResponseError, BotoServerError
from boto.provider import Provider
from boto.dynamodb import exceptions as dynamodb_exceptions
from boto.compat import json
@@ -122,7 +122,8 @@ def make_request(self, action, body='', object_hook=None):
start = time.time()
response = self._mexe(http_request, sender=None,
override_num_retries=self.NumberRetries,
- retry_handler=self._retry_handler)
+ retry_handler=self._retry_handler,
+ retry_exhausted_handler=self._retry_exhausted_handler)
elapsed = (time.time() - start) * 1000
request_id = response.getheader('x-amzn-RequestId')
boto.log.debug('RequestId: %s' % request_id)
@@ -169,6 +170,16 @@ def _retry_handler(self, response, i, next_sleep):
status = (msg, i + 1, self._exponential_time(i))
return status
+ def _retry_exhausted_handler(self, response):
+ if response.status == 400:
+ response_body = response.read()
+ boto.log.debug(response_body)
+ data = json.loads(response_body)
+ if self.ThruputError in data.get('__type'):
+ raise dynamodb_exceptions.DynamoDBThroughputExceededError(response.status, response.reason, data)
+ else:
+ raise BotoServerError(response.status, response.reason, data)
+
def _exponential_time(self, i):
if i == 0:
next_sleep = 0
Something went wrong with that request. Please try again.