Class: Parse::Request

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

Overview

This class represents a Parse request.

Class Attribute Summary collapse

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(method, uri, body: nil, headers: nil, opts: {}) ⇒ Request

Creates a new request

Parameters:

  • method (String)

    the HTTP method

  • uri (String)

    the API path of the request (without the host)

  • body (Hash) (defaults to: nil)

    the body (or parameters) of this request.

  • headers (Hash) (defaults to: nil)

    additional headers to send in this request.

  • opts (Hash) (defaults to: {})

    additional optional parameters.

Options Hash (opts:):

  • :request_id (String)

    custom request ID for idempotency

  • :idempotent (Boolean)

    force enable/disable idempotency for this request



90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
# File 'lib/parse/client/request.rb', line 90

def initialize(method, uri, body: nil, headers: nil, opts: {})
  @tag = 0
  method = method.downcase.to_sym
  unless method == :get || method == :put || method == :post || method == :delete
    raise ArgumentError, "Invalid method #{method} for request : '#{uri}'"
  end

  self.method = method
  self.path = uri
  self.body = body
  self.headers = headers || {}
  self.opts = opts || {}

  # Handle request ID for idempotency
  setup_request_id
end

Class Attribute Details

.assume_server_idempotencyBoolean

Returns operator assertion that the Parse Server is configured with idempotencyOptions covering the write paths the SDK targets. When true, a request that carries a stable X-Parse-Request-Id header becomes safe for Client to transparently RETRY on an ambiguous failure (500/503/dropped connection) even when it is a POST or an atomic-op write — Parse Server deduplicates the replay server-side, so the write applies AT MOST ONCE.

The replay does NOT transparently return the original response, though: Parse Server rejects the duplicate with error 159, which the SDK raises as Error::DuplicateRequestError. A caller relying on this retry must rescue that error (the original write already landed) and re-fetch by its own key if it needs the result.

Default false. Sending the X-Parse-Request-Id header is harmless on its own, but ASSUMING the server deduplicates when it does not would double-apply the write on retry. Only set this true when Parse Server's idempotencyOptions is actually configured to cover those paths (it is OFF by default on Parse Server).

Returns:

  • (Boolean)

    operator assertion that the Parse Server is configured with idempotencyOptions covering the write paths the SDK targets. When true, a request that carries a stable X-Parse-Request-Id header becomes safe for Client to transparently RETRY on an ambiguous failure (500/503/dropped connection) even when it is a POST or an atomic-op write — Parse Server deduplicates the replay server-side, so the write applies AT MOST ONCE.

    The replay does NOT transparently return the original response, though: Parse Server rejects the duplicate with error 159, which the SDK raises as Error::DuplicateRequestError. A caller relying on this retry must rescue that error (the original write already landed) and re-fetch by its own key if it needs the result.

    Default false. Sending the X-Parse-Request-Id header is harmless on its own, but ASSUMING the server deduplicates when it does not would double-apply the write on retry. Only set this true when Parse Server's idempotencyOptions is actually configured to cover those paths (it is OFF by default on Parse Server).



71
72
73
# File 'lib/parse/client/request.rb', line 71

def assume_server_idempotency
  @assume_server_idempotency
end

.enable_request_idBoolean

Returns whether to automatically generate request IDs for idempotency.

Returns:

  • (Boolean)

    whether to automatically generate request IDs for idempotency



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

def enable_request_id
  @enable_request_id
end

.idempotent_methodsArray<Symbol>

Returns HTTP methods that should include request IDs.

Returns:

  • (Array<Symbol>)

    HTTP methods that should include request IDs



48
49
50
# File 'lib/parse/client/request.rb', line 48

def idempotent_methods
  @idempotent_methods
end

.request_id_headerString

Returns the header name to use for request IDs.

Returns:

  • (String)

    the header name to use for request IDs



44
45
46
# File 'lib/parse/client/request.rb', line 44

def request_id_header
  @request_id_header
end

Instance Attribute Details

#bodyObject

Returns the value of attribute body.



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

#cacheBoolean

Returns:

  • (Boolean)


26
# File 'lib/parse/client/request.rb', line 26

attr_accessor :method, :path, :body, :headers, :opts, :cache

#headersObject

Returns the value of attribute headers.



26
27
28
# File 'lib/parse/client/request.rb', line 26

def headers
  @headers
end

#methodObject

Returns the value of attribute method.



# File 'lib/parse/client/request.rb', line 11

#optsHash

Returns a set of options for this request.

Returns:

  • (Hash)

    a set of options for this request.



26
# File 'lib/parse/client/request.rb', line 26

attr_accessor :method, :path, :body, :headers, :opts, :cache

#pathObject

Returns the value of attribute path.



# File 'lib/parse/client/request.rb', line 14

#request_idString

Returns unique identifier for this request to enable idempotency.

Returns:

  • (String)

    unique identifier for this request to enable idempotency



34
35
36
# File 'lib/parse/client/request.rb', line 34

def request_id
  @request_id
end

Class Method Details

.configure_idempotency(enabled: true, methods: [:post, :put, :patch], header: "X-Parse-Request-Id", assume_server_dedup: false) ⇒ Object

Configures idempotency settings

Parameters:

  • enabled (Boolean) (defaults to: true)

    whether to enable idempotency

  • methods (Array<Symbol>) (defaults to: [:post, :put, :patch])

    HTTP methods to apply idempotency to

  • header (String) (defaults to: "X-Parse-Request-Id")

    header name to use for request IDs

  • assume_server_dedup (Boolean) (defaults to: false)

    sets assume_server_idempotency (default false). Pass true ONLY when Parse Server idempotencyOptions is configured for the targeted paths.



277
278
279
280
281
282
# File 'lib/parse/client/request.rb', line 277

def self.configure_idempotency(enabled: true, methods: [:post, :put, :patch], header: "X-Parse-Request-Id", assume_server_dedup: false)
  self.enable_request_id = enabled
  self.idempotent_methods = methods
  self.request_id_header = header
  self.assume_server_idempotency = assume_server_dedup
end

.disable_idempotency!Object

Disables request ID generation globally. Also clears assume_server_idempotency so writes are never treated as retry-safe once the header is no longer sent.



265
266
267
268
# File 'lib/parse/client/request.rb', line 265

def self.disable_idempotency!
  self.enable_request_id = false
  self.assume_server_idempotency = false
end

.enable_idempotency!(methods: [:post, :put, :patch], header: "X-Parse-Request-Id", assume_server_dedup: nil) ⇒ Object

Enables request ID generation globally

Parameters:

  • methods (Array<Symbol>) (defaults to: [:post, :put, :patch])

    HTTP methods to apply idempotency to

  • header (String) (defaults to: "X-Parse-Request-Id")

    header name to use for request IDs

  • assume_server_dedup (Boolean, nil) (defaults to: nil)

    when non-nil, also sets assume_server_idempotency — pass true ONLY when Parse Server's idempotencyOptions is configured, to additionally make writes retry-safe. Leave nil (default) to send the header without changing the retry posture.



255
256
257
258
259
260
# File 'lib/parse/client/request.rb', line 255

def self.enable_idempotency!(methods: [:post, :put, :patch], header: "X-Parse-Request-Id", assume_server_dedup: nil)
  self.enable_request_id = true
  self.idempotent_methods = methods
  self.request_id_header = header
  self.assume_server_idempotency = assume_server_dedup unless assume_server_dedup.nil?
end

Instance Method Details

#==(r) ⇒ Boolean

Returns:

  • (Boolean)


119
120
121
122
# File 'lib/parse/client/request.rb', line 119

def ==(r)
  return false unless r.is_a?(Request)
  @method == r.method && @path == r.path && @body == r.body && @headers == r.headers
end

#as_jsonHash

Returns JSON encoded hash.

Returns:

  • (Hash)

    JSON encoded hash



114
115
116
# File 'lib/parse/client/request.rb', line 114

def as_json
  signature.as_json
end

#idempotent?Boolean

Checks if this request has idempotency enabled

Returns:

  • (Boolean)


241
242
243
# File 'lib/parse/client/request.rb', line 241

def idempotent?
  @request_id.present? && @headers[self.class.request_id_header].present?
end

#queryHash

The parameters of this request if the HTTP method is GET.

Returns:



109
110
111
# File 'lib/parse/client/request.rb', line 109

def query
  body if @method == :get
end

#signatureHash

Signature provies a way for us to compare different requests objects. Two requests objects are the same if they have the same signature.

Returns:

  • (Hash)

    A hash representing this request.



127
128
129
# File 'lib/parse/client/request.rb', line 127

def signature
  { method: @method.upcase, path: @path, body: @body }
end

#to_sString

Returns:



137
138
139
# File 'lib/parse/client/request.rb', line 137

def to_s
  "#{@method.to_s.upcase} #{@path}"
end

#with_idempotency(custom_id = nil) ⇒ self

Enables idempotency for this specific request

Parameters:

  • custom_id (String) (defaults to: nil)

    optional custom request ID to use

Returns:

  • (self)

    for method chaining



223
224
225
226
227
228
# File 'lib/parse/client/request.rb', line 223

def with_idempotency(custom_id = nil)
  @opts[:idempotent] = true
  @opts[:request_id] = custom_id if custom_id
  setup_request_id
  self
end

#without_idempotencyself

Disables idempotency for this specific request

Returns:

  • (self)

    for method chaining



232
233
234
235
236
237
# File 'lib/parse/client/request.rb', line 232

def without_idempotency
  @opts[:idempotent] = false
  @request_id = nil
  @headers.delete(self.class.request_id_header)
  self
end