Class: Excon::Middleware::AWS::ExponentialBackoff
- Inherits:
-
Base
- Object
- Base
- Excon::Middleware::AWS::ExponentialBackoff
- Defined in:
- lib/excon/middleware/aws/exponential_backoff.rb,
lib/excon/middleware/aws/exponential_backoff/version.rb
Constant Summary collapse
- MILLISECOND =
1.0/1000
- SLEEP_FACTOR =
MILLISECOND * 100
- ERROR_CODE_REGEX =
Regexp.new(/<Code>([^<]+)<\/Code>/mi)
- THROTTLING_ERROR_CODES =
%w[ Throttling ThrottlingException ProvisionedThroughputExceededException RequestThrottled RequestLimitExceeded BandwidthLimitExceeded ]
- SERVER_ERROR_CLASSES =
[ Excon::Errors::InternalServerError, Excon::Errors::BadGateway, Excon::Errors::ServiceUnavailable, Excon::Errors::GatewayTimeout ]
- VALID_MIDDLEWARE_KEYS =
[ :backoff ]
- VERSION =
"0.0.2"
Instance Method Summary collapse
- #do_backoff(datum) ⇒ Object
- #do_handoff(datum) ⇒ Object
- #do_sleep(sleep_time, datum) ⇒ Object
- #error_call(datum) ⇒ Object
- #extract_error_code(body) ⇒ Object
- #server_error?(datum) ⇒ Boolean
- #should_retry?(datum) ⇒ Boolean
- #sleep_time(datum) ⇒ Object
- #throttle?(datum) ⇒ Boolean
Instance Method Details
#do_backoff(datum) ⇒ Object
46 47 48 49 50 51 52 |
# File 'lib/excon/middleware/aws/exponential_backoff.rb', line 46 def do_backoff(datum) do_sleep(sleep_time(datum), datum) datum[:backoff][:retry_count] += 1 connection = datum.delete(:connection) datum.reject! { |key, _| !(Excon::VALID_REQUEST_KEYS + VALID_MIDDLEWARE_KEYS).include?(key) } connection.request(datum) end |
#do_handoff(datum) ⇒ Object
42 43 44 |
# File 'lib/excon/middleware/aws/exponential_backoff.rb', line 42 def do_handoff(datum) @stack.error_call(datum) end |
#do_sleep(sleep_time, datum) ⇒ Object
54 55 56 57 58 59 60 61 62 |
# File 'lib/excon/middleware/aws/exponential_backoff.rb', line 54 def do_sleep(sleep_time, datum) if datum.has_key?(:instrumentor) datum[:instrumentor].instrument("#{datum[:instrumentor_name]}.backoff", datum) do sleep sleep_time end else sleep sleep_time end end |
#error_call(datum) ⇒ Object
29 30 31 32 33 34 35 36 37 38 39 40 |
# File 'lib/excon/middleware/aws/exponential_backoff.rb', line 29 def error_call(datum) datum[:backoff] ||= {} datum[:backoff][:max_retries] ||= 0 datum[:backoff][:max_delay] ||= 30 datum[:backoff][:retry_count] ||= 0 if (throttle?(datum) || server_error?(datum)) && should_retry?(datum) do_backoff(datum) else do_handoff(datum) end end |
#extract_error_code(body) ⇒ Object
89 90 91 92 93 94 |
# File 'lib/excon/middleware/aws/exponential_backoff.rb', line 89 def extract_error_code(body) match = ERROR_CODE_REGEX.match(body) if match && code = match[1] code.strip if code end end |
#server_error?(datum) ⇒ Boolean
85 86 87 |
# File 'lib/excon/middleware/aws/exponential_backoff.rb', line 85 def server_error?(datum) SERVER_ERROR_CLASSES.any? { |ex| datum[:error].kind_of?(ex) } end |
#should_retry?(datum) ⇒ Boolean
72 73 74 75 76 |
# File 'lib/excon/middleware/aws/exponential_backoff.rb', line 72 def should_retry?(datum) # Always retry if max_retries is 0. datum[:backoff][:max_retries] == 0 || datum[:backoff][:retry_count] < datum[:backoff][:max_retries] end |
#sleep_time(datum) ⇒ Object
64 65 66 67 68 69 70 |
# File 'lib/excon/middleware/aws/exponential_backoff.rb', line 64 def sleep_time(datum) exponential_wait = (2 ** datum[:backoff][:retry_count] + rand(0.0)) * SLEEP_FACTOR [ exponential_wait, datum[:backoff][:max_delay] ].min.round(2) end |
#throttle?(datum) ⇒ Boolean
78 79 80 81 82 83 |
# File 'lib/excon/middleware/aws/exponential_backoff.rb', line 78 def throttle?(datum) datum[:error].kind_of?(Excon::Errors::BadRequest) && THROTTLING_ERROR_CODES.include?(extract_error_code(datum[:error].response.body)) end |