class KnapsackPro::Client::Connection

Constants

REQUEST_RETRY_TIMEBOX
TIMEOUT

Attributes

action[R]
http_response[R]
response_body[R]

Public Class Methods

new(action) click to toggle source
# File lib/knapsack_pro/client/connection.rb, line 11
def initialize(action)
  @action = action
end

Public Instance Methods

api_code() click to toggle source
# File lib/knapsack_pro/client/connection.rb, line 30
def api_code
  return unless response_body
  response_body['code']
end
call() click to toggle source
# File lib/knapsack_pro/client/connection.rb, line 15
def call
  send(action.http_method)
end
errors?() click to toggle source
# File lib/knapsack_pro/client/connection.rb, line 26
def errors?
  !!(response_body && (response_body['errors'] || response_body['error']))
end
server_error?() click to toggle source
# File lib/knapsack_pro/client/connection.rb, line 35
def server_error?
  status = http_response.code.to_i
  status >= 500 && status < 600
end
success?() click to toggle source
# File lib/knapsack_pro/client/connection.rb, line 19
def success?
  return false if !response_body

  status = http_response.code.to_i
  status >= 200 && status < 500
end

Private Instance Methods

build_http(uri) click to toggle source
# File lib/knapsack_pro/client/connection.rb, line 143
def build_http(uri)
  http = net_http.new(uri.host, uri.port)
  http.use_ssl = (uri.scheme == 'https')
  http.open_timeout = TIMEOUT
  http.read_timeout = TIMEOUT
  http
end
client_name() click to toggle source
# File lib/knapsack_pro/client/connection.rb, line 75
def client_name
  [
    'knapsack_pro-ruby',
    ENV['KNAPSACK_PRO_TEST_RUNNER'],
  ].compact.join('/')
end
endpoint() click to toggle source
# File lib/knapsack_pro/client/connection.rb, line 48
def endpoint
  KnapsackPro::Config::Env.endpoint
end
endpoint_url() click to toggle source
# File lib/knapsack_pro/client/connection.rb, line 52
def endpoint_url
  endpoint + action.endpoint_path
end
get() click to toggle source
# File lib/knapsack_pro/client/connection.rb, line 167
def get
  uri = URI.parse(endpoint_url)
  uri.query = URI.encode_www_form(request_hash)
  http = build_http(uri)
  make_request do
    http.get(uri, json_headers)
  end
end
has_seed?() click to toggle source
# File lib/knapsack_pro/client/connection.rb, line 94
def has_seed?
  !seed.nil?
end
json_headers() click to toggle source
# File lib/knapsack_pro/client/connection.rb, line 64
def json_headers
  {
    'Content-Type' => 'application/json',
    'Accept' => 'application/json',
    'KNAPSACK-PRO-CLIENT-NAME' => client_name,
    'KNAPSACK-PRO-CLIENT-VERSION' => KnapsackPro::VERSION,
    'KNAPSACK-PRO-TEST-SUITE-TOKEN' => KnapsackPro::Config::Env.test_suite_token,
    'KNAPSACK-PRO-CI-PROVIDER' => KnapsackPro::Config::Env.ci_provider,
  }.compact
end
logger() click to toggle source
# File lib/knapsack_pro/client/connection.rb, line 44
def logger
  KnapsackPro.logger
end
make_request(&block) click to toggle source
# File lib/knapsack_pro/client/connection.rb, line 98
def make_request(&block)
  retries ||= 0

  @http_response = block.call
  @response_body = parse_response_body(http_response.body)

  request_uuid = http_response.header['X-Request-Id'] || 'N/A'

  logger.debug("#{action.http_method.to_s.upcase} #{endpoint_url}")
  logger.debug("API request UUID: #{request_uuid}")
  logger.debug("Test suite split seed: #{seed}") if has_seed?
  logger.debug('API response:')
  if errors?
    logger.error(response_body)
  else
    logger.debug(response_body)
  end

  if server_error?
    raise ServerError.new(response_body)
  end

  response_body
rescue ServerError, Errno::ECONNREFUSED, Errno::ECONNRESET, Errno::ETIMEDOUT, Errno::EPIPE, EOFError, SocketError, Net::OpenTimeout, Net::ReadTimeout, OpenSSL::SSL::SSLError => e
  logger.warn("#{action.http_method.to_s.upcase} #{endpoint_url}")
  logger.warn('Request failed due to:')
  logger.warn(e.inspect)
  retries += 1
  if retries < max_request_retries
    wait = retries * REQUEST_RETRY_TIMEBOX
    print_every = 2 # seconds
    (wait / print_every).ceil.times do |i|
      if i == 0
        logger.warn("Wait for #{wait}s before retrying the request to Knapsack Pro API.")
      else
        logger.warn("#{wait - i * print_every}s left before retry...")
      end
      Kernel.sleep(print_every)
    end
    retry
  else
    response_body
  end
end
max_request_retries() click to toggle source
# File lib/knapsack_pro/client/connection.rb, line 176
def max_request_retries
  # when user defined max request retries
  return KnapsackPro::Config::Env.max_request_retries if KnapsackPro::Config::Env.max_request_retries

  # when Fallback Mode is disabled then try more attempts to connect to the API
  return 6 unless KnapsackPro::Config::Env.fallback_mode_enabled?

  # when Regular Mode then try more attempts to connect to the API
  # if only one CI node starts Fallback Mode instead of all then we can't guarantee all test files will be run
  # https://github.com/KnapsackPro/knapsack_pro-ruby/pull/124
  return 6 if KnapsackPro::Config::Env.regular_mode?

  # default number of attempts
  3
end
net_http() click to toggle source
# File lib/knapsack_pro/client/connection.rb, line 151
def net_http
  if defined?(WebMock::HttpLibAdapters::NetHttpAdapter::OriginalNetHTTP)
    WebMock::HttpLibAdapters::NetHttpAdapter::OriginalNetHTTP
  else
    Net::HTTP
  end
end
parse_response_body(body) click to toggle source
# File lib/knapsack_pro/client/connection.rb, line 82
def parse_response_body(body)
  return '' if body == '' || body.nil?
  JSON.parse(body)
rescue JSON::ParserError
  nil
end
post() click to toggle source
# File lib/knapsack_pro/client/connection.rb, line 159
def post
  uri = URI.parse(endpoint_url)
  http = build_http(uri)
  make_request do
    http.post(uri.path, request_body, json_headers)
  end
end
request_body() click to toggle source
# File lib/knapsack_pro/client/connection.rb, line 60
def request_body
  request_hash.to_json
end
request_hash() click to toggle source
# File lib/knapsack_pro/client/connection.rb, line 56
def request_hash
  action.request_hash
end
seed() click to toggle source
# File lib/knapsack_pro/client/connection.rb, line 89
def seed
  return if @response_body.nil? || @response_body == ''
  response_body['build_distribution_id']
end