lib/active_support/cache.rb in activesupport-4.0.0.beta1 vs lib/active_support/cache.rb in activesupport-4.0.0.rc1

- old
+ new

@@ -54,27 +54,30 @@ def lookup_store(*store_option) store, *parameters = *Array.wrap(store_option).flatten case store when Symbol - store_class_name = store.to_s.camelize - store_class = - begin - require "active_support/cache/#{store}" - rescue LoadError => e - raise "Could not find cache store adapter for #{store} (#{e})" - else - ActiveSupport::Cache.const_get(store_class_name) - end - store_class.new(*parameters) + retrieve_store_class(store).new(*parameters) when nil ActiveSupport::Cache::MemoryStore.new else store end end + # Expands out the +key+ argument into a key that can be used for the + # cache store. Optionally accepts a namespace, and all keys will be + # scoped within that namespace. + # + # If the +key+ argument provided is an array, or responds to +to_a+, then + # each of elements in the array will be turned into parameters/keys and + # concatenated into a single key. For example: + # + # expand_cache_key([:foo, :bar]) # => "foo/bar" + # expand_cache_key([:foo, :bar], "namespace") # => "namespace/foo/bar" + # + # The +key+ argument can also respond to +cache_key+ or +to_param+. def expand_cache_key(key, namespace = nil) expanded_cache_key = namespace ? "#{namespace}/" : "" if prefix = ENV["RAILS_CACHE_ID"] || ENV["RAILS_APP_VERSION"] expanded_cache_key << "#{prefix}/" @@ -92,10 +95,20 @@ when key.is_a?(Array) then key.map { |element| retrieve_cache_key(element) }.to_param when key.respond_to?(:to_a) then retrieve_cache_key(key.to_a) else key.to_param end.to_s end + + # Obtains the specified cache store class, given the name of the +store+. + # Raises an error when the store class cannot be found. + def retrieve_store_class(store) + require "active_support/cache/#{store}" + rescue LoadError => e + raise "Could not find cache store adapter for #{store} (#{e})" + else + ActiveSupport::Cache.const_get(store.to_s.camelize) + end 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. @@ -342,32 +355,32 @@ # Writes the value to the cache, with the key. # # Options are passed to the underlying cache implementation. def write(name, value, options = nil) options = merged_options(options) - instrument(:write, name, options) do |payload| + instrument(:write, name, options) do entry = Entry.new(value, options) write_entry(namespaced_key(name, options), entry, options) end end # Deletes an entry in the cache. Returns +true+ if an entry is deleted. # # Options are passed to the underlying cache implementation. def delete(name, options = nil) options = merged_options(options) - instrument(:delete, name) do |payload| + instrument(:delete, name) do delete_entry(namespaced_key(name, options), options) end end # Return +true+ if the cache contains an entry for the given key. # # Options are passed to the underlying cache implementation. def exist?(name, options = nil) options = merged_options(options) - instrument(:exist?, name) do |payload| + instrument(:exist?, name) do entry = read_entry(namespaced_key(name, options), options) entry && !entry.expired? end end @@ -520,11 +533,11 @@ end def handle_expired_entry(entry, key, options) if entry && entry.expired? race_ttl = options[:race_condition_ttl].to_i - if race_ttl && (Time.now - entry.expires_at <= race_ttl) + if race_ttl && (Time.now.to_f - entry.expires_at <= race_ttl) # When an entry has :race_condition_ttl defined, put the stale entry back into the cache # for a brief period while the entry is begin recalculated. entry.expires_at = Time.now + race_ttl write_entry(key, entry, :expires_in => race_ttl * 2) else @@ -560,42 +573,42 @@ # Create a new cache entry for the specified value. Options supported are # +:compress+, +:compress_threshold+, and +:expires_in+. def initialize(value, options = {}) if should_compress?(value, options) - @v = compress(value) - @c = true + @value = compress(value) + @compressed = true else - @v = value + @value = value end - if expires_in = options[:expires_in] - @x = (Time.now + expires_in).to_i - end + @created_at = Time.now.to_f + @expires_in = options[:expires_in] + @expires_in = @expires_in.to_f if @expires_in end def value - convert_version_3_entry! if defined?(@value) - compressed? ? uncompress(@v) : @v + convert_version_4beta1_entry! if defined?(@v) + compressed? ? uncompress(@value) : @value end # Check if the entry is expired. The +expires_in+ parameter can override # the value set when the entry was created. def expired? - convert_version_3_entry! if defined?(@value) - if defined?(@x) - @x && @x < Time.now.to_i - else - false - end + convert_version_4beta1_entry! if defined?(@value) + @expires_in && @created_at + @expires_in <= Time.now.to_f end def expires_at - Time.at(@x) if defined?(@x) + @expires_in ? @created_at + @expires_in : nil end def expires_at=(value) - @x = value.to_i + if value + @expires_in = value.to_f - @created_at + else + @expires_in = nil + end end # Returns the size of the cached value. This could be less than # <tt>value.size</tt> if the data is compressed. def size @@ -604,26 +617,26 @@ else case value when NilClass 0 when String - @v.bytesize + @value.bytesize else - @s = Marshal.dump(@v).bytesize + @s = Marshal.dump(@value).bytesize end end end # Duplicate the value in a class. This is used by cache implementations that don't natively # serialize entries to protect against accidental cache modifications. def dup_value! - convert_version_3_entry! if defined?(@value) - if @v && !compressed? && !(@v.is_a?(Numeric) || @v == true || @v == false) - if @v.is_a?(String) - @v = @v.dup + convert_version_4beta1_entry! if defined?(@v) + if @value && !compressed? && !(@value.is_a?(Numeric) || @value == true || @value == false) + if @value.is_a?(String) + @value = @value.dup else - @v = Marshal.load(Marshal.dump(@v)) + @value = Marshal.load(Marshal.dump(@value)) end end end private @@ -635,11 +648,11 @@ end false end def compressed? - defined?(@c) ? @c : false + defined?(@compressed) ? @compressed : false end def compress(value) Zlib::Deflate.deflate(Marshal.dump(value)) end @@ -648,22 +661,22 @@ Marshal.load(Zlib::Inflate.inflate(value)) end # The internals of this method changed between Rails 3.x and 4.0. This method provides the glue # to ensure that cache entries created under the old version still work with the new class definition. - def convert_version_3_entry! - if defined?(@value) - @v = @value - remove_instance_variable(:@value) + def convert_version_4beta1_entry! + if defined?(@v) + @value = @v + remove_instance_variable(:@v) end - if defined?(@compressed) - @c = @compressed - remove_instance_variable(:@compressed) + if defined?(@c) + @compressed = @c + remove_instance_variable(:@c) end - if defined?(@expires_in) && defined?(@created_at) && @expires_in && @created_at - @x = (@created_at + @expires_in).to_i - remove_instance_variable(:@created_at) - remove_instance_variable(:@expires_in) + if defined?(@x) && @x + @created_at ||= Time.now.to_f + @expires_in = @x - @created_at + remove_instance_variable(:@x) end end end end end