f9a7fb144085ae0e690684bf326a8bdcb6de886d
5 # A cache store implementation which stores data in Memcached:
6 # http://www.danga.com/memcached/
8 # This is currently the most popular cache store for production websites.
11 # - Clustering and load balancing. One can specify multiple memcached servers,
12 # and MemCacheStore will load balance between all available servers. If a
13 # server goes down, then MemCacheStore will ignore it until it goes back
15 # - Time-based expiry support. See #write and the +:expires_in+ option.
16 class MemCacheStore
< Store
17 module Response
# :nodoc:
19 NOT_STORED
= "NOT_STORED\r\n"
21 NOT_FOUND
= "NOT_FOUND\r\n"
22 DELETED
= "DELETED\r\n"
25 attr_reader
:addresses
27 # Creates a new MemCacheStore object, with the given memcached server
28 # addresses. Each address is either a host name, or a host-with-port string
29 # in the form of "host_name:port". For example:
31 # ActiveSupport::Cache::MemCacheStore.new("localhost", "server-downstairs.localnetwork:8229")
33 # If no addresses are specified, then MemCacheStore will connect to
34 # localhost port 11211 (the default memcached port).
35 def initialize(*addresses
)
36 addresses
= addresses
.flatten
37 options
= addresses
.extract_options
!
38 addresses
= ["localhost"] if addresses
.empty
?
39 @addresses = addresses
40 @data = MemCache
.new(addresses
, options
)
43 def read(key
, options
= nil) # :nodoc:
45 @data.get(key
, raw
?(options
))
46 rescue MemCache
::MemCacheError => e
47 logger
.error("MemCacheError (#{e}): #{e.message}")
51 # Writes a value to the cache.
54 # - +:unless_exist+ - set to true if you don't want to update the cache
55 # if the key is already set.
56 # - +:expires_in+ - the number of seconds that this value may stay in
57 # the cache. See ActiveSupport::Cache::Store#write for an example.
58 def write(key
, value
, options
= nil)
60 method
= options
&& options
[:unless_exist] ? :add : :set
61 # memcache-client will break the connection if you send it an integer
62 # in raw mode, so we convert it to a string to be sure it continues working.
63 value
= value
.to_s
if raw
?(options
)
64 response
= @data.send(method
, key
, value
, expires_in(options
), raw
?(options
))
65 response
== Response
::STORED
66 rescue MemCache
::MemCacheError => e
67 logger
.error("MemCacheError (#{e}): #{e.message}")
71 def delete(key
, options
= nil) # :nodoc:
73 response
= @data.delete(key
, expires_in(options
))
74 response
== Response
::DELETED
75 rescue MemCache
::MemCacheError => e
76 logger
.error("MemCacheError (#{e}): #{e.message}")
80 def exist
?(key
, options
= nil) # :nodoc:
81 # Doesn't call super, cause exist? in memcache is in fact a read
82 # But who cares? Reading is very fast anyway
83 !read(key
, options
).nil?
86 def increment(key
, amount
= 1) # :nodoc:
87 log("incrementing", key
, amount
)
89 response
= @data.incr(key
, amount
)
90 response
== Response
::NOT_FOUND ? nil : response
91 rescue MemCache
::MemCacheError
95 def decrement(key
, amount
= 1) # :nodoc:
96 log("decrement", key
, amount
)
98 response
= @data.decr(key
, amount
)
99 response
== Response
::NOT_FOUND ? nil : response
100 rescue MemCache
::MemCacheError
104 def delete_matched(matcher
, options
= nil) # :nodoc:
106 raise "Not supported by Memcache"
118 def expires_in(options
)
119 (options
&& options
[:expires_in]) || 0
123 options
&& options
[:raw]