Class: Parse::Client

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

Overview

A class which encapsulates the HTTPS communication with the Parse API server.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(data = {}) ⇒ Client

Returns a new instance of Client.



24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
# File 'lib/parse/client.rb', line 24

def initialize(data = {})
  @host           = data[:host] || Protocol::HOST
  @application_id = data[:application_id]
  @api_key        = data[:api_key]
  @master_key     = data[:master_key]
  @session_token  = data[:session_token]
  @max_retries    = data[:max_retries] || 3
  @logger         = data[:logger] || Logger.new(STDERR).tap{|l| l.level = Logger::INFO}
  @session        = data[:http_client] || Parse::DEFAULT_HTTP_CLIENT.new

  if data[:ironio_project_id] && data[:ironio_token]

    if data[:max_concurrent_requests]
      @max_concurrent_requests = data[:max_concurrent_requests]
    else
      @max_concurrent_requests = 50
    end

    @queue = IronMQ::Client.new({
      :project_id => data[:ironio_project_id],
      :token => data[:ironio_token]
    }).queue("concurrent_parse_requests")

  end

  @session.base_url                 = "https://#{host}"
  @session.headers["Content-Type"]  = "application/json"
  @session.headers["Accept"]        = "application/json"
  @session.headers["User-Agent"]    = "Parse for Ruby, 0.0"
end

Instance Attribute Details

#api_keyObject

Returns the value of attribute api_key.



17
18
19
# File 'lib/parse/client.rb', line 17

def api_key
  @api_key
end

#application_idObject

Returns the value of attribute application_id.



16
17
18
# File 'lib/parse/client.rb', line 16

def application_id
  @application_id
end

#hostObject

Returns the value of attribute host.



15
16
17
# File 'lib/parse/client.rb', line 15

def host
  @host
end

#loggerObject

Returns the value of attribute logger.



22
23
24
# File 'lib/parse/client.rb', line 22

def logger
  @logger
end

#master_keyObject

Returns the value of attribute master_key.



18
19
20
# File 'lib/parse/client.rb', line 18

def master_key
  @master_key
end

#max_retriesObject

Returns the value of attribute max_retries.



21
22
23
# File 'lib/parse/client.rb', line 21

def max_retries
  @max_retries
end

#sessionObject

Returns the value of attribute session.



20
21
22
# File 'lib/parse/client.rb', line 20

def session
  @session
end

#session_tokenObject

Returns the value of attribute session_token.



19
20
21
# File 'lib/parse/client.rb', line 19

def session_token
  @session_token
end

Instance Method Details

#delete(uri) ⇒ Object



163
164
165
# File 'lib/parse/client.rb', line 163

def delete(uri)
  request(uri, :delete)
end

#get(uri) ⇒ Object



151
152
153
# File 'lib/parse/client.rb', line 151

def get(uri)
  request(uri)
end

#post(uri, body) ⇒ Object



155
156
157
# File 'lib/parse/client.rb', line 155

def post(uri, body)
  request(uri, :post, body)
end

#put(uri, body) ⇒ Object



159
160
161
# File 'lib/parse/client.rb', line 159

def put(uri, body)
  request(uri, :put, body)
end

#request(uri, method = :get, body = nil, query = nil, content_type = nil) ⇒ Object

Perform an HTTP request for the given uri and method with common basic response handling. Will raise a ParseProtocolError if the response has an error status code, and will return the parsed JSON body on success, if there is one.



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
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
# File 'lib/parse/client.rb', line 59

def request(uri, method = :get, body = nil, query = nil, content_type = nil)
  options = {}
  headers = {}

  headers[Protocol::HEADER_MASTER_KEY]    = @master_key if @master_key
  headers[Protocol::HEADER_API_KEY]       = @api_key
  headers[Protocol::HEADER_APP_ID]        = @application_id
  headers[Protocol::HEADER_SESSION_TOKEN] = @session_token if @session_token

  if body
    options[:data] = body
  end
  if query
    options[:query] = @session.build_query(query)

    # Avoid 502 or 414 when sending a large querystring. See https://parse.com/questions/502-error-when-query-with-huge-contains
    if options[:query].size > 2000 && method == :get && !body && !content_type
      options[:data] = options[:query]
      options[:query] = nil
      method = :post
      headers['X-HTTP-Method-Override'] = 'GET'
      content_type = 'application/x-www-form-urlencoded'
    end
  end

  if content_type
    headers["Content-Type"] = content_type
  end

  num_tries = 0
  begin
    num_tries += 1

    if @queue

      #while true
      #  if @queue.reload.size >= @max_concurrent_requests
      #    sleep 1
      #  else
          # add to queue before request
          @queue.post("1")
          response = @session.request(method, uri, headers, options)
          # delete from queue after request
          msg = @queue.get()
          msg.delete
      #  end
      #end
    else
      response = @session.request(method, uri, headers, options)
    end

    parsed = JSON.parse(response.body)

    if response.status >= 400
      parsed ||= {}
      raise ParseProtocolError.new({"error" => "HTTP Status #{response.status} Body #{response.body}"}.merge(parsed))
    end

    if content_type
      @session.headers["Content-Type"] = "application/json"
    end

    return parsed
  rescue JSON::ParserError => e
    if num_tries <= max_retries && response.status >= 500
      log_retry(e, uri, query, body, response)
      retry
    end
    raise
  rescue HttpClient::TimeoutError => e
    if num_tries <= max_retries
      log_retry(e, uri, query, body, response)
      retry
    end
    raise
  rescue ParseProtocolError => e
    if num_tries <= max_retries
      if e.code
        sleep 60 if e.code == Protocol::ERROR_EXCEEDED_BURST_LIMIT
        if [Protocol::ERROR_INTERNAL, Protocol::ERROR_TIMEOUT, Protocol::ERROR_EXCEEDED_BURST_LIMIT].include?(e.code)
          log_retry(e, uri, query, body, response)
          retry
        end
      elsif response.status >= 500
        log_retry(e, uri, query, body, response)
        retry
      end
    end
    raise
  end
end