aboutsummaryrefslogtreecommitdiffstats
path: root/activesupport/lib
diff options
context:
space:
mode:
Diffstat (limited to 'activesupport/lib')
-rw-r--r--activesupport/lib/active_support/cache.rb104
-rw-r--r--activesupport/lib/active_support/cache/file_store.rb1
-rw-r--r--activesupport/lib/active_support/cache/mem_cache_store.rb42
-rw-r--r--activesupport/lib/active_support/cache/memory_store.rb14
-rw-r--r--activesupport/lib/active_support/cache/synchronized_memory_store.rb1
-rw-r--r--activesupport/lib/active_support/testing/performance.rb2
6 files changed, 153 insertions, 11 deletions
diff --git a/activesupport/lib/active_support/cache.rb b/activesupport/lib/active_support/cache.rb
index 51a6309dce..e62cec6fcb 100644
--- a/activesupport/lib/active_support/cache.rb
+++ b/activesupport/lib/active_support/cache.rb
@@ -1,7 +1,33 @@
require 'benchmark'
module ActiveSupport
+ # See ActiveSupport::Cache::Store for documentation.
module Cache
+ # Creates a new CacheStore object according to the given options.
+ #
+ # If no arguments are passed to this method, then a new
+ # ActiveSupport::Cache::MemoryStore object will be returned.
+ #
+ # If you pass a Symbol as the first argument, then a corresponding cache
+ # store class under the ActiveSupport::Cache namespace will be created.
+ # For example:
+ #
+ # ActiveSupport::Cache.lookup_store(:memory_store)
+ # # => returns a new ActiveSupport::Cache::MemoryStore object
+ #
+ # ActiveSupport::Cache.lookup_store(:drb_store)
+ # # => returns a new ActiveSupport::Cache::DRbStore object
+ #
+ # Any additional arguments will be passed to the corresponding cache store
+ # class's constructor:
+ #
+ # ActiveSupport::Cache.lookup_store(:file_store, "/tmp/cache")
+ # # => same as: ActiveSupport::Cache::FileStore.new("/tmp/cache")
+ #
+ # If the first argument is not a Symbol, then it will simply be returned:
+ #
+ # ActiveSupport::Cache.lookup_store(MyOwnCacheStore.new)
+ # # => returns MyOwnCacheStore.new
def self.lookup_store(*store_option)
store, *parameters = *([ store_option ].flatten)
@@ -36,6 +62,21 @@ module ActiveSupport
expanded_cache_key
end
+ # An abstract cache store class. There are multiple cache store
+ # implementations, each having its own additional features. See the classes
+ # under the ActiveSupport::Cache module, e.g.
+ # ActiveSupport::Cache::MemCacheStore. MemCacheStore is currently the most
+ # popular cache store for large production websites.
+ #
+ # ActiveSupport::Cache::Store is meant for caching strings. Some cache
+ # store implementations, like MemoryStore, are able to cache arbitrary
+ # Ruby objects, but don't count on every cache store to be able to do that.
+ #
+ # cache = ActiveSupport::Cache::MemoryStore.new
+ #
+ # cache.read("city") # => nil
+ # cache.write("city", "Duckburgh")
+ # cache.read("city") # => "Duckburgh"
class Store
cattr_accessor :logger
@@ -44,7 +85,46 @@ module ActiveSupport
self
end
- # Pass <tt>:force => true</tt> to force a cache miss.
+ # Fetches data from the cache, using the given key. If there is data in
+ # the cache with the given key, then that data is returned.
+ #
+ # If there is no such data in the cache (a cache miss occurred), then
+ # then nil will be returned. However, if a block has been passed, then
+ # that block will be run in the event of a cache miss. The return value
+ # of the block will be written to the cache under the given cache key,
+ # and that return value will be returned.
+ #
+ # cache.write("today", "Monday")
+ # cache.fetch("today") # => "Monday"
+ #
+ # cache.fetch("city") # => nil
+ # cache.fetch("city") do
+ # "Duckburgh"
+ # end
+ # cache.fetch("city") # => "Duckburgh"
+ #
+ # You may also specify additional options via the +options+ argument.
+ # Setting <tt>:force => true</tt> will force a cache miss:
+ #
+ # cache.write("today", "Monday")
+ # cache.fetch("today", :force => true) # => nil
+ #
+ # Other options will be handled by the specific cache store implementation.
+ # Internally, #fetch calls #read, and calls #write on a cache miss.
+ # +options+ will be passed to the #read and #write calls.
+ #
+ # For example, MemCacheStore's #write method supports the +:expires_in+
+ # option, which tells the memcached server to automatically expire the
+ # cache item after a certain period. We can use this option with #fetch
+ # too:
+ #
+ # cache = ActiveSupport::Cache::MemCacheStore.new
+ # cache.fetch("foo", :force => true, :expires_in => 5.seconds) do
+ # "bar"
+ # end
+ # cache.fetch("foo") # => "bar"
+ # sleep(6)
+ # cache.fetch("foo") # => nil
def fetch(key, options = {})
@logger_off = true
if !options[:force] && value = read(key, options)
@@ -68,10 +148,32 @@ module ActiveSupport
end
end
+ # Fetches data from the cache, using the given key. If there is data in
+ # the cache with the given key, then that data is returned. Otherwise,
+ # nil is returned.
+ #
+ # You may also specify additional options via the +options+ argument.
+ # The specific cache store implementation will decide what to do with
+ # +options+.
def read(key, options = nil)
log("read", key, options)
end
+ # Writes the given value to the cache, with the given key.
+ #
+ # You may also specify additional options via the +options+ argument.
+ # The specific cache store implementation will decide what to do with
+ # +options+.
+ #
+ # For example, MemCacheStore supports the +:expires_in+ option, which
+ # tells the memcached server to automatically expire the cache item after
+ # a certain period:
+ #
+ # cache = ActiveSupport::Cache::MemCacheStore.new
+ # cache.write("foo", "bar", :expires_in => 5.seconds)
+ # cache.read("foo") # => "bar"
+ # sleep(6)
+ # cache.read("foo") # => nil
def write(key, value, options = nil)
log("write", key, options)
end
diff --git a/activesupport/lib/active_support/cache/file_store.rb b/activesupport/lib/active_support/cache/file_store.rb
index ffe0baba99..7f34cb52a1 100644
--- a/activesupport/lib/active_support/cache/file_store.rb
+++ b/activesupport/lib/active_support/cache/file_store.rb
@@ -1,5 +1,6 @@
module ActiveSupport
module Cache
+ # A cache store implementation which stores everything on the filesystem.
class FileStore < Store
attr_reader :cache_path
diff --git a/activesupport/lib/active_support/cache/mem_cache_store.rb b/activesupport/lib/active_support/cache/mem_cache_store.rb
index 5531c30b7f..f9a7fb1440 100644
--- a/activesupport/lib/active_support/cache/mem_cache_store.rb
+++ b/activesupport/lib/active_support/cache/mem_cache_store.rb
@@ -2,8 +2,19 @@ require 'memcache'
module ActiveSupport
module Cache
+ # A cache store implementation which stores data in Memcached:
+ # http://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.
class MemCacheStore < Store
- module Response
+ module Response # :nodoc:
STORED = "STORED\r\n"
NOT_STORED = "NOT_STORED\r\n"
EXISTS = "EXISTS\r\n"
@@ -13,6 +24,14 @@ module ActiveSupport
attr_reader :addresses
+ # 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).
def initialize(*addresses)
addresses = addresses.flatten
options = addresses.extract_options!
@@ -21,7 +40,7 @@ module ActiveSupport
@data = MemCache.new(addresses, options)
end
- def read(key, options = nil)
+ def read(key, options = nil) # :nodoc:
super
@data.get(key, raw?(options))
rescue MemCache::MemCacheError => e
@@ -29,8 +48,13 @@ module ActiveSupport
nil
end
- # Set key = value. Pass :unless_exist => true if you don't
- # want to update the cache if the key is already set.
+ # 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.
def write(key, value, options = nil)
super
method = options && options[:unless_exist] ? :add : :set
@@ -44,7 +68,7 @@ module ActiveSupport
false
end
- def delete(key, options = nil)
+ def delete(key, options = nil) # :nodoc:
super
response = @data.delete(key, expires_in(options))
response == Response::DELETED
@@ -53,13 +77,13 @@ module ActiveSupport
false
end
- def exist?(key, options = nil)
+ 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
!read(key, options).nil?
end
- def increment(key, amount = 1)
+ def increment(key, amount = 1) # :nodoc:
log("incrementing", key, amount)
response = @data.incr(key, amount)
@@ -68,7 +92,7 @@ module ActiveSupport
nil
end
- def decrement(key, amount = 1)
+ def decrement(key, amount = 1) # :nodoc:
log("decrement", key, amount)
response = @data.decr(key, amount)
@@ -77,7 +101,7 @@ module ActiveSupport
nil
end
- def delete_matched(matcher, options = nil)
+ def delete_matched(matcher, options = nil) # :nodoc:
super
raise "Not supported by Memcache"
end
diff --git a/activesupport/lib/active_support/cache/memory_store.rb b/activesupport/lib/active_support/cache/memory_store.rb
index c1a713b4c5..1b30d49155 100644
--- a/activesupport/lib/active_support/cache/memory_store.rb
+++ b/activesupport/lib/active_support/cache/memory_store.rb
@@ -1,5 +1,19 @@
module ActiveSupport
module Cache
+ # A cache store implementation which stores everything into memory in the
+ # same process. If you're running multiple Ruby on Rails server processes
+ # (which is the case if you're using mongrel_cluster or Phusion Passenger),
+ # then this means that your Rails server process instances won't be able
+ # to share cache data with each other. If your application never performs
+ # manual cache item expiry (e.g. when you're using generational cache keys),
+ # then using MemoryStore is ok. Otherwise, consider carefully whether you
+ # should be using this cache store.
+ #
+ # MemoryStore is not only able to store strings, but also arbitrary Ruby
+ # objects.
+ #
+ # MemoryStore is not thread-safe. Use SynchronizedMemoryStore instead
+ # if you need thread-safety.
class MemoryStore < Store
def initialize
@data = {}
diff --git a/activesupport/lib/active_support/cache/synchronized_memory_store.rb b/activesupport/lib/active_support/cache/synchronized_memory_store.rb
index d2ff28768f..ea03a119c6 100644
--- a/activesupport/lib/active_support/cache/synchronized_memory_store.rb
+++ b/activesupport/lib/active_support/cache/synchronized_memory_store.rb
@@ -1,5 +1,6 @@
module ActiveSupport
module Cache
+ # Like MemoryStore, but thread-safe.
class SynchronizedMemoryStore < MemoryStore
def initialize
super
diff --git a/activesupport/lib/active_support/testing/performance.rb b/activesupport/lib/active_support/testing/performance.rb
index f996c40793..bd136c2596 100644
--- a/activesupport/lib/active_support/testing/performance.rb
+++ b/activesupport/lib/active_support/testing/performance.rb
@@ -124,7 +124,7 @@ module ActiveSupport
def environment
unless defined? @env
- app = "#{$1}.#{$2}" if `git branch -v` =~ /^\* (\S+)\s+(\S+)/
+ app = "#{$1}.#{$2}" if File.directory?('.git') && `git branch -v` =~ /^\* (\S+)\s+(\S+)/
rails = Rails::VERSION::STRING
if File.directory?('vendor/rails/.git')