def execute(self, action, parameters):
        """
        Execute a DynamoDB action with the given parameters. The method will
        retry requests that failed due to OS level errors or when being
        throttled by DynamoDB.

        :param str action: DynamoDB action to invoke
        :param dict parameters: parameters to send into the action
        :rtype: tornado.concurrent.Future

        This method creates a future that will resolve to the result
        of calling the specified DynamoDB function.  It does it's best
        to unwrap the response from the function to make life a little
        easier for you.  It does this for the ``GetItem`` and ``Query``
        functions currently.

        :raises:
            :exc:`~sprockets_dynamodb.exceptions.DynamoDBException`
            :exc:`~sprockets_dynamodb.exceptions.ConfigNotFound`
            :exc:`~sprockets_dynamodb.exceptions.NoCredentialsError`
            :exc:`~sprockets_dynamodb.exceptions.NoProfileError`
            :exc:`~sprockets_dynamodb.exceptions.TimeoutException`
            :exc:`~sprockets_dynamodb.exceptions.RequestException`
            :exc:`~sprockets_dynamodb.exceptions.InternalFailure`
            :exc:`~sprockets_dynamodb.exceptions.LimitExceeded`
            :exc:`~sprockets_dynamodb.exceptions.MissingParameter`
            :exc:`~sprockets_dynamodb.exceptions.OptInRequired`
            :exc:`~sprockets_dynamodb.exceptions.ResourceInUse`
            :exc:`~sprockets_dynamodb.exceptions.RequestExpired`
            :exc:`~sprockets_dynamodb.exceptions.ResourceNotFound`
            :exc:`~sprockets_dynamodb.exceptions.ServiceUnavailable`
            :exc:`~sprockets_dynamodb.exceptions.ThroughputExceeded`
            :exc:`~sprockets_dynamodb.exceptions.ValidationException`

        """
        measurements = collections.deque([], self._max_retries)
        for attempt in range(1, self._max_retries + 1):
            try:
                result = yield self._execute(
                    action, parameters, attempt, measurements)
            except (exceptions.InternalServerError,
                    exceptions.RequestException,
                    exceptions.ThrottlingException,
                    exceptions.ThroughputExceeded,
                    exceptions.ServiceUnavailable) as error:
                if attempt == self._max_retries:
                    if self._instrumentation_callback:
                        self._instrumentation_callback(measurements)
                    self._on_exception(error)
                duration = self._sleep_duration(attempt)
                self.logger.warning('%r on attempt %i, sleeping %.2f seconds',
                                    error, attempt, duration)
                yield gen.sleep(duration)
            except exceptions.DynamoDBException as error:
                if self._instrumentation_callback:
                    self._instrumentation_callback(measurements)
                self._on_exception(error)
            else:
                if self._instrumentation_callback:
                    self._instrumentation_callback(measurements)
                self.logger.debug('%s result: %r', action, result)
                raise gen.Return(_unwrap_result(action, result))