Module: Operto::Client

Extended by:
Client
Included in:
Client
Defined in:
lib/operto/client.rb

Overview

The single HTTP gateway: Faraday connection, auth header, retry, and Operto's quirky response envelope (a 200 with ReasonCode >= 300 is a failure).

Constant Summary collapse

RETRY_OPTIONS =
{
  max: 3,
  interval: 1.0,
  interval_randomness: 0.5,
  backoff_factor: 2,
  retry_statuses: [401, 429, 502, 503, 504],
  exceptions: [*Faraday::Retry::Middleware::DEFAULT_EXCEPTIONS, Faraday::ConnectionFailed],
  methods: [*Faraday::Retry::Middleware::IDEMPOTENT_METHODS, :patch, :post],
  retry_block: ->(env:, **) { Operto.config.token_store.clear if env.status == 401 }
}.freeze

Instance Method Summary collapse

Instance Method Details

#auth_tokenObject



69
70
71
# File 'lib/operto/client.rb', line 69

def auth_token
  AccessTokens::Upsert.new.call!.value!.access_token
end

#client_idObject



73
74
75
# File 'lib/operto/client.rb', line 73

def client_id
  Operto.config.client_id
end

#connection(url: Operto.config.base_url, skip_auth: false) ⇒ Object



19
20
21
22
23
24
25
26
27
28
29
# File 'lib/operto/client.rb', line 19

def connection(url: Operto.config.base_url, skip_auth: false)
  Faraday.new(url:) do |builder|
    builder.request :authorization, 'VRS', -> { auth_token } unless skip_auth

    builder.request :json
    builder.request :retry, RETRY_OPTIONS
    builder.request :url_encoded
    builder.response :json, parser_options: { symbolize_names: true, mode: :rails, decoder: [Oj, :load] }
    builder.options[:timeout] = 20
  end
end

#formatted_error(response) ⇒ Object



44
45
46
47
48
49
50
# File 'lib/operto/client.rb', line 44

def formatted_error(response)
  body = response_body(response)
  reason_code = body[:ReasonCode] || response.status
  reason_text = body[:ReasonText] || body[:Message] || response.body.to_s

  Operto::Error.new("#{reason_code}: #{reason_text}")
end

#handle_response(response, &block) ⇒ Object



31
32
33
34
35
# File 'lib/operto/client.rb', line 31

def handle_response(response, &block)
  return Failure(formatted_error(response)) unless successful_response?(response)

  Success(block ? block.call(response_body(response)) : true)
end

#parsed_body_from_string(body) ⇒ Object



59
60
61
62
63
64
65
66
67
# File 'lib/operto/client.rb', line 59

def parsed_body_from_string(body)
  string_body = body.to_s
  return {} if string_body.empty?

  parsed = Oj.load(string_body, symbol_keys: true)
  parsed.is_a?(Hash) ? parsed : {}
rescue StandardError
  {}
end

#response_body(response) ⇒ Object



52
53
54
55
56
57
# File 'lib/operto/client.rb', line 52

def response_body(response)
  body = response.body
  return body if body.is_a?(Hash)

  parsed_body_from_string(body)
end

#secretObject



77
78
79
# File 'lib/operto/client.rb', line 77

def secret
  Operto.config.secret
end

#successful_response?(response) ⇒ Boolean

Returns:

  • (Boolean)


37
38
39
40
41
42
# File 'lib/operto/client.rb', line 37

def successful_response?(response)
  body = response_body(response)
  reason_code = body[:ReasonCode]

  response.success? && (reason_code.nil? || reason_code.to_i < 300)
end