Skip to content
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 1 addition & 3 deletions gems/smithy-client/lib/smithy-client/http/response.rb
Original file line number Diff line number Diff line change
Expand Up @@ -98,9 +98,7 @@ def signal_done(options = {})
@done = true
emit(:done)
else
msg = 'options must be empty or must contain :status_code, :headers, ' \
'and :body'
raise ArgumentError, msg
raise ArgumentError, 'options must be empty or must contain :status_code, :headers, and :body'
end
end

Expand Down
27 changes: 17 additions & 10 deletions gems/smithy-client/lib/smithy-client/log_param_formatter.rb
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@ def initialize(options = {})

def summarize(value)
case value
when Array then "[#{array(value)}]"
when Array then array(value)
when File then file(value)
when Hash then "{ #{hash(value)} }"
when Hash then hash(value)
when Pathname then pathname(value)
when String then string(value)
when Tempfile then tempfile(value)
Expand All @@ -36,17 +36,24 @@ def string(str)
end

def hash(hash)
hash.map do |key, value|
if key.is_a?(String)
"#{key.inspect} => #{summarize(value)}"
else
"#{key}: #{summarize(value)}"
end
end.join(', ')
return if hash.empty?

res =
hash.map do |key, value|
if key.is_a?(String)
"#{key.inspect} => #{summarize(value)}"
else
"#{key}: #{summarize(value)}"
end
end.join(', ')
"{ #{res} }"
end

def array(array)
array.map { |v| summarize(v) }.join(', ')
return if array.empty?

res = array.map { |v| summarize(v) }.join(', ')
"[#{res}]"
end

def file(file)
Expand Down
7 changes: 1 addition & 6 deletions gems/smithy-client/lib/smithy-client/net_http/handler.rb
Original file line number Diff line number Diff line change
Expand Up @@ -137,12 +137,7 @@ def net_http_request_class(request)
# @param [Http::Request] request
# @return [Hash<String, String>]
def net_headers_for(request)
# Net::HTTP adds a default header for accept-encoding (2.0.0+).
# Setting a default empty value defeats this.
# Removing this is necessary for most services to not break request
# signatures as well as dynamodb crc32 checks (these fail if the
# response is gzipped).
headers = { 'accept-encoding' => '' }
headers = {}
request.headers.each_pair do |key, value|
headers[key] = value
end
Expand Down
2 changes: 1 addition & 1 deletion gems/smithy-client/lib/smithy-client/pageable_response.rb
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ def next_page_params(params)
prev_tokens = @paginator.prev_tokens(context.params)
# Remove all previous tokens from original params
# Sometimes a token can be nil and merge would not include it.
new_params = context.params.except(*prev_tokens)
new_params = context[:original_params].except(*prev_tokens)
new_params.merge!(@paginator.next_tokens(data).merge(params))
end
end
Expand Down
2 changes: 1 addition & 1 deletion gems/smithy-client/lib/smithy-client/param_converter.rb
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ def union(ref, values)
if values.is_a?(Schema::Union)
_name, member_ref = ref.shape.member_by_type(values.class)
values = shape(member_ref, values)
else
elsif values.is_a?(Hash)
key, value = values.first
values[key] = shape(ref.shape.member(key), value)
end
Expand Down
2 changes: 1 addition & 1 deletion gems/smithy-client/lib/smithy-client/param_validator.rb
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ def union(ref, values, errors, context)
if values.is_a?(Schema::Union)
_name, member_ref = ref.shape.member_by_type(values.class)
shape(member_ref, values.value, errors, context)
else
elsif values.is_a?(Hash)
values.each_pair do |name, value|
next if value.nil?

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ class PageableResponse < Plugin
# @api private
class Handler < Client::Handler
def call(context)
context[:original_params] = context.params
response = @handler.call(context)
response.extend(Client::PageableResponse)
response.paginator = context.operation[:paginator] || NullPaginator.new
Expand Down
31 changes: 27 additions & 4 deletions gems/smithy-client/lib/smithy-client/plugins/retry_errors.rb
Original file line number Diff line number Diff line change
Expand Up @@ -33,15 +33,38 @@ class RetryErrors < Plugin
DOCS

option(
:retry_backoff,
default: Retry::EXPONENTIAL_BACKOFF,
doc_default: 'Smithy::Client::Retry::EXPONENTIAL_BACKOFF',
doc_type: 'lambda',
:retry_max_delay,
default: 20,
docstring: <<~DOCS)
The maximum delay, in seconds, between retry attempts. This option is ignored
if a custom `retry_backoff` is provided. Used in the `standard` and `adaptive`
retry strategies.
DOCS

option(
:retry_base_delay,
default: 2,
docstring: <<~DOCS)
The base delay, in seconds, used to calculate the exponential backoff for
retry attempts. This option is ignored if a custom `retry_backoff` is provided.
Used in the `standard` and `adaptive` retry strategies.
DOCS

option(
:retry_backoff,
doc_default: 'Smithy::Client::Retry::ExponentialBackoff.new',
rbs_type: 'Smithy::Client::Retry::ExponentialBackoff',
doc_type: '#call(attempts)',
docstring: <<~DOCS) do |config|
A callable object that calculates a backoff delay for a retry attempt. The callable
should accept a single argument, `attempts`, that represents the number of attempts
that have been made. Used in the `standard` and `adaptive` retry strategies.
DOCS
Retry::ExponentialBackoff.new(
retry_base_delay: config.retry_base_delay,
retry_max_delay: config.retry_max_delay
)
end

option(
:adaptive_retry_wait_to_fill,
Expand Down
32 changes: 2 additions & 30 deletions gems/smithy-client/lib/smithy-client/retry.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,35 +2,7 @@

require_relative 'retry/adaptive'
require_relative 'retry/client_rate_limiter'
require_relative 'retry/exponential_backoff'
require_relative 'retry/quota'
require_relative 'retry/standard'

module Smithy
module Client
module Retry
# The maximum backoff delay for retrying requests.
MAX_BACKOFF = 20

# The default backoff for retrying requests.
EXPONENTIAL_BACKOFF = lambda do |attempts|
[Kernel.rand * (2**attempts), MAX_BACKOFF].min || 0
end

# Represents a token that can be used to retry an operation.
class Token
def initialize
@retry_count = 0
@retry_delay = 0
end

# The number of times the operation has been retried.
# @return [Integer]
attr_accessor :retry_count

# The delay before the next retry.
# @return [Numeric]
attr_accessor :retry_delay
end
end
end
end
require_relative 'retry/token'
7 changes: 5 additions & 2 deletions gems/smithy-client/lib/smithy-client/retry/adaptive.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ module Client
module Retry
# Adaptive retry strategy for retrying requests.
class Adaptive
# @option [#call] :backoff (EXPONENTIAL_BACKOFF) A callable object that
# @option [#call] :backoff (ExponentialBackoff.new) A callable object that
# calculates a backoff delay for a retry attempt.
# @option [Integer] :max_attempts (3) The maximum number of attempts that
# will be made for a single request, including the initial attempt.
Expand All @@ -15,7 +15,10 @@ class Adaptive
# not retry instead of sleeping.
def initialize(options = {})
super()
@backoff = options[:backoff] || EXPONENTIAL_BACKOFF
@backoff = options[:backoff] || ExponentialBackoff.new(
base_delay: options[:base_delay],
max_delay: options[:max_delay]
)
@max_attempts = options[:max_attempts] || 3
@wait_to_fill = options[:wait_to_fill] || true
@client_rate_limiter = ClientRateLimiter.new
Expand Down
29 changes: 29 additions & 0 deletions gems/smithy-client/lib/smithy-client/retry/exponential_backoff.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# frozen_string_literal: true

module Smithy
module Client
module Retry
# Default exponential backoff retry strategy for retrying requests.
class ExponentialBackoff
def initialize(options = {})
@base_delay = options[:base_delay] || 2
@max_delay = options[:max_delay] || 20
end

# @return [Numeric]
attr_reader :base_delay

# @return [Numeric]
attr_reader :max_delay

# Calculates a delay based on exponential backoff strategy. Uses full jitter approach.
# @param [Integer] attempts
# @return [Numeric] delay in seconds
def call(attempts)
delay = (@base_delay**attempts)
[delay, @max_delay].min * Kernel.rand
end
end
end
end
end
7 changes: 5 additions & 2 deletions gems/smithy-client/lib/smithy-client/retry/standard.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,16 @@ module Client
module Retry
# Standard retry strategy for retrying requests.
class Standard
# @option [#call] :backoff (EXPONENTIAL_BACKOFF) A callable object that
# @option [#call] :backoff (ExponentialBackoff.new) A callable object that
# calculates a backoff delay for a retry attempt.
# @option [Integer] :max_attempts (3) The maximum number of attempts that
# will be made for a single request, including the initial attempt.
def initialize(options = {})
super()
@backoff = options[:backoff] || EXPONENTIAL_BACKOFF
@backoff = options[:backoff] || ExponentialBackoff.new(
base_delay: options[:base_delay],
max_delay: options[:max_delay]
)
@max_attempts = options[:max_attempts] || 3
@quota = Quota.new
@capacity_amount = 0
Expand Down
23 changes: 23 additions & 0 deletions gems/smithy-client/lib/smithy-client/retry/token.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# frozen_string_literal: true

module Smithy
module Client
module Retry
# Represents a token that can be used to retry an operation.
class Token
def initialize
@retry_count = 0
@retry_delay = 0
end

# The number of times the operation has been retried.
# @return [Integer]
attr_accessor :retry_count

# The delay before the next retry.
# @return [Numeric]
attr_accessor :retry_delay
end
end
end
end
12 changes: 12 additions & 0 deletions gems/smithy-client/sig/smithy-client/retry/exponential_backoff.rbs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
module Smithy
module Client
module Retry
class ExponentialBackoff
def initialize: (?Hash[Symbol, untyped] options) -> void
attr_reader base_delay: Numeric
attr_reader max_delay: Numeric
def call: (Integer attempts) -> Numeric
end
end
end
end
Original file line number Diff line number Diff line change
Expand Up @@ -203,8 +203,8 @@ module Plugins
end

it 'does not exceed the max backoff time' do
config.retry_strategy = Retry::Standard.new(max_delay: 3)
retry_strategy.instance_variable_set(:@max_attempts, 5)
stub_const('Smithy::Client::Retry::MAX_BACKOFF', 3)

test_case_def = [
{
Expand Down
6 changes: 4 additions & 2 deletions gems/smithy/lib/smithy/views/client/module.rb
Original file line number Diff line number Diff line change
Expand Up @@ -58,9 +58,11 @@ def relative_requires
# types must come before schemas
return %i[customizations types schema] if @plan.type == :schema

# types must come before schemas
# paginators must come before schemas
%w[types paginators schema auth_parameters auth_resolver client customizations errors endpoint_parameters
endpoint_provider waiters]
# customizations must come last
%w[types paginators schema auth_parameters auth_resolver client errors
endpoint_parameters endpoint_provider waiters customizations]
end

private
Expand Down
2 changes: 1 addition & 1 deletion projections/shapes/lib/shapes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ module ShapeService
require_relative 'shapes/auth_parameters'
require_relative 'shapes/auth_resolver'
require_relative 'shapes/client'
require_relative 'shapes/customizations'
require_relative 'shapes/errors'
require_relative 'shapes/endpoint_parameters'
require_relative 'shapes/endpoint_provider'
require_relative 'shapes/waiters'
require_relative 'shapes/customizations'
10 changes: 9 additions & 1 deletion projections/shapes/lib/shapes/client.rb
Original file line number Diff line number Diff line change
Expand Up @@ -140,13 +140,21 @@ class Client < Smithy::Client::Base
# @option options [Integer] :request_min_compression_size_bytes (10240)
# The minimum size in bytes that triggers compression for request bodies.
# The value must be non-negative integer value between 0 and 10,485,780 bytes inclusive.
# @option options [lambda] :retry_backoff (Smithy::Client::Retry::EXPONENTIAL_BACKOFF)
# @option options [#call(attempts)] :retry_backoff (Smithy::Client::Retry::ExponentialBackoff.new)
# A callable object that calculates a backoff delay for a retry attempt. The callable
# should accept a single argument, `attempts`, that represents the number of attempts
# that have been made. Used in the `standard` and `adaptive` retry strategies.
# @option options :retry_base_delay (2)
# The base delay, in seconds, used to calculate the exponential backoff for
# retry attempts. This option is ignored if a custom `retry_backoff` is provided.
# Used in the `standard` and `adaptive` retry strategies.
# @option options [Integer] :retry_max_attempts (3)
# The maximum number attempts that will be made for a single request, including
# the initial attempt. Used in the `standard` and `adaptive` retry strategies.
# @option options :retry_max_delay (20)
# The maximum delay, in seconds, between retry attempts. This option is ignored
# if a custom `retry_backoff` is provided. Used in the `standard` and `adaptive`
# retry strategies.
# @option options [String, Class] :retry_strategy ('standard')
# The retry strategy to use when retrying errors. This can be one of the following:
# * `standard` - A standardized retry strategy used by the AWS SDKs. This includes support
Expand Down
4 changes: 3 additions & 1 deletion projections/shapes/sig/shapes/client.rbs
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,10 @@ module ShapeService
?logger: Logger,
?raise_response_errors: bool,
?request_min_compression_size_bytes: Integer,
?retry_backoff: lambda,
?retry_backoff: #call(attempts),
?retry_base_delay: untyped,
?retry_max_attempts: Integer,
?retry_max_delay: untyped,
?retry_strategy: String | Class,
?stub_responses: bool,
?user_agent_suffix: String,
Expand Down
2 changes: 1 addition & 1 deletion projections/weather/lib/weather.rb
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ module Weather
require_relative 'weather/auth_parameters'
require_relative 'weather/auth_resolver'
require_relative 'weather/client'
require_relative 'weather/customizations'
require_relative 'weather/errors'
require_relative 'weather/endpoint_parameters'
require_relative 'weather/endpoint_provider'
require_relative 'weather/waiters'
require_relative 'weather/customizations'
10 changes: 9 additions & 1 deletion projections/weather/lib/weather/client.rb
Original file line number Diff line number Diff line change
Expand Up @@ -140,13 +140,21 @@ class Client < Smithy::Client::Base
# @option options [Integer] :request_min_compression_size_bytes (10240)
# The minimum size in bytes that triggers compression for request bodies.
# The value must be non-negative integer value between 0 and 10,485,780 bytes inclusive.
# @option options [lambda] :retry_backoff (Smithy::Client::Retry::EXPONENTIAL_BACKOFF)
# @option options [#call(attempts)] :retry_backoff (Smithy::Client::Retry::ExponentialBackoff.new)
# A callable object that calculates a backoff delay for a retry attempt. The callable
# should accept a single argument, `attempts`, that represents the number of attempts
# that have been made. Used in the `standard` and `adaptive` retry strategies.
# @option options :retry_base_delay (2)
# The base delay, in seconds, used to calculate the exponential backoff for
# retry attempts. This option is ignored if a custom `retry_backoff` is provided.
# Used in the `standard` and `adaptive` retry strategies.
# @option options [Integer] :retry_max_attempts (3)
# The maximum number attempts that will be made for a single request, including
# the initial attempt. Used in the `standard` and `adaptive` retry strategies.
# @option options :retry_max_delay (20)
# The maximum delay, in seconds, between retry attempts. This option is ignored
# if a custom `retry_backoff` is provided. Used in the `standard` and `adaptive`
# retry strategies.
# @option options [String, Class] :retry_strategy ('standard')
# The retry strategy to use when retrying errors. This can be one of the following:
# * `standard` - A standardized retry strategy used by the AWS SDKs. This includes support
Expand Down
Loading