Skip to content

Commit

Permalink
Merge pull request #10239 from rubys/cache_entry_conversion_problems
Browse files Browse the repository at this point in the history
switch (and lazily convert) ivar names to 3.x
  • Loading branch information
jeremy committed Apr 16, 2013
2 parents 1692732 + 8efc87c commit 46287d6
Show file tree
Hide file tree
Showing 2 changed files with 51 additions and 52 deletions.
72 changes: 36 additions & 36 deletions activesupport/lib/active_support/cache.rb
Expand Up @@ -522,7 +522,7 @@ def find_cached_entry(key, name, options)
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
Expand Down Expand Up @@ -562,38 +562,38 @@ class Entry # :nodoc:
# +: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
end
if expires_in = options[:expires_in]
@x = (Time.now + expires_in).to_i
@value = value
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
Expand All @@ -606,22 +606,22 @@ def size
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
Expand All @@ -637,7 +637,7 @@ def should_compress?(value, options)
end

def compressed?
defined?(@c) ? @c : false
defined?(@compressed) ? @compressed : false
end

def compress(value)
Expand All @@ -650,19 +650,19 @@ def uncompress(value)

# 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
Expand Down
31 changes: 15 additions & 16 deletions activesupport/test/caching_test.rb
Expand Up @@ -943,29 +943,28 @@ def test_non_compress_values
assert_equal value.bytesize, entry.size
end

def test_restoring_version_3_entries
version_3_entry = ActiveSupport::Cache::Entry.allocate
version_3_entry.instance_variable_set(:@value, "hello")
version_3_entry.instance_variable_set(:@created_at, Time.now - 60)
entry = Marshal.load(Marshal.dump(version_3_entry))
def test_restoring_version_4beta1_entries
version_4beta1_entry = ActiveSupport::Cache::Entry.allocate
version_4beta1_entry.instance_variable_set(:@v, "hello")
version_4beta1_entry.instance_variable_set(:@x, Time.now.to_i + 60)
entry = Marshal.load(Marshal.dump(version_4beta1_entry))
assert_equal "hello", entry.value
assert_equal false, entry.expired?
end

def test_restoring_compressed_version_3_entries
version_3_entry = ActiveSupport::Cache::Entry.allocate
version_3_entry.instance_variable_set(:@value, Zlib::Deflate.deflate(Marshal.dump("hello")))
version_3_entry.instance_variable_set(:@compressed, true)
entry = Marshal.load(Marshal.dump(version_3_entry))
def test_restoring_compressed_version_4beta1_entries
version_4beta1_entry = ActiveSupport::Cache::Entry.allocate
version_4beta1_entry.instance_variable_set(:@v, Zlib::Deflate.deflate(Marshal.dump("hello")))
version_4beta1_entry.instance_variable_set(:@c, true)
entry = Marshal.load(Marshal.dump(version_4beta1_entry))
assert_equal "hello", entry.value
end

def test_restoring_expired_version_3_entries
version_3_entry = ActiveSupport::Cache::Entry.allocate
version_3_entry.instance_variable_set(:@value, "hello")
version_3_entry.instance_variable_set(:@created_at, Time.now - 60)
version_3_entry.instance_variable_set(:@expires_in, 58.9)
entry = Marshal.load(Marshal.dump(version_3_entry))
def test_restoring_expired_version_4beta1_entries
version_4beta1_entry = ActiveSupport::Cache::Entry.allocate
version_4beta1_entry.instance_variable_set(:@v, "hello")
version_4beta1_entry.instance_variable_set(:@x, Time.now.to_i - 1)
entry = Marshal.load(Marshal.dump(version_4beta1_entry))
assert_equal "hello", entry.value
assert_equal true, entry.expired?
end
Expand Down

0 comments on commit 46287d6

Please sign in to comment.