diff options
Diffstat (limited to 'activesupport')
-rw-r--r-- | activesupport/CHANGELOG.md | 10 | ||||
-rw-r--r-- | activesupport/lib/active_support/cache/redis_cache_store.rb | 19 | ||||
-rw-r--r-- | activesupport/lib/active_support/values/time_zone.rb | 3 | ||||
-rw-r--r-- | activesupport/test/time_zone_test.rb | 15 | ||||
-rw-r--r-- | activesupport/test/time_zone_test_helpers.rb | 13 |
5 files changed, 53 insertions, 7 deletions
diff --git a/activesupport/CHANGELOG.md b/activesupport/CHANGELOG.md index 82c985fae2..247eec68ac 100644 --- a/activesupport/CHANGELOG.md +++ b/activesupport/CHANGELOG.md @@ -1,3 +1,13 @@ +* Fix bug where `ActiveSupport::Timezone.all` would fail when tzinfo data for + any timezone defined in `ActiveSupport::MAPPING` is missing. + + *Dominik Sander* + +* Redis cache store: `delete_matched` no longer blocks the Redis server. + (Switches from evaled Lua to a batched SCAN + DEL loop.) + + *Gleb Mazovetskiy* + * Fix bug where `ActiveSupport::Cache` will massively inflate the storage size when compression is enabled (which is true by default). This patch does not attempt to repair existing data: please manually flush the cache diff --git a/activesupport/lib/active_support/cache/redis_cache_store.rb b/activesupport/lib/active_support/cache/redis_cache_store.rb index 74f935e02e..11c574258f 100644 --- a/activesupport/lib/active_support/cache/redis_cache_store.rb +++ b/activesupport/lib/active_support/cache/redis_cache_store.rb @@ -62,8 +62,9 @@ module ActiveSupport end end - DELETE_GLOB_LUA = "for i, name in ipairs(redis.call('KEYS', ARGV[1])) do redis.call('DEL', name); end" - private_constant :DELETE_GLOB_LUA + # The maximum number of entries to receive per SCAN call. + SCAN_BATCH_SIZE = 1000 + private_constant :SCAN_BATCH_SIZE # Support raw values in the local cache strategy. module LocalCacheWithRaw # :nodoc: @@ -231,12 +232,18 @@ module ActiveSupport # Failsafe: Raises errors. def delete_matched(matcher, options = nil) instrument :delete_matched, matcher do - case matcher - when String - redis.with { |c| c.eval DELETE_GLOB_LUA, [], [namespace_key(matcher, options)] } - else + unless String === matcher raise ArgumentError, "Only Redis glob strings are supported: #{matcher.inspect}" end + redis.with do |c| + pattern = namespace_key(matcher, options) + cursor = "0" + # Fetch keys in batches using SCAN to avoid blocking the Redis server. + begin + cursor, keys = c.scan(cursor, match: pattern, count: SCAN_BATCH_SIZE) + c.del(*keys) unless keys.empty? + end until cursor == "0" + end end end diff --git a/activesupport/lib/active_support/values/time_zone.rb b/activesupport/lib/active_support/values/time_zone.rb index 9dfaddb825..5f709c5fd9 100644 --- a/activesupport/lib/active_support/values/time_zone.rb +++ b/activesupport/lib/active_support/values/time_zone.rb @@ -279,7 +279,8 @@ module ActiveSupport def zones_map @zones_map ||= MAPPING.each_with_object({}) do |(name, _), zones| - zones[name] = self[name] + timezone = self[name] + zones[name] = timezone if timezone end end end diff --git a/activesupport/test/time_zone_test.rb b/activesupport/test/time_zone_test.rb index 63ca22efb5..120afa61f2 100644 --- a/activesupport/test/time_zone_test.rb +++ b/activesupport/test/time_zone_test.rb @@ -725,6 +725,21 @@ class TimeZoneTest < ActiveSupport::TestCase assert_not_includes all_zones, galapagos end + def test_all_not_raises_exception_with_mizzing_tzinfo_data + mappings = { + "Puerto Rico" => "America/Unknown", + "Pittsburgh" => "America/New_York" + } + + with_tz_mappings(mappings) do + assert_nil ActiveSupport::TimeZone["Puerto Rico"] + assert_nil ActiveSupport::TimeZone[-9] + assert_nothing_raised do + ActiveSupport::TimeZone.all + end + end + end + def test_index assert_nil ActiveSupport::TimeZone["bogus"] assert_instance_of ActiveSupport::TimeZone, ActiveSupport::TimeZone["Central Time (US & Canada)"] diff --git a/activesupport/test/time_zone_test_helpers.rb b/activesupport/test/time_zone_test_helpers.rb index 051703a781..85ed727c9b 100644 --- a/activesupport/test/time_zone_test_helpers.rb +++ b/activesupport/test/time_zone_test_helpers.rb @@ -23,4 +23,17 @@ module TimeZoneTestHelpers ensure ActiveSupport.to_time_preserves_timezone = old_preserve_tz end + + def with_tz_mappings(mappings) + old_mappings = ActiveSupport::TimeZone::MAPPING.dup + ActiveSupport::TimeZone.clear + ActiveSupport::TimeZone::MAPPING.clear + ActiveSupport::TimeZone::MAPPING.merge!(mappings) + + yield + ensure + ActiveSupport::TimeZone.clear + ActiveSupport::TimeZone::MAPPING.clear + ActiveSupport::TimeZone::MAPPING.merge!(old_mappings) + end end |