Class: ActiveSupport::Cache::MemCacheStore

Inherits:
Store show all
Includes:
DupLocalCache, Strategy::LocalCache
Defined in:
lib/active_support/cache/mem_cache_store.rb

Overview

Memcached Cache Store

A cache store implementation which stores data in Memcached: memcached.org

This is currently the most popular cache store for production websites.

Special features:

  • Clustering and load balancing. One can specify multiple memcached servers, and MemCacheStore will load balance between all available servers. If a server goes down, then MemCacheStore will ignore it until it comes back up.

MemCacheStore implements the Strategy::LocalCache strategy which implements an in-memory cache inside of a block.

Defined Under Namespace

Modules: DupLocalCache

Constant Summary collapse

OVERRIDDEN_OPTIONS =

These options represent behavior overridden by this implementation and should not be allowed to get down to the Dalli client

UNIVERSAL_OPTIONS
KEY_MAX_SIZE =
250
ESCAPE_KEY_CHARS =
/[\x00-\x20%\x7F-\xFF]/n

Instance Attribute Summary

Attributes inherited from Store

#options, #silence

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Strategy::LocalCache

#cleanup, #delete_matched, #middleware, #with_local_cache

Methods inherited from Store

#cleanup, #delete, #delete_matched, #delete_multi, #exist?, #fetch, #fetch_multi, #mute, #new_entry, #read, #read_multi, #silence!, #write, #write_multi

Constructor Details

#initialize(*addresses) ⇒ MemCacheStore

Creates a new MemCacheStore object, with the given memcached server addresses. Each address is either a host name, or a host-with-port string in the form of “host_name:port”. For example:

ActiveSupport::Cache::MemCacheStore.new("localhost", "server-downstairs.localnetwork:8229")

If no addresses are provided, but ENV['MEMCACHE_SERVERS'] is defined, it will be used instead. Otherwise, MemCacheStore will connect to localhost:11211 (the default memcached port). Passing a Dalli::Client instance is deprecated and will be removed. Please pass an address instead.



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
# File 'lib/active_support/cache/mem_cache_store.rb', line 118

def initialize(*addresses)
  addresses = addresses.flatten
  options = addresses.extract_options!
  if options.key?(:cache_nils)
    options[:skip_nil] = !options.delete(:cache_nils)
  end
  super(options)

  unless [String, Dalli::Client, NilClass].include?(addresses.first.class)
    raise ArgumentError, "First argument must be an empty array, address, or array of addresses."
  end
  if addresses.first.is_a?(Dalli::Client)
    ActiveSupport.deprecator.warn(<<~MSG)
      Initializing MemCacheStore with a Dalli::Client is deprecated and will be removed in Rails 7.2.
      Use memcached server addresses instead.
    MSG
    @data = addresses.first
  else
    @mem_cache_options = options.dup
    # The value "compress: false" prevents duplicate compression within Dalli.
    @mem_cache_options[:compress] = false
    (OVERRIDDEN_OPTIONS - %i(compress)).each { |name| @mem_cache_options.delete(name) }
    @data = self.class.build_mem_cache(*(addresses + [@mem_cache_options]))
  end
end

Class Method Details

.build_mem_cache(*addresses) ⇒ Object

Creates a new Dalli::Client instance with specified addresses and options. If no addresses are provided, we give nil to Dalli::Client, so it uses its fallbacks:

  • ENV (if defined)

  • “127.0.0.1:11211” (otherwise)

    ActiveSupport::Cache::MemCacheStore.build_mem_cache

    # => #<Dalli::Client:0x007f98a47d2028 @servers=["127.0.0.1:11211"], @options={}, @ring=nil>
    

    ActiveSupport::Cache::MemCacheStore.build_mem_cache(‘localhost:10290’)

    # => #<Dalli::Client:0x007f98a47b3a60 @servers=["localhost:10290"], @options={}, @ring=nil>
    


96
97
98
99
100
101
102
103
104
105
106
107
# File 'lib/active_support/cache/mem_cache_store.rb', line 96

def self.build_mem_cache(*addresses) # :nodoc:
  addresses = addresses.flatten
  options = addresses.extract_options!
  addresses = nil if addresses.compact.empty?
  pool_options = retrieve_pool_options(options)

  if pool_options
    ConnectionPool.new(pool_options) { Dalli::Client.new(addresses, options.merge(threadsafe: false)) }
  else
    Dalli::Client.new(addresses, options)
  end
end

.supports_cache_versioning?Boolean

Advertise cache versioning support.

Returns:

  • (Boolean)


38
39
40
# File 'lib/active_support/cache/mem_cache_store.rb', line 38

def self.supports_cache_versioning?
  true
end

Instance Method Details

#clear(options = nil) ⇒ Object

Clear the entire cache on all memcached servers. This method should be used with care when shared cache is being used.



215
216
217
# File 'lib/active_support/cache/mem_cache_store.rb', line 215

def clear(options = nil)
  rescue_error_with(nil) { @data.with { |c| c.flush_all } }
end

#decrement(name, amount = 1, options = nil) ⇒ Object

Decrement a cached integer value using the memcached decr atomic operator. Returns the updated value.

If the key is unset or has expired, it will be set to 0. Memcached does not support negative counters.

cache.decrement("foo") # => 0

To set a specific value, call #write passing raw: true:

cache.write("baz", 5, raw: true)
cache.decrement("baz") # => 4

Decrementing a non-numeric value, or a value written without raw: true, will fail and return nil.



204
205
206
207
208
209
210
211
# File 'lib/active_support/cache/mem_cache_store.rb', line 204

def decrement(name, amount = 1, options = nil)
  options = merged_options(options)
  instrument(:decrement, name, amount: amount) do
    rescue_error_with nil do
      @data.with { |c| c.decr(normalize_key(name, options), amount, options[:expires_in], 0) }
    end
  end
end

#increment(name, amount = 1, options = nil) ⇒ Object

Increment a cached integer value using the memcached incr atomic operator. Returns the updated value.

If the key is unset or has expired, it will be set to amount:

cache.increment("foo") # => 1
cache.increment("bar", 100) # => 100

To set a specific value, call #write passing raw: true:

cache.write("baz", 5, raw: true)
cache.increment("baz") # => 6

Incrementing a non-numeric value, or a value written without raw: true, will fail and return nil.



180
181
182
183
184
185
186
187
# File 'lib/active_support/cache/mem_cache_store.rb', line 180

def increment(name, amount = 1, options = nil)
  options = merged_options(options)
  instrument(:increment, name, amount: amount) do
    rescue_error_with nil do
      @data.with { |c| c.incr(normalize_key(name, options), amount, options[:expires_in], amount) }
    end
  end
end

#inspectObject



144
145
146
147
# File 'lib/active_support/cache/mem_cache_store.rb', line 144

def inspect
  instance = @data || @mem_cache_options
  "#<#{self.class} options=#{options.inspect} mem_cache=#{instance.inspect}>"
end

#statsObject

Get the statistics from the memcached servers.



220
221
222
# File 'lib/active_support/cache/mem_cache_store.rb', line 220

def stats
  @data.with { |c| c.stats }
end