From b047929c14f088d535eea460ddd8769f43cd4ae5 Mon Sep 17 00:00:00 2001 From: Pratik Naik Date: Sun, 2 Nov 2008 04:02:40 +0530 Subject: Merge with docrails --- activesupport/lib/active_support/cache.rb | 104 ++++++++++++++++++++- .../lib/active_support/cache/file_store.rb | 1 + .../lib/active_support/cache/mem_cache_store.rb | 42 +++++++-- .../lib/active_support/cache/memory_store.rb | 14 +++ .../cache/synchronized_memory_store.rb | 1 + 5 files changed, 152 insertions(+), 10 deletions(-) (limited to 'activesupport') 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 :force => true 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 :force => true 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 -- cgit v1.2.3