Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix AS::Cache 7.1 format to properly compress bare strings #48660

Merged
merged 1 commit into from Jul 5, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
19 changes: 15 additions & 4 deletions activesupport/lib/active_support/cache/serializer_with_fallback.rb
Expand Up @@ -159,12 +159,20 @@ module Marshal71WithFallback
MARK_UNCOMPRESSED = "\x00".b.freeze
MARK_COMPRESSED = "\x01".b.freeze

def dump(entry, raw = false)
if raw
super(entry)
else
MARK_UNCOMPRESSED + super(entry)
end
end

def _dump(entry)
MARK_UNCOMPRESSED + Marshal.dump(entry.pack)
Marshal.dump(entry.pack)
end

def dump_compressed(entry, threshold)
dumped = Marshal.dump(entry.pack)
dumped = dump(entry, true)
if compressed = try_compress(dumped, threshold)
MARK_COMPRESSED + compressed
else
Expand All @@ -175,7 +183,7 @@ def dump_compressed(entry, threshold)
def _load(marked)
dumped = marked.byteslice(1..-1)
dumped = decompress(dumped) if marked.start_with?(MARK_COMPRESSED)
Cache::Entry.unpack(Marshal.load(dumped))
try_load_bare_string(dumped) || Cache::Entry.unpack(Marshal.load(dumped))
end

def dumped?(dumped)
Expand All @@ -186,7 +194,10 @@ def dumped?(dumped)
module Marshal70WithFallback
include Marshal71WithFallback
extend self
alias :dump :_dump # Prevent dumping bare strings.

def try_dump_bare_string(_entry)
nil # Prevent dumping bare strings.
end
end

module MessagePackWithFallback
Expand Down
2 changes: 2 additions & 0 deletions activesupport/test/abstract_unit.rb
Expand Up @@ -29,6 +29,8 @@
ActiveSupport.to_time_preserves_timezone = ENV.fetch("PRESERVE_TIMEZONES", "1") == "1"
end

ActiveSupport::Cache.format_version = 7.1

# Disable available locale checks to avoid warnings running the test suite.
I18n.enforce_available_locales = false

Expand Down
Expand Up @@ -10,7 +10,7 @@ module CacheStoreFormatVersionBehavior
included do
test "format version affects default coder" do
coders = FORMAT_VERSIONS.map do |format_version|
ActiveSupport::Cache.with(format_version: format_version) do
with_format(format_version) do
lookup_store.instance_variable_get(:@coder)
end
end
Expand All @@ -19,7 +19,7 @@ module CacheStoreFormatVersionBehavior
end

test "invalid format version raises" do
ActiveSupport::Cache.with(format_version: 0) do
with_format(0) do
assert_raises do
lookup_store
end
Expand All @@ -30,26 +30,33 @@ module CacheStoreFormatVersionBehavior
test "format version #{read_version.inspect} can read #{write_version.inspect} entries" do
key = SecureRandom.uuid

ActiveSupport::Cache.with(format_version: write_version) do
with_format(write_version) do
lookup_store.write(key, "value for #{key}")
end

ActiveSupport::Cache.with(format_version: read_version) do
with_format(read_version) do
assert_equal "value for #{key}", lookup_store.read(key)
end
end

test "format version #{read_version.inspect} can read #{write_version.inspect} entries with compression" do
key = SecureRandom.uuid

ActiveSupport::Cache.with(format_version: write_version) do
with_format(write_version) do
lookup_store(compress_threshold: 1).write(key, key * 10)
end

ActiveSupport::Cache.with(format_version: read_version) do
with_format(read_version) do
assert_equal key * 10, lookup_store.read(key)
end
end
end
end

private
def with_format(format_version, &block)
ActiveSupport.deprecator.silence do
ActiveSupport::Cache.with(format_version: format_version, &block)
end
end
end