Class: ActiveSupport::Cache::MemCacheStore

Inherits:
Store show all
Includes:
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.

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).



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

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

  @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>
    


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

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.



171
172
173
# File 'lib/active_support/cache/mem_cache_store.rb', line 171

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.



158
159
160
161
162
163
164
165
166
167
# File 'lib/active_support/cache/mem_cache_store.rb', line 158

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.



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

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



176
177
178
# File 'lib/active_support/cache/mem_cache_store.rb', line 176

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