Class: ESIUtils::ESIClient

Inherits:
ESI::ApiClient
  • Object
show all
Defined in:
lib/esi-utils-bvv/esiclient.rb

Overview

ESIUtils::Client

API client that extends call_api to look for API warnings.

Instance Method Summary collapse

Constructor Details

#initializeESIClient

Returns a new instance of ESIClient.



12
13
14
15
16
# File 'lib/esi-utils-bvv/esiclient.rb', line 12

def initialize
  super
  @seen_warnings = Set.new
  @delay_times = [0, 0.5, 1, 2, 5, 15].freeze
end

Instance Method Details

#call_api(http_method, path, opts = {}) ⇒ Object

Customised call_api, which wraps itself around the one provided by the Swagger generated code.

Adds:

  • Logging of warning headers when the API is versioned.

  • Automatic retrying of temporary failures.



91
92
93
94
95
96
97
98
99
100
101
102
103
# File 'lib/esi-utils-bvv/esiclient.rb', line 91

def call_api(http_method, path, opts = {})
  delays = @delay_times.dup
  begin
    data, code, headers = super(http_method, path, opts)
    log_warning_header(path, headers)
    [data, code, headers]
  rescue ESI::ApiError => api_error
    raise unless (secs = can_retry?(api_error, delays))
    logger.info "retrying #{http_method} on '#{path}' after #{secs}s"
    sleep(secs)
    retry
  end
end

#can_retry?(api_error, delays) ⇒ Boolean

Can we retry?

Based on the details of the APIError exception along with an array of remaining retry delays.

If retrying is possible, the result is a number of seconds to delay before performing the next attempt.

Returns:

  • (Boolean)


73
74
75
76
77
78
79
80
# File 'lib/esi-utils-bvv/esiclient.rb', line 73

def can_retry?(api_error, delays)
  # Can't retry if we have exhausted our list of retry delays.
  return false if delays.empty?
  # Only certain status codes are retryable.
  return false unless retry_status?(api_error.code)
  # Peel off a time to delay for before retrying.
  delays.shift
end

#log_warning_header(path, headers) ⇒ Object

Log deprecation warnings, as they indicate that we need to upgrade to a new version of the route.



30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
# File 'lib/esi-utils-bvv/esiclient.rb', line 30

def log_warning_header(path, headers)
  return unless (warning = headers['Warning'])

  # Don't warn just because a new route is available.
  return if warning.start_with? '199'

  # Genericise the path, removing parameters
  g_path = path.gsub(%r{/\d+/}, '/id/')

  # Only notify about a given (genericised) path once
  return if @seen_warnings.include?(g_path)
  @seen_warnings.add(g_path)

  logger.warn "'#{warning}' on path '#{g_path}'"
end

#loggerObject

Shorthand access to the base API client’s configured logger.



22
23
24
# File 'lib/esi-utils-bvv/esiclient.rb', line 22

def logger
  @config.logger
end

#retry_status?(code) ⇒ Boolean

Does the given HTTP status code represent something that we should retry?

420 Error Limited 502 Bad Gateway 503 Service Unavailable 504 Gateway Timeout

Returns:

  • (Boolean)


55
56
57
58
59
60
61
62
# File 'lib/esi-utils-bvv/esiclient.rb', line 55

def retry_status?(code)
  case code
  when 420, 502, 503, 504
    true
  else
    false
  end
end