Class: Shazamio::HTTPClient

Inherits:
Object
  • Object
show all
Defined in:
lib/shazamio/http_client.rb

Overview

Thin Net::HTTP wrapper with exponential-backoff retries, mirroring the Python client's use of aiohttp_retry.ExponentialRetry(attempts: 20, max_timeout: 60, statuses: 502, 503, 504, 429).

Ruby has no first-class async story equivalent to asyncio/aiohttp in the standard library, so this client is synchronous. Wrap calls in threads or fibers (or use the async/async-http gems) if you need concurrency.

Defined Under Namespace

Classes: Retryable

Constant Summary collapse

RETRY_STATUSES =
[429, 500, 502, 503, 504].freeze

Instance Method Summary collapse

Constructor Details

#initialize(attempts: 20, max_timeout: 60, open_timeout: 10, read_timeout: 30) ⇒ HTTPClient

Returns a new instance of HTTPClient.



21
22
23
24
25
26
# File 'lib/shazamio/http_client.rb', line 21

def initialize(attempts: 20, max_timeout: 60, open_timeout: 10, read_timeout: 30)
  @attempts = attempts
  @max_timeout = max_timeout
  @open_timeout = open_timeout
  @read_timeout = read_timeout
end

Instance Method Details

#request(method, url, headers: {}, params: nil, json: nil, proxy: nil, content_type: "application/json") ⇒ Object

Parameters:

  • method (String)

    "GET" or "POST"

  • url (String)
  • headers (Hash) (defaults to: {})
  • params (Hash) (defaults to: nil)

    query string params (GET only)

  • json (Hash) (defaults to: nil)

    JSON body (POST only)

  • proxy (String, nil) (defaults to: nil)
  • content_type (String) (defaults to: "application/json")

    expected response content type for JSON validation



35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
# File 'lib/shazamio/http_client.rb', line 35

def request(method, url, headers: {}, params: nil, json: nil, proxy: nil, content_type: "application/json")
  uri = build_uri(url, params)

  attempt = 0
  backoff = 1.0

  begin
    attempt += 1
    response = perform(method, uri, headers, json, proxy)

    if RETRY_STATUSES.include?(response.code.to_i) && attempt < @attempts
      sleep([backoff, @max_timeout].min)
      backoff *= 2
      raise Retryable
    end

    parse_json(response, content_type)
  rescue Retryable
    retry
  end
end