Class: Riveter::Client

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

Overview

Client for the Riveter API. https://docs.riveterhq.com

Constant Summary collapse

DEFAULT_BASE_URL =
"https://api.riveterhq.com/v1"

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(api_key: nil, base_url: nil, timeout: 60, max_retries: 2) ⇒ Client

api_key falls back to ENV; base_url falls back to ENV, then production. timeout (seconds) must exceed the 50s wait long-poll. max_retries covers 429s (any method) and 5xx/network failures (GETs only).



21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
# File 'lib/riveter/client.rb', line 21

def initialize(api_key: nil, base_url: nil, timeout: 60, max_retries: 2)
  @api_key = api_key || ENV.fetch("RIVETER_API_KEY", nil)
  if @api_key.nil? || @api_key.empty?
    raise Error, "Missing API key: pass api_key: or set RIVETER_API_KEY " \
                 "(get one at https://app.riveterhq.com/settings/api)"
  end

  @base_url = (base_url || ENV.fetch("RIVETER_BASE_URL", nil) || DEFAULT_BASE_URL).sub(%r{/+\z}, "")
  @timeout = timeout
  @max_retries = max_retries
  @runs = Resources::Runs.new(self)
  @enrichments = Resources::Enrichments.new(self)
  @datasets = Resources::Datasets.new(self)
  @configured_datasets = Resources::ConfiguredDatasets.new(self)
  @extractions = Resources::Extractions.new(self)
  @monitors = Resources::Monitors.new(self)
end

Instance Attribute Details

#base_urlObject (readonly)

Returns the value of attribute base_url.



13
14
15
# File 'lib/riveter/client.rb', line 13

def base_url
  @base_url
end

#configured_datasetsObject (readonly)

Returns the value of attribute configured_datasets.



13
14
15
# File 'lib/riveter/client.rb', line 13

def configured_datasets
  @configured_datasets
end

#datasetsObject (readonly)

Returns the value of attribute datasets.



13
14
15
# File 'lib/riveter/client.rb', line 13

def datasets
  @datasets
end

#enrichmentsObject (readonly)

Returns the value of attribute enrichments.



13
14
15
# File 'lib/riveter/client.rb', line 13

def enrichments
  @enrichments
end

#extractionsObject (readonly)

Returns the value of attribute extractions.



13
14
15
# File 'lib/riveter/client.rb', line 13

def extractions
  @extractions
end

#max_retriesObject (readonly)

Returns the value of attribute max_retries.



13
14
15
# File 'lib/riveter/client.rb', line 13

def max_retries
  @max_retries
end

#monitorsObject (readonly)

Returns the value of attribute monitors.



13
14
15
# File 'lib/riveter/client.rb', line 13

def monitors
  @monitors
end

#runsObject (readonly)

Returns the value of attribute runs.



13
14
15
# File 'lib/riveter/client.rb', line 13

def runs
  @runs
end

#timeoutObject (readonly)

Returns the value of attribute timeout.



13
14
15
# File 'lib/riveter/client.rb', line 13

def timeout
  @timeout
end

Instance Method Details

#accountObject

Account, plan, and credit info for the API key. (operationId: getAccount)



55
56
57
# File 'lib/riveter/client.rb', line 55

def 
  AccountInfo.new(request(:get, "/account"))
end

#enrich(**params) ⇒ Object

Start an enrichment run on rows of input data. (operationId: enrich)



40
41
42
# File 'lib/riveter/client.rb', line 40

def enrich(**params)
  Run.new(request(:post, "/enrich", body: params))
end

#quick_search(**params) ⇒ Object

Run one web search synchronously; results are already in #output. (operationId: quickSearch)



45
46
47
# File 'lib/riveter/client.rb', line 45

def quick_search(**params)
  Run.new(request(:post, "/quick_search", body: params))
end

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



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
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
# File 'lib/riveter/client.rb', line 59

def request(method, path, query: nil, body: nil, timeout: nil)
  uri = URI.parse(@base_url + path)
  if query
    compact = query.reject { |_key, value| value.nil? }
    uri.query = URI.encode_www_form(compact) unless compact.empty?
  end

  retry_on_failure = method == :get
  attempt = 0
  loop do
    response = begin
      perform_http_request(method, uri, body, timeout || @timeout)
    rescue Net::OpenTimeout, Net::ReadTimeout => e
      if retry_on_failure && attempt < @max_retries
        sleep(backoff_seconds(attempt))
        attempt += 1
        next
      end
      raise APITimeoutError, "Request timed out: #{method.to_s.upcase} #{path} (#{e.class})"
    rescue SystemCallError, SocketError, IOError, OpenSSL::SSL::SSLError => e
      if retry_on_failure && attempt < @max_retries
        sleep(backoff_seconds(attempt))
        attempt += 1
        next
      end
      raise APIConnectionError, "Request failed: #{method.to_s.upcase} #{path}: #{e.message}"
    end

    status = response.code.to_i
    return parse_json_body(response) if status.between?(200, 299)

    if status == 429 && attempt < @max_retries
      sleep(rate_limit_delay_seconds(response, attempt))
      attempt += 1
      next
    end
    if status >= 500 && retry_on_failure && attempt < @max_retries
      sleep(backoff_seconds(attempt))
      attempt += 1
      next
    end

    raise APIError.from_response(status, parse_json_body(response))
  end
end

#scrape(**params) ⇒ Object

Scrape a webpage and return its text synchronously. (operationId: scrape)



50
51
52
# File 'lib/riveter/client.rb', line 50

def scrape(**params)
  ScrapeResult.new(request(:post, "/scrape", body: params))
end