Class: TestingBot::Connection

Inherits:
Object
  • Object
show all
Defined in:
lib/testingbot/connection.rb

Overview

Transport layer for the TestingBot API.

Owns the base URL, API version, credentials and HTTP client, and exposes a single request entry point that every endpoint goes through. Centralising transport here means timeouts, retries/backoff, rate-limit handling, JSON parsing, error mapping and debug redaction all live in one place.

The HTTP client is injectable (http:) so the gem can be unit-tested without real network access.

Constant Summary collapse

API_URL =
"https://api.testingbot.com".freeze
API_VERSION =
1
DEFAULT_OPEN_TIMEOUT =
10
DEFAULT_READ_TIMEOUT =
30
DEFAULT_MAX_RETRIES =
3
IDEMPOTENT =

Verbs safe to retry automatically. POST is excluded so we never replay a side-effecting create/upload.

[:get, :put, :delete].freeze
RETRYABLE =

Transient failures worth retrying on idempotent verbs.

[
  RestClient::RequestTimeout,        # 408
  RestClient::TooManyRequests,       # 429
  RestClient::InternalServerError,   # 500
  RestClient::BadGateway,            # 502
  RestClient::ServiceUnavailable,    # 503
  RestClient::GatewayTimeout,        # 504
  RestClient::Exceptions::Timeout,   # open/read timeout
  RestClient::ServerBrokeConnection,
  SocketError,
  Errno::ECONNRESET,
  Errno::ECONNREFUSED,
  Errno::EHOSTUNREACH,
  Errno::ETIMEDOUT
].freeze
REDACT_KEYS =

Response keys whose values are redacted in debug output.

%w[key secret api_key api_secret client_key token password].freeze

Instance Method Summary collapse

Constructor Details

#initialize(key:, secret:, options: {}, http: RestClient::Request) ⇒ Connection

Returns a new instance of Connection.



48
49
50
51
52
53
# File 'lib/testingbot/connection.rb', line 48

def initialize(key:, secret:, options: {}, http: RestClient::Request)
  @key     = key
  @secret  = secret
  @options = options || {}
  @http    = http
end

Instance Method Details

#request(verb, path, params = {}, opts = {}) ⇒ Object

Execute an HTTP request and return the parsed JSON body.

verb - one of :get, :post, :put, :delete path - path after the version prefix, e.g. “/tests/123” params - request payload (ignored for :get and for empty payloads) opts - per-call overrides, e.g. { timeout: 600 } for uploads



61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
# File 'lib/testingbot/connection.rb', line 61

def request(verb, path, params = {}, opts = {})
  idempotent = IDEMPOTENT.include?(verb)
  attempt = 0

  begin
    parse(execute(verb, path, params, opts))
  rescue *RETRYABLE => e
    attempt += 1
    if idempotent && attempt <= max_retries
      sleep(delay_for(e, attempt))
      retry
    end
    raise map_exception(e)
  rescue RestClient::ExceptionWithResponse => e
    raise map_exception(e)
  end
end