Class: Sumologic::Http::Client

Inherits:
Object
  • Object
show all
Defined in:
lib/sumologic/http/client.rb

Overview

Orchestrates HTTP communication with Sumo Logic API Delegates to specialized components for request building, response handling, connection pooling, and cookie management

Features automatic retry with exponential backoff for:

  • Rate limit errors (429)

  • Server errors (5xx)

  • Connection errors

Constant Summary collapse

RETRYABLE_EXCEPTIONS =

Errors that are safe to retry

[
  Errno::ECONNRESET,
  Errno::EPIPE,
  Errno::ETIMEDOUT,
  Errno::ECONNREFUSED,
  EOFError,
  Net::HTTPBadResponse,
  Net::OpenTimeout,
  Net::ReadTimeout
].freeze

Instance Method Summary collapse

Constructor Details

#initialize(base_url:, authenticator:, config: nil) ⇒ Client



32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
# File 'lib/sumologic/http/client.rb', line 32

def initialize(base_url:, authenticator:, config: nil)
  @config = config
  @max_retries = config&.max_retries || 3
  @retry_base_delay = config&.retry_base_delay || 1.0
  @retry_max_delay = config&.retry_max_delay || 30.0

  @cookie_jar = CookieJar.new
  @request_builder = RequestBuilder.new(
    base_url: base_url,
    authenticator: authenticator,
    cookie_jar: @cookie_jar
  )
  @response_handler = ResponseHandler.new
  @connection_pool = ConnectionPool.new(
    base_url: base_url,
    max_connections: 10,
    read_timeout: config&.read_timeout,
    connect_timeout: config&.connect_timeout
  )
end

Instance Method Details

#close_all_connectionsObject

Close all connections in the pool



89
90
91
# File 'lib/sumologic/http/client.rb', line 89

def close_all_connections
  @connection_pool.close_all
end

#request(method:, path:, body: nil, query_params: nil) ⇒ Object

Execute HTTP request with automatic retry for transient errors Uses connection pool for thread-safe parallel execution



55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
# File 'lib/sumologic/http/client.rb', line 55

def request(method:, path:, body: nil, query_params: nil)
  uri = @request_builder.build_uri(path, query_params)
  attempt = 0

  loop do
    attempt += 1
    request = @request_builder.build_request(method, uri, body)

    DebugLogger.log_request(method, uri, body, request.to_hash)

    begin
      response = execute_request(uri, request)
      DebugLogger.log_response(response)

      # Check if response is retryable before handling
      if @response_handler.retryable?(response) && attempt <= @max_retries
        delay = calculate_retry_delay(attempt, response)
        log_retry(attempt, delay, "HTTP #{response.code}")
        sleep(delay)
        next
      end

      return @response_handler.handle(response)
    rescue *RETRYABLE_EXCEPTIONS => e
      raise Error, "Connection error: #{e.message}" if attempt > @max_retries

      delay = calculate_retry_delay(attempt)
      log_retry(attempt, delay, e.class.name)
      sleep(delay)
    end
  end
end