Class: Parse::Middleware::Caching

Inherits:
Faraday::Middleware
  • Object
show all
Includes:
Protocol
Defined in:
lib/parse/client/caching.rb

Overview

This is a caching middleware for Parse queries using Moneta. The caching middleware will cache all GET requests made to the Parse REST API as long as the API responds with a successful non-empty result payload.

Whenever an object is created or updated, the corresponding entry in the cache when fetching the particular record (using the specific non-Query based API) will be cleared.

Constant Summary collapse

CACHEABLE_HTTP_CODES =

List of status codes that can be cached:

  • 200 - 'OK'
  • 203 - 'Non-Authoritative Information'
  • 300 - 'Multiple Choices'
  • 301 - 'Moved Permanently'
  • 302 - 'Found'
  • 404 - 'Not Found' - removed
  • 410 - 'Gone' - removed
[200, 203, 300, 301, 302].freeze
CACHE_CONTROL =

Cache control header

"Cache-Control"
CONTENT_LENGTH_KEY =

Request env key for the content length

"content-length"
CACHE_RESPONSE_HEADER =

Header in response that is sent if this is a cached result

"X-Cache-Response"
CACHE_EXPIRES_DURATION =

Header in request to set caching information for the middleware.

"X-Parse-Stack-Cache-Expires"
CACHE_WRITE_ONLY =

Header in request to enable write-only cache mode (skip read, still write)

"X-Parse-Stack-Cache-Write-Only"

Constants included from Protocol

Protocol::API_KEY, Protocol::APP_ID, Protocol::CLOUD_CONTEXT, Protocol::CONTENT_TYPE, Protocol::CONTENT_TYPE_FORMAT, Protocol::EMAIL, Protocol::INSTALLATION_ID, Protocol::MASTER_KEY, Protocol::PASSWORD, Protocol::READ_PREFERENCE, Protocol::READ_PREFERENCES, Protocol::REVOCABLE_SESSION, Protocol::SERVER_URL, Protocol::SESSION_TOKEN

Class Attribute Summary collapse

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(adapter, store, opts = {}) ⇒ Caching

Creates a new caching middleware.

Parameters:

  • adapter (Faraday::Adapter)

    An instance of the Faraday adapter used for the connection. Defaults Faraday::Adapter::NetHttp.

  • store (Moneta)

    An instance of the Moneta cache store to use.

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

    additional options.

Options Hash (opts):

  • :expires (Integer)

    the default expiration for a cache entry.

Raises:

  • ArgumentError, if store is not a Moneta::Transformer or Moneta::Expires instance.



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
# File 'lib/parse/client/caching.rb', line 79

def initialize(adapter, store, opts = {})
  super(adapter)
  @store = store
  @opts = { expires: 0 }
  @opts.merge!(opts) if opts.is_a?(Hash)
  @expires = @opts[:expires]
  # Optional cache key namespace so two Parse apps sharing one Redis don't
  # collide (e.g. `mk:/classes/Song/abc` is the same path for both apps).
  # When set, keys become `<namespace>:<existing-prefix>:<url>`. Empty
  # string is treated as nil. Trailing `:` is stripped once so users can
  # pass either `"app_x"` or `"app_x:"`.
  ns = @opts[:namespace].to_s
  ns = ns.chomp(":")
  @namespace = ns.empty? ? nil : ns

  # The keyspace owns physical key layout and the patterns that clear it,
  # so key generation and eviction cannot drift apart. Previously this
  # middleware composed keys from its own `@namespace` while
  # `Parse::Cache::Redis` held a separate one, and `clear_cache!` used
  # only the latter: a client namespaced here but not there would clear
  # every SDK key on the database instead of its own.
  #
  # When no keyspace is supplied the middleware keeps writing legacy
  # un-prefixed keys, so an upgrade that does not opt in behaves exactly
  # as before.
  @keyspace = @opts[:keyspace]
  # During the transition, also delete the pre-keyspace form of a key on
  # invalidation. Without this, a rolling deploy has new workers writing
  # keyspaced keys while old workers still read legacy ones, so a write
  # served by a new worker never invalidates what an old worker serves.
  @delete_legacy_variants = @opts.fetch(:delete_legacy_variants, true)

  unless [:key?, :[], :delete, :store].all? { |method| @store.respond_to?(method) }
    raise ArgumentError, "Caching store object must a Moneta key/value store."
  end
end

Class Attribute Details

.enabledBoolean

Returns whether the caching middleware should be enabled.

Returns:

  • (Boolean)

    whether the caching middleware should be enabled.



45
# File 'lib/parse/client/caching.rb', line 45

attr_writer :enabled

.loggingBoolean

Returns whether the logging should be enabled.

Returns:

  • (Boolean)

    whether the logging should be enabled.



49
50
51
# File 'lib/parse/client/caching.rb', line 49

def logging
  @logging
end

Instance Attribute Details

#expiresInteger

The expiration time in seconds for this particular request.

Returns:

  • (Integer)


70
71
72
# File 'lib/parse/client/caching.rb', line 70

def expires
  @expires
end

#storeMoneta::Transformer, Moneta::Expires

The internal moneta cache store instance.

Returns:

  • (Moneta::Transformer, Moneta::Expires)


65
66
67
# File 'lib/parse/client/caching.rb', line 65

def store
  @store
end

Class Method Details

.caching?Boolean

Returns whether caching is enabled.

Returns:

  • (Boolean)

    whether caching is enabled.



57
58
59
# File 'lib/parse/client/caching.rb', line 57

def caching?
  @enabled
end