Class: ActiveSupport::Cache::MemCacheStore

Inherits:
Store show all
Includes:
Strategy::LocalCache
Defined in:
activesupport/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.

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
ESCAPE_KEY_CHARS =
/[\x00-\x20%\x7F-\xFF]/n

Constants inherited from Store

Store::DEFAULT_POOL_OPTIONS, Store::MAX_KEY_SIZE

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, #fetch_multi, #local_cache, #middleware, #new_local_cache, #unset_local_cache, #with_local_cache

Methods inherited from Store

#cleanup, #delete, #delete_matched, #delete_multi, #exist?, #fetch, #fetch_multi, #mute, #namespace, #namespace=, #new_entry, #read, #read_counter, #read_multi, #silence!, #write, #write_counter, #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).



76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
# File 'activesupport/lib/active_support/cache/mem_cache_store.rb', line 76

def initialize(*addresses)
  addresses = addresses.flatten
  options = addresses.extract_options!
  if options.key?(:cache_nils)
    options[:skip_nil] = !options.delete(:cache_nils)
  end
  options[:max_key_size] ||= MAX_KEY_SIZE
  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

  @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

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>
    


55
56
57
58
59
60
61
62
63
64
65
66
# File 'activesupport/lib/active_support/cache/mem_cache_store.rb', line 55

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 'activesupport/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.



178
179
180
# File 'activesupport/lib/active_support/cache/mem_cache_store.rb', line 178

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.

To read the value later, call #read_counter:

cache.decrement("baz") # => 3
cache.read_counter("baz") # 3


165
166
167
168
169
170
171
172
173
174
# File 'activesupport/lib/active_support/cache/mem_cache_store.rb', line 165

def decrement(name, amount = 1, options = nil)
  options = merged_options(options)
  key = normalize_key(name, options)

  instrument(:decrement, key, amount: amount) do
    rescue_error_with nil do
      @data.with { |c| c.decr(key, 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.

To read the value later, call #read_counter:

cache.increment("baz") # => 7
cache.read_counter("baz") # 7


134
135
136
137
138
139
140
141
142
143
# File 'activesupport/lib/active_support/cache/mem_cache_store.rb', line 134

def increment(name, amount = 1, options = nil)
  options = merged_options(options)
  key = normalize_key(name, options)

  instrument(:increment, key, amount: amount) do
    rescue_error_with nil do
      @data.with { |c| c.incr(key, amount, options[:expires_in], amount) }
    end
  end
end

#inspectObject



96
97
98
99
# File 'activesupport/lib/active_support/cache/mem_cache_store.rb', line 96

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.



183
184
185
# File 'activesupport/lib/active_support/cache/mem_cache_store.rb', line 183

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