Class: ActiveSupport::Cache::MemCacheStore

Inherits:
Store show all
Defined in:
lib/active_support/cache/mem_cache_store.rb

Overview

A cache store implementation which stores data in Memcached: www.danga.com/memcached/

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 goes back online.

  • Time-based expiry support. See #write and the :expires_in option.

  • Per-request in memory cache for all communication with the MemCache server(s).

Direct Known Subclasses

CompressedMemCacheStore

Defined Under Namespace

Modules: Response

Instance Attribute Summary

Attributes inherited from Store

#logger_off, #silence

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from Store

#fetch, #mute, #silence!

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 specified, then MemCacheStore will connect to localhost port 11211 (the default memcached port).

Instead of addresses one can pass in a MemCache-like object. For example:

require 'memcached' # gem install memcached; uses C bindings to libmemcached
ActiveSupport::Cache::MemCacheStore.new(Memcached::Rails.new("localhost:11211"))


46
47
48
49
50
51
52
53
54
# File 'lib/active_support/cache/mem_cache_store.rb', line 46

def initialize(*addresses)
  if addresses.first.respond_to?(:get)
    @data = addresses.first
  else
    @data = self.class.build_mem_cache(*addresses)
  end

  extend Strategy::LocalCache
end

Class Method Details

.build_mem_cache(*addresses) ⇒ Object



26
27
28
29
30
31
# File 'lib/active_support/cache/mem_cache_store.rb', line 26

def self.build_mem_cache(*addresses)
  addresses = addresses.flatten
  options = addresses.extract_options!
  addresses = ["localhost"] if addresses.empty?
  MemCache.new(addresses, options)
end

Instance Method Details

#clearObject



129
130
131
# File 'lib/active_support/cache/mem_cache_store.rb', line 129

def clear
  @data.flush_all
end

#decrement(key, amount = 1) ⇒ Object

:nodoc:



114
115
116
117
118
119
120
# File 'lib/active_support/cache/mem_cache_store.rb', line 114

def decrement(key, amount = 1) # :nodoc:
  log("decrement", key, amount)
  response = @data.decr(key, amount)
  response == Response::NOT_FOUND ? nil : response
rescue MemCache::MemCacheError
  nil
end

#delete(key, options = nil) ⇒ Object

:nodoc:



89
90
91
92
93
94
95
96
# File 'lib/active_support/cache/mem_cache_store.rb', line 89

def delete(key, options = nil) # :nodoc:
  super
  response = @data.delete(key, expires_in(options))
  response == Response::DELETED
rescue MemCache::MemCacheError => e
  logger.error("MemCacheError (#{e}): #{e.message}")
  false
end

#delete_matched(matcher, options = nil) ⇒ Object

:nodoc:



122
123
124
125
126
127
# File 'lib/active_support/cache/mem_cache_store.rb', line 122

def delete_matched(matcher, options = nil) # :nodoc:
  # don't do any local caching at present, just pass
  # through and let the error happen
  super
  raise "Not supported by Memcache"
end

#exist?(key, options = nil) ⇒ Boolean

:nodoc:

Returns:

  • (Boolean)


98
99
100
101
102
103
# File 'lib/active_support/cache/mem_cache_store.rb', line 98

def exist?(key, options = nil) # :nodoc:
  # Doesn't call super, cause exist? in memcache is in fact a read
  # But who cares? Reading is very fast anyway
  # Local cache is checked first, if it doesn't know then memcache itself is read from
  !read(key, options).nil?
end

#increment(key, amount = 1) ⇒ Object

:nodoc:



105
106
107
108
109
110
111
112
# File 'lib/active_support/cache/mem_cache_store.rb', line 105

def increment(key, amount = 1) # :nodoc:
  log("incrementing", key, amount)

  response = @data.incr(key, amount)
  response == Response::NOT_FOUND ? nil : response
rescue MemCache::MemCacheError
  nil
end

#read(key, options = nil) ⇒ Object

:nodoc:



61
62
63
64
65
66
67
# File 'lib/active_support/cache/mem_cache_store.rb', line 61

def read(key, options = nil) # :nodoc:
  super
  @data.get(key, raw?(options))
rescue MemCache::MemCacheError => e
  logger.error("MemCacheError (#{e}): #{e.message}")
  nil
end

#read_multi(*keys) ⇒ Object

Reads multiple keys from the cache.



57
58
59
# File 'lib/active_support/cache/mem_cache_store.rb', line 57

def read_multi(*keys)
  @data.get_multi keys
end

#statsObject



133
134
135
# File 'lib/active_support/cache/mem_cache_store.rb', line 133

def stats
  @data.stats
end

#write(key, value, options = nil) ⇒ Object

Writes a value to the cache.

Possible options:

  • :unless_exist - set to true if you don’t want to update the cache if the key is already set.

  • :expires_in - the number of seconds that this value may stay in the cache. See ActiveSupport::Cache::Store#write for an example.



76
77
78
79
80
81
82
83
84
85
86
87
# File 'lib/active_support/cache/mem_cache_store.rb', line 76

def write(key, value, options = nil)
  super
  method = options && options[:unless_exist] ? :add : :set
  # memcache-client will break the connection if you send it an integer
  # in raw mode, so we convert it to a string to be sure it continues working.
  value = value.to_s if raw?(options)
  response = @data.send(method, key, value, expires_in(options), raw?(options))
  response == Response::STORED
rescue MemCache::MemCacheError => e
  logger.error("MemCacheError (#{e}): #{e.message}")
  false
end