Class: SmartyStreets::RetrySender

Inherits:
Object
  • Object
show all
Defined in:
lib/smartystreets_ruby_sdk/retry_sender.rb

Constant Summary collapse

MAX_BACKOFF_DURATION =
10
STATUS_TOO_MANY_REQUESTS =
429
STATUS_TO_RETRY =
[408, 429, 500, 502, 503, 504]
TIMEOUT_ERRORS =
[Net::OpenTimeout, Net::ReadTimeout, Timeout::Error, Errno::ETIMEDOUT]

Instance Method Summary collapse

Constructor Details

#initialize(max_retries, inner, sleeper, logger) ⇒ RetrySender

Returns a new instance of RetrySender.



11
12
13
14
15
16
# File 'lib/smartystreets_ruby_sdk/retry_sender.rb', line 11

def initialize(max_retries, inner, sleeper, logger)
  @max_retries = max_retries
  @inner = inner
  @sleeper = sleeper
  @logger = logger
end

Instance Method Details

#backoff(attempt, message = 'There was an error processing the request.') ⇒ Object



57
58
59
60
61
62
# File 'lib/smartystreets_ruby_sdk/retry_sender.rb', line 57

def backoff(attempt, message = 'There was an error processing the request.')
  backoff_duration = [attempt, MAX_BACKOFF_DURATION].min

  @logger.log("#{message} Retrying in #{backoff_duration} seconds...")
  @sleeper.sleep(backoff_duration)
end

#rate_limit_backoff(backoff_duration) ⇒ Object



64
65
66
67
# File 'lib/smartystreets_ruby_sdk/retry_sender.rb', line 64

def rate_limit_backoff(backoff_duration)
  @logger.log("Rate limit reached. Retrying in #{backoff_duration} seconds...")
  @sleeper.sleep(backoff_duration)
end

#send(request) ⇒ Object



18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
# File 'lib/smartystreets_ruby_sdk/retry_sender.rb', line 18

def send(request)
  response = @inner.send(request)

  (1..@max_retries).each do |i|

    if timeout_error?(response.error)
      timeout_backoff(i, response.error)
      response = @inner.send(request)
    elsif !STATUS_TO_RETRY.include?(response.status_code.to_i)
      break
    else
      if response.status_code.to_i == STATUS_TOO_MANY_REQUESTS
        seconds_to_backoff = 10
        unless response.header.nil?
          if Integer(response.header["Retry-After"], exception: false)
            seconds_to_backoff = response.header["Retry-After"].to_i
          end
        end
        rate_limit_backoff(seconds_to_backoff)
      else
        backoff(i)
      end
      response = @inner.send(request)
    end
  end

  response
end

#timeout_backoff(attempt, error) ⇒ Object



53
54
55
# File 'lib/smartystreets_ruby_sdk/retry_sender.rb', line 53

def timeout_backoff(attempt, error)
  backoff(attempt, "Timeout error (#{error.class}).")
end

#timeout_error?(error) ⇒ Boolean

Returns:

  • (Boolean)


47
48
49
50
51
# File 'lib/smartystreets_ruby_sdk/retry_sender.rb', line 47

def timeout_error?(error)
  return false if error.nil?

  TIMEOUT_ERRORS.any? { |klass| error.is_a?(klass) }
end