Class: Typesense::ApiCall

Inherits:
Object
  • Object
show all
Defined in:
lib/typesense/api_call.rb

Constant Summary collapse

API_KEY_HEADER_NAME =
'X-TYPESENSE-API-KEY'

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(configuration) ⇒ ApiCall

Returns a new instance of ApiCall.



12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# File 'lib/typesense/api_call.rb', line 12

def initialize(configuration)
  @configuration = configuration

  @api_key = @configuration.api_key
  @nodes = @configuration.nodes.dup # Make a copy, since we'll be adding additional metadata to the nodes
  @nearest_node = @configuration.nearest_node.dup
  @connection_timeout_seconds = @configuration.connection_timeout_seconds
  @healthcheck_interval_seconds = @configuration.healthcheck_interval_seconds
  @num_retries_per_request = @configuration.num_retries
  @retry_interval_seconds = @configuration.retry_interval_seconds

  @logger = @configuration.logger

  
  @current_node_index = -1
end

Instance Attribute Details

#loggerObject (readonly)

Returns the value of attribute logger.



10
11
12
# File 'lib/typesense/api_call.rb', line 10

def logger
  @logger
end

Instance Method Details

#delete(endpoint, query_parameters = {}) ⇒ Object



56
57
58
59
60
# File 'lib/typesense/api_call.rb', line 56

def delete(endpoint, query_parameters = {})
  perform_request :delete,
                  endpoint,
                  query_parameters: query_parameters
end

#get(endpoint, query_parameters = {}) ⇒ Object



50
51
52
53
54
# File 'lib/typesense/api_call.rb', line 50

def get(endpoint, query_parameters = {})
  perform_request :get,
                  endpoint,
                  query_parameters: query_parameters
end

#patch(endpoint, body_parameters = {}, query_parameters = {}) ⇒ Object



36
37
38
39
40
41
# File 'lib/typesense/api_call.rb', line 36

def patch(endpoint, body_parameters = {}, query_parameters = {})
  perform_request :patch,
                  endpoint,
                  query_parameters: query_parameters,
                  body_parameters: body_parameters
end

#perform_request(method, endpoint, query_parameters: nil, body_parameters: nil, additional_headers: {}) ⇒ Object



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
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
# File 'lib/typesense/api_call.rb', line 62

def perform_request(method, endpoint, query_parameters: nil, body_parameters: nil, additional_headers: {})
  @configuration.validate!
  last_exception = nil
  @logger.debug "Performing #{method.to_s.upcase} request: #{endpoint}"
  (1..(@num_retries_per_request + 1)).each do |num_tries|
    node = next_node

    @logger.debug "Attempting #{method.to_s.upcase} request Try ##{num_tries} to Node #{node[:index]}"

    begin
      conn = Faraday.new(uri_for(endpoint, node)) do |f|
        f.options.timeout = @connection_timeout_seconds
        f.options.open_timeout = @connection_timeout_seconds
      end

      headers = default_headers.merge(additional_headers)

      response = conn.send(method) do |req|
        req.headers = headers
        req.params = query_parameters unless query_parameters.nil?
        unless body_parameters.nil?
          body = body_parameters
          body = JSON.dump(body_parameters) if headers['Content-Type'] == 'application/json'
          req.body = body
        end
      end
      set_node_healthcheck(node, is_healthy: true) if response.status.between?(1, 499)

      @logger.debug "Request #{method}:#{uri_for(endpoint, node)} to Node #{node[:index]} was successfully made (at the network layer). response.status was #{response.status}."

      parsed_response = if response.headers && (response.headers['content-type'] || '').include?('application/json')
                          JSON.parse(response.body)
                        else
                          response.body
                        end

      # If response is 2xx return the object, else raise the response as an exception
      return parsed_response if response.status.between?(200, 299)

      exception_message = (parsed_response && parsed_response['message']) || 'Error'
      raise custom_exception_klass_for(response), exception_message
    rescue Faraday::ConnectionFailed, Faraday::TimeoutError,
           Errno::EINVAL, Errno::ENETDOWN, Errno::ENETUNREACH, Errno::ENETRESET,
           Errno::ECONNABORTED, Errno::ECONNRESET, Errno::ETIMEDOUT,
           Errno::ECONNREFUSED, Errno::EHOSTDOWN, Errno::EHOSTUNREACH,
           Typesense::Error::ServerError, Typesense::Error::HTTPStatus0Error => e
      # Rescue network layer exceptions and HTTP 5xx errors, so the loop can continue.
      # Using loops for retries instead of rescue...retry to maintain consistency with client libraries in
      #   other languages that might not support the same construct.
      set_node_healthcheck(node, is_healthy: false)
      last_exception = e
      @logger.warn "Request #{method}:#{uri_for(endpoint, node)} to Node #{node[:index]} failed due to \"#{e.class}: #{e.message}\""
      @logger.warn "Sleeping for #{@retry_interval_seconds}s and then retrying request..."
      sleep @retry_interval_seconds if num_tries <= @num_retries_per_request
    end
  end
  @logger.debug "No retries left. Raising last error \"#{last_exception.class}: #{last_exception.message}\"..."
  raise last_exception
end

#post(endpoint, body_parameters = {}, query_parameters = {}) ⇒ Object



29
30
31
32
33
34
# File 'lib/typesense/api_call.rb', line 29

def post(endpoint, body_parameters = {}, query_parameters = {})
  perform_request :post,
                  endpoint,
                  query_parameters: query_parameters,
                  body_parameters: body_parameters
end

#put(endpoint, body_parameters = {}, query_parameters = {}) ⇒ Object



43
44
45
46
47
48
# File 'lib/typesense/api_call.rb', line 43

def put(endpoint, body_parameters = {}, query_parameters = {})
  perform_request :put,
                  endpoint,
                  query_parameters: query_parameters,
                  body_parameters: body_parameters
end