activesupport 5.1.7 → 6.1.7
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of activesupport might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/CHANGELOG.md +434 -490
- data/MIT-LICENSE +1 -1
- data/README.rdoc +6 -5
- data/lib/active_support/actionable_error.rb +48 -0
- data/lib/active_support/all.rb +2 -0
- data/lib/active_support/array_inquirer.rb +6 -2
- data/lib/active_support/backtrace_cleaner.rb +31 -3
- data/lib/active_support/benchmarkable.rb +3 -1
- data/lib/active_support/builder.rb +2 -0
- data/lib/active_support/cache/file_store.rb +37 -36
- data/lib/active_support/cache/mem_cache_store.rb +72 -56
- data/lib/active_support/cache/memory_store.rb +61 -33
- data/lib/active_support/cache/null_store.rb +10 -3
- data/lib/active_support/cache/redis_cache_store.rb +493 -0
- data/lib/active_support/cache/strategy/local_cache.rb +67 -21
- data/lib/active_support/cache/strategy/local_cache_middleware.rb +2 -0
- data/lib/active_support/cache.rb +310 -126
- data/lib/active_support/callbacks.rb +106 -100
- data/lib/active_support/concern.rb +79 -6
- data/lib/active_support/concurrency/load_interlock_aware_monitor.rb +18 -0
- data/lib/active_support/concurrency/share_lock.rb +2 -1
- data/lib/active_support/configurable.rb +12 -14
- data/lib/active_support/configuration_file.rb +51 -0
- data/lib/active_support/core_ext/array/access.rb +21 -7
- data/lib/active_support/core_ext/array/conversions.rb +7 -5
- data/lib/active_support/core_ext/array/extract.rb +21 -0
- data/lib/active_support/core_ext/array/extract_options.rb +2 -0
- data/lib/active_support/core_ext/array/grouping.rb +2 -0
- data/lib/active_support/core_ext/array/inquiry.rb +2 -0
- data/lib/active_support/core_ext/array/wrap.rb +2 -0
- data/lib/active_support/core_ext/array.rb +3 -1
- data/lib/active_support/core_ext/benchmark.rb +4 -2
- data/lib/active_support/core_ext/big_decimal/conversions.rb +2 -0
- data/lib/active_support/core_ext/big_decimal.rb +2 -0
- data/lib/active_support/core_ext/class/attribute.rb +50 -47
- data/lib/active_support/core_ext/class/attribute_accessors.rb +2 -0
- data/lib/active_support/core_ext/class/subclasses.rb +18 -40
- data/lib/active_support/core_ext/class.rb +2 -0
- data/lib/active_support/core_ext/date/acts_like.rb +2 -0
- data/lib/active_support/core_ext/date/blank.rb +2 -0
- data/lib/active_support/core_ext/date/calculations.rb +8 -5
- data/lib/active_support/core_ext/date/conversions.rb +12 -10
- data/lib/active_support/core_ext/date/zones.rb +2 -0
- data/lib/active_support/core_ext/date.rb +2 -0
- data/lib/active_support/core_ext/date_and_time/calculations.rb +61 -37
- data/lib/active_support/core_ext/date_and_time/compatibility.rb +18 -1
- data/lib/active_support/core_ext/date_and_time/zones.rb +2 -1
- data/lib/active_support/core_ext/date_time/acts_like.rb +2 -0
- data/lib/active_support/core_ext/date_time/blank.rb +2 -0
- data/lib/active_support/core_ext/date_time/calculations.rb +3 -1
- data/lib/active_support/core_ext/date_time/compatibility.rb +7 -5
- data/lib/active_support/core_ext/date_time/conversions.rb +2 -1
- data/lib/active_support/core_ext/date_time.rb +2 -0
- data/lib/active_support/core_ext/digest/uuid.rb +4 -1
- data/lib/active_support/core_ext/digest.rb +3 -0
- data/lib/active_support/core_ext/enumerable.rb +174 -71
- data/lib/active_support/core_ext/file/atomic.rb +3 -1
- data/lib/active_support/core_ext/file.rb +2 -0
- data/lib/active_support/core_ext/hash/conversions.rb +7 -5
- data/lib/active_support/core_ext/hash/deep_merge.rb +8 -12
- data/lib/active_support/core_ext/hash/deep_transform_values.rb +46 -0
- data/lib/active_support/core_ext/hash/except.rb +4 -2
- data/lib/active_support/core_ext/hash/indifferent_access.rb +2 -0
- data/lib/active_support/core_ext/hash/keys.rb +3 -30
- data/lib/active_support/core_ext/hash/reverse_merge.rb +5 -2
- data/lib/active_support/core_ext/hash/slice.rb +8 -29
- data/lib/active_support/core_ext/hash.rb +3 -2
- data/lib/active_support/core_ext/integer/inflections.rb +2 -0
- data/lib/active_support/core_ext/integer/multiple.rb +3 -1
- data/lib/active_support/core_ext/integer/time.rb +7 -14
- data/lib/active_support/core_ext/integer.rb +2 -0
- data/lib/active_support/core_ext/kernel/concern.rb +2 -0
- data/lib/active_support/core_ext/kernel/reporting.rb +2 -0
- data/lib/active_support/core_ext/kernel/singleton_class.rb +2 -0
- data/lib/active_support/core_ext/kernel.rb +2 -1
- data/lib/active_support/core_ext/load_error.rb +3 -8
- data/lib/active_support/core_ext/marshal.rb +4 -0
- data/lib/active_support/core_ext/module/aliasing.rb +2 -0
- data/lib/active_support/core_ext/module/anonymous.rb +2 -0
- data/lib/active_support/core_ext/module/attr_internal.rb +4 -2
- data/lib/active_support/core_ext/module/attribute_accessors.rb +44 -56
- data/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb +18 -18
- data/lib/active_support/core_ext/module/concerning.rb +15 -10
- data/lib/active_support/core_ext/module/delegation.rb +103 -58
- data/lib/active_support/core_ext/module/deprecation.rb +2 -0
- data/lib/active_support/core_ext/module/introspection.rb +18 -15
- data/lib/active_support/core_ext/module/redefine_method.rb +40 -0
- data/lib/active_support/core_ext/module/remove_method.rb +5 -23
- data/lib/active_support/core_ext/module.rb +3 -1
- data/lib/active_support/core_ext/name_error.rb +36 -2
- data/lib/active_support/core_ext/numeric/bytes.rb +2 -0
- data/lib/active_support/core_ext/numeric/conversions.rb +131 -129
- data/lib/active_support/core_ext/numeric/time.rb +7 -15
- data/lib/active_support/core_ext/numeric.rb +2 -1
- data/lib/active_support/core_ext/object/acts_like.rb +12 -1
- data/lib/active_support/core_ext/object/blank.rb +13 -3
- data/lib/active_support/core_ext/object/conversions.rb +2 -0
- data/lib/active_support/core_ext/object/deep_dup.rb +3 -1
- data/lib/active_support/core_ext/object/duplicable.rb +9 -114
- data/lib/active_support/core_ext/object/inclusion.rb +2 -0
- data/lib/active_support/core_ext/object/instance_variables.rb +2 -0
- data/lib/active_support/core_ext/object/json.rb +22 -2
- data/lib/active_support/core_ext/object/to_param.rb +2 -0
- data/lib/active_support/core_ext/object/to_query.rb +2 -0
- data/lib/active_support/core_ext/object/try.rb +19 -7
- data/lib/active_support/core_ext/object/with_options.rb +4 -2
- data/lib/active_support/core_ext/object.rb +2 -0
- data/lib/active_support/core_ext/range/compare_range.rb +82 -0
- data/lib/active_support/core_ext/range/conversions.rb +35 -25
- data/lib/active_support/core_ext/range/each.rb +5 -2
- data/lib/active_support/core_ext/range/include_time_with_zone.rb +28 -0
- data/lib/active_support/core_ext/range/overlaps.rb +2 -0
- data/lib/active_support/core_ext/range.rb +4 -1
- data/lib/active_support/core_ext/regexp.rb +10 -5
- data/lib/active_support/core_ext/securerandom.rb +25 -3
- data/lib/active_support/core_ext/string/access.rb +7 -16
- data/lib/active_support/core_ext/string/behavior.rb +2 -0
- data/lib/active_support/core_ext/string/conversions.rb +3 -0
- data/lib/active_support/core_ext/string/exclude.rb +2 -0
- data/lib/active_support/core_ext/string/filters.rb +44 -1
- data/lib/active_support/core_ext/string/indent.rb +2 -0
- data/lib/active_support/core_ext/string/inflections.rb +69 -16
- data/lib/active_support/core_ext/string/inquiry.rb +3 -0
- data/lib/active_support/core_ext/string/multibyte.rb +9 -4
- data/lib/active_support/core_ext/string/output_safety.rb +104 -20
- data/lib/active_support/core_ext/string/starts_ends_with.rb +4 -2
- data/lib/active_support/core_ext/string/strip.rb +5 -1
- data/lib/active_support/core_ext/string/zones.rb +2 -0
- data/lib/active_support/core_ext/string.rb +2 -0
- data/lib/active_support/core_ext/symbol/starts_ends_with.rb +14 -0
- data/lib/active_support/core_ext/symbol.rb +3 -0
- data/lib/active_support/core_ext/time/acts_like.rb +2 -0
- data/lib/active_support/core_ext/time/calculations.rb +76 -18
- data/lib/active_support/core_ext/time/compatibility.rb +4 -2
- data/lib/active_support/core_ext/time/conversions.rb +4 -0
- data/lib/active_support/core_ext/time/zones.rb +6 -4
- data/lib/active_support/core_ext/time.rb +2 -0
- data/lib/active_support/core_ext/uri.rb +11 -6
- data/lib/active_support/core_ext.rb +3 -1
- data/lib/active_support/current_attributes/test_helper.rb +13 -0
- data/lib/active_support/current_attributes.rb +210 -0
- data/lib/active_support/dependencies/autoload.rb +2 -0
- data/lib/active_support/dependencies/interlock.rb +2 -0
- data/lib/active_support/dependencies/zeitwerk_integration.rb +120 -0
- data/lib/active_support/dependencies.rb +134 -60
- data/lib/active_support/deprecation/behaviors.rb +43 -11
- data/lib/active_support/deprecation/constant_accessor.rb +4 -2
- data/lib/active_support/deprecation/disallowed.rb +56 -0
- data/lib/active_support/deprecation/instance_delegator.rb +2 -1
- data/lib/active_support/deprecation/method_wrappers.rb +29 -21
- data/lib/active_support/deprecation/proxy_wrappers.rb +32 -6
- data/lib/active_support/deprecation/reporting.rb +54 -9
- data/lib/active_support/deprecation.rb +9 -2
- data/lib/active_support/descendants_tracker.rb +61 -9
- data/lib/active_support/digest.rb +22 -0
- data/lib/active_support/duration/iso8601_parser.rb +6 -6
- data/lib/active_support/duration/iso8601_serializer.rb +20 -14
- data/lib/active_support/duration.rb +102 -45
- data/lib/active_support/encrypted_configuration.rb +45 -0
- data/lib/active_support/encrypted_file.rb +117 -0
- data/lib/active_support/environment_inquirer.rb +20 -0
- data/lib/active_support/evented_file_update_checker.rb +84 -117
- data/lib/active_support/execution_wrapper.rb +19 -13
- data/lib/active_support/executor.rb +2 -0
- data/lib/active_support/file_update_checker.rb +2 -1
- data/lib/active_support/fork_tracker.rb +64 -0
- data/lib/active_support/gem_version.rb +3 -1
- data/lib/active_support/gzip.rb +2 -0
- data/lib/active_support/hash_with_indifferent_access.rb +123 -41
- data/lib/active_support/i18n.rb +4 -1
- data/lib/active_support/i18n_railtie.rb +19 -14
- data/lib/active_support/inflections.rb +2 -0
- data/lib/active_support/inflector/inflections.rb +19 -8
- data/lib/active_support/inflector/methods.rb +87 -77
- data/lib/active_support/inflector/transliterate.rb +56 -18
- data/lib/active_support/inflector.rb +2 -0
- data/lib/active_support/json/decoding.rb +27 -26
- data/lib/active_support/json/encoding.rb +13 -3
- data/lib/active_support/json.rb +2 -0
- data/lib/active_support/key_generator.rb +3 -33
- data/lib/active_support/lazy_load_hooks.rb +7 -2
- data/lib/active_support/locale/en.rb +33 -0
- data/lib/active_support/locale/en.yml +7 -3
- data/lib/active_support/log_subscriber/test_helper.rb +2 -0
- data/lib/active_support/log_subscriber.rb +42 -11
- data/lib/active_support/logger.rb +4 -17
- data/lib/active_support/logger_silence.rb +13 -20
- data/lib/active_support/logger_thread_safe_level.rb +54 -7
- data/lib/active_support/message_encryptor.rb +100 -32
- data/lib/active_support/message_verifier.rb +85 -14
- data/lib/active_support/messages/metadata.rb +80 -0
- data/lib/active_support/messages/rotation_configuration.rb +23 -0
- data/lib/active_support/messages/rotator.rb +57 -0
- data/lib/active_support/multibyte/chars.rb +12 -68
- data/lib/active_support/multibyte/unicode.rb +17 -327
- data/lib/active_support/multibyte.rb +2 -0
- data/lib/active_support/notifications/fanout.rb +118 -16
- data/lib/active_support/notifications/instrumenter.rb +73 -9
- data/lib/active_support/notifications.rb +74 -8
- data/lib/active_support/number_helper/number_converter.rb +7 -6
- data/lib/active_support/number_helper/number_to_currency_converter.rb +6 -9
- data/lib/active_support/number_helper/number_to_delimited_converter.rb +5 -2
- data/lib/active_support/number_helper/number_to_human_converter.rb +6 -3
- data/lib/active_support/number_helper/number_to_human_size_converter.rb +6 -3
- data/lib/active_support/number_helper/number_to_percentage_converter.rb +5 -1
- data/lib/active_support/number_helper/number_to_phone_converter.rb +5 -2
- data/lib/active_support/number_helper/number_to_rounded_converter.rb +14 -27
- data/lib/active_support/number_helper/rounding_helper.rb +16 -30
- data/lib/active_support/number_helper.rb +40 -12
- data/lib/active_support/option_merger.rb +24 -3
- data/lib/active_support/ordered_hash.rb +3 -1
- data/lib/active_support/ordered_options.rb +17 -5
- data/lib/active_support/parameter_filter.rb +133 -0
- data/lib/active_support/per_thread_registry.rb +4 -1
- data/lib/active_support/proxy_object.rb +2 -0
- data/lib/active_support/rails.rb +3 -10
- data/lib/active_support/railtie.rb +60 -9
- data/lib/active_support/reloader.rb +12 -11
- data/lib/active_support/rescuable.rb +7 -6
- data/lib/active_support/secure_compare_rotator.rb +51 -0
- data/lib/active_support/security_utils.rb +26 -15
- data/lib/active_support/string_inquirer.rb +6 -3
- data/lib/active_support/subscriber.rb +74 -24
- data/lib/active_support/tagged_logging.rb +44 -8
- data/lib/active_support/test_case.rb +94 -2
- data/lib/active_support/testing/assertions.rb +58 -20
- data/lib/active_support/testing/autorun.rb +2 -0
- data/lib/active_support/testing/constant_lookup.rb +2 -0
- data/lib/active_support/testing/declarative.rb +2 -0
- data/lib/active_support/testing/deprecation.rb +2 -1
- data/lib/active_support/testing/file_fixtures.rb +4 -0
- data/lib/active_support/testing/isolation.rb +4 -2
- data/lib/active_support/testing/method_call_assertions.rb +30 -1
- data/lib/active_support/testing/parallelization/server.rb +78 -0
- data/lib/active_support/testing/parallelization/worker.rb +100 -0
- data/lib/active_support/testing/parallelization.rb +51 -0
- data/lib/active_support/testing/setup_and_teardown.rb +12 -7
- data/lib/active_support/testing/stream.rb +3 -2
- data/lib/active_support/testing/tagged_logging.rb +2 -0
- data/lib/active_support/testing/time_helpers.rb +78 -13
- data/lib/active_support/time.rb +2 -0
- data/lib/active_support/time_with_zone.rb +113 -41
- data/lib/active_support/values/time_zone.rb +54 -25
- data/lib/active_support/version.rb +2 -0
- data/lib/active_support/xml_mini/jdom.rb +5 -4
- data/lib/active_support/xml_mini/libxml.rb +4 -2
- data/lib/active_support/xml_mini/libxmlsax.rb +6 -4
- data/lib/active_support/xml_mini/nokogiri.rb +4 -2
- data/lib/active_support/xml_mini/nokogirisax.rb +5 -3
- data/lib/active_support/xml_mini/rexml.rb +12 -3
- data/lib/active_support/xml_mini.rb +5 -11
- data/lib/active_support.rb +18 -13
- metadata +71 -32
- data/lib/active_support/core_ext/array/prepend_and_append.rb +0 -7
- data/lib/active_support/core_ext/hash/compact.rb +0 -27
- data/lib/active_support/core_ext/hash/transform_values.rb +0 -30
- data/lib/active_support/core_ext/kernel/agnostics.rb +0 -11
- data/lib/active_support/core_ext/module/reachable.rb +0 -8
- data/lib/active_support/core_ext/numeric/inquiry.rb +0 -26
- data/lib/active_support/core_ext/range/include_range.rb +0 -23
- data/lib/active_support/values/unicode_tables.dat +0 -0
data/lib/active_support/cache.rb
CHANGED
@@ -1,23 +1,28 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "zlib"
|
2
4
|
require "active_support/core_ext/array/extract_options"
|
3
5
|
require "active_support/core_ext/array/wrap"
|
6
|
+
require "active_support/core_ext/enumerable"
|
4
7
|
require "active_support/core_ext/module/attribute_accessors"
|
5
8
|
require "active_support/core_ext/numeric/bytes"
|
6
9
|
require "active_support/core_ext/numeric/time"
|
7
10
|
require "active_support/core_ext/object/to_param"
|
11
|
+
require "active_support/core_ext/object/try"
|
8
12
|
require "active_support/core_ext/string/inflections"
|
9
13
|
|
10
14
|
module ActiveSupport
|
11
15
|
# See ActiveSupport::Cache::Store for documentation.
|
12
16
|
module Cache
|
13
|
-
autoload :FileStore,
|
14
|
-
autoload :MemoryStore,
|
15
|
-
autoload :MemCacheStore,
|
16
|
-
autoload :NullStore,
|
17
|
+
autoload :FileStore, "active_support/cache/file_store"
|
18
|
+
autoload :MemoryStore, "active_support/cache/memory_store"
|
19
|
+
autoload :MemCacheStore, "active_support/cache/mem_cache_store"
|
20
|
+
autoload :NullStore, "active_support/cache/null_store"
|
21
|
+
autoload :RedisCacheStore, "active_support/cache/redis_cache_store"
|
17
22
|
|
18
23
|
# These options mean something to all cache implementations. Individual cache
|
19
24
|
# implementations may support additional options.
|
20
|
-
UNIVERSAL_OPTIONS = [:namespace, :compress, :compress_threshold, :expires_in, :race_condition_ttl]
|
25
|
+
UNIVERSAL_OPTIONS = [:namespace, :compress, :compress_threshold, :expires_in, :race_condition_ttl, :coder]
|
21
26
|
|
22
27
|
module Strategy
|
23
28
|
autoload :LocalCache, "active_support/cache/strategy/local_cache"
|
@@ -49,12 +54,19 @@ module ActiveSupport
|
|
49
54
|
#
|
50
55
|
# ActiveSupport::Cache.lookup_store(MyOwnCacheStore.new)
|
51
56
|
# # => returns MyOwnCacheStore.new
|
52
|
-
def lookup_store(*
|
53
|
-
store, *parameters = *Array.wrap(store_option).flatten
|
54
|
-
|
57
|
+
def lookup_store(store = nil, *parameters)
|
55
58
|
case store
|
56
59
|
when Symbol
|
57
|
-
|
60
|
+
options = parameters.extract_options!
|
61
|
+
# clean this up once Ruby 2.7 support is dropped
|
62
|
+
# see https://github.com/rails/rails/pull/41522#discussion_r581186602
|
63
|
+
if options.empty?
|
64
|
+
retrieve_store_class(store).new(*parameters)
|
65
|
+
else
|
66
|
+
retrieve_store_class(store).new(*parameters, **options)
|
67
|
+
end
|
68
|
+
when Array
|
69
|
+
lookup_store(*store)
|
58
70
|
when nil
|
59
71
|
ActiveSupport::Cache::MemoryStore.new
|
60
72
|
else
|
@@ -75,7 +87,7 @@ module ActiveSupport
|
|
75
87
|
#
|
76
88
|
# The +key+ argument can also respond to +cache_key+ or +to_param+.
|
77
89
|
def expand_cache_key(key, namespace = nil)
|
78
|
-
expanded_cache_key = namespace ? "#{namespace}/" : ""
|
90
|
+
expanded_cache_key = namespace ? +"#{namespace}/" : +""
|
79
91
|
|
80
92
|
if prefix = ENV["RAILS_CACHE_ID"] || ENV["RAILS_APP_VERSION"]
|
81
93
|
expanded_cache_key << "#{prefix}/"
|
@@ -88,16 +100,19 @@ module ActiveSupport
|
|
88
100
|
private
|
89
101
|
def retrieve_cache_key(key)
|
90
102
|
case
|
91
|
-
when key.respond_to?(:
|
92
|
-
when key.
|
93
|
-
when key.
|
94
|
-
|
103
|
+
when key.respond_to?(:cache_key_with_version) then key.cache_key_with_version
|
104
|
+
when key.respond_to?(:cache_key) then key.cache_key
|
105
|
+
when key.is_a?(Array) then key.map { |element| retrieve_cache_key(element) }.to_param
|
106
|
+
when key.respond_to?(:to_a) then retrieve_cache_key(key.to_a)
|
107
|
+
else key.to_param
|
95
108
|
end.to_s
|
96
109
|
end
|
97
110
|
|
98
111
|
# Obtains the specified cache store class, given the name of the +store+.
|
99
112
|
# Raises an error when the store class cannot be found.
|
100
113
|
def retrieve_store_class(store)
|
114
|
+
# require_relative cannot be used here because the class might be
|
115
|
+
# provided by another gem, like redis-activesupport for example.
|
101
116
|
require "active_support/cache/#{store}"
|
102
117
|
rescue LoadError => e
|
103
118
|
raise "Could not find cache store adapter for #{store} (#{e})"
|
@@ -143,23 +158,42 @@ module ActiveSupport
|
|
143
158
|
# cache.namespace = -> { @last_mod_time } # Set the namespace to a variable
|
144
159
|
# @last_mod_time = Time.now # Invalidate the entire cache by changing namespace
|
145
160
|
#
|
146
|
-
#
|
147
|
-
#
|
148
|
-
#
|
149
|
-
# <tt
|
150
|
-
#
|
151
|
-
# <tt>:compress_threshold</tt> option. The default threshold is 16K.
|
161
|
+
# Cached data larger than 1kB are compressed by default. To turn off
|
162
|
+
# compression, pass <tt>compress: false</tt> to the initializer or to
|
163
|
+
# individual +fetch+ or +write+ method calls. The 1kB compression
|
164
|
+
# threshold is configurable with the <tt>:compress_threshold</tt> option,
|
165
|
+
# specified in bytes.
|
152
166
|
class Store
|
167
|
+
DEFAULT_CODER = Marshal
|
168
|
+
|
153
169
|
cattr_accessor :logger, instance_writer: true
|
154
170
|
|
155
171
|
attr_reader :silence, :options
|
156
172
|
alias :silence? :silence
|
157
173
|
|
174
|
+
class << self
|
175
|
+
private
|
176
|
+
def retrieve_pool_options(options)
|
177
|
+
{}.tap do |pool_options|
|
178
|
+
pool_options[:size] = options.delete(:pool_size) if options[:pool_size]
|
179
|
+
pool_options[:timeout] = options.delete(:pool_timeout) if options[:pool_timeout]
|
180
|
+
end
|
181
|
+
end
|
182
|
+
|
183
|
+
def ensure_connection_pool_added!
|
184
|
+
require "connection_pool"
|
185
|
+
rescue LoadError => e
|
186
|
+
$stderr.puts "You don't have connection_pool installed in your application. Please add it to your Gemfile and run bundle install"
|
187
|
+
raise e
|
188
|
+
end
|
189
|
+
end
|
190
|
+
|
158
191
|
# Creates a new cache. The options will be passed to any write method calls
|
159
192
|
# except for <tt>:namespace</tt> which can be used to set the global
|
160
193
|
# namespace for the cache.
|
161
194
|
def initialize(options = nil)
|
162
195
|
@options = options ? options.dup : {}
|
196
|
+
@coder = @options.delete(:coder) { self.class::DEFAULT_CODER } || NullCoder
|
163
197
|
end
|
164
198
|
|
165
199
|
# Silences the logger.
|
@@ -207,8 +241,15 @@ module ActiveSupport
|
|
207
241
|
# ask whether you should force a cache write. Otherwise, it's clearer to
|
208
242
|
# just call <tt>Cache#write</tt>.
|
209
243
|
#
|
210
|
-
# Setting <tt
|
211
|
-
#
|
244
|
+
# Setting <tt>skip_nil: true</tt> will not cache nil result:
|
245
|
+
#
|
246
|
+
# cache.fetch('foo') { nil }
|
247
|
+
# cache.fetch('bar', skip_nil: true) { nil }
|
248
|
+
# cache.exist?('foo') # => true
|
249
|
+
# cache.exist?('bar') # => false
|
250
|
+
#
|
251
|
+
#
|
252
|
+
# Setting <tt>compress: false</tt> disables compression of the cache entry.
|
212
253
|
#
|
213
254
|
# Setting <tt>:expires_in</tt> will set an expiration time on the cache.
|
214
255
|
# All caches support auto-expiring content after a specified number of
|
@@ -219,6 +260,10 @@ module ActiveSupport
|
|
219
260
|
# cache = ActiveSupport::Cache::MemoryStore.new(expires_in: 5.minutes)
|
220
261
|
# cache.write(key, value, expires_in: 1.minute) # Set a lower value for one entry
|
221
262
|
#
|
263
|
+
# Setting <tt>:version</tt> verifies the cache stored under <tt>name</tt>
|
264
|
+
# is of the same version. nil is returned on mismatches despite contents.
|
265
|
+
# This feature is used to support recyclable cache keys.
|
266
|
+
#
|
222
267
|
# Setting <tt>:race_condition_ttl</tt> is very useful in situations where
|
223
268
|
# a cache entry is used very frequently and is under heavy load. If a
|
224
269
|
# cache expires and due to heavy load several different processes will try
|
@@ -278,15 +323,16 @@ module ActiveSupport
|
|
278
323
|
# :bar
|
279
324
|
# end
|
280
325
|
# cache.fetch('foo') # => "bar"
|
281
|
-
def fetch(name, options = nil)
|
326
|
+
def fetch(name, options = nil, &block)
|
282
327
|
if block_given?
|
283
328
|
options = merged_options(options)
|
284
329
|
key = normalize_key(name, options)
|
285
330
|
|
286
331
|
entry = nil
|
287
332
|
instrument(:read, name, options) do |payload|
|
288
|
-
cached_entry = read_entry(key, options) unless options[:force]
|
333
|
+
cached_entry = read_entry(key, **options, event: payload) unless options[:force]
|
289
334
|
entry = handle_expired_entry(cached_entry, key, options)
|
335
|
+
entry = nil if entry && entry.mismatched?(normalize_version(name, options))
|
290
336
|
payload[:super_operation] = :fetch if payload
|
291
337
|
payload[:hit] = !!entry if payload
|
292
338
|
end
|
@@ -294,7 +340,7 @@ module ActiveSupport
|
|
294
340
|
if entry
|
295
341
|
get_entry_value(entry, name, options)
|
296
342
|
else
|
297
|
-
save_block_result_to_cache(name, options)
|
343
|
+
save_block_result_to_cache(name, options, &block)
|
298
344
|
end
|
299
345
|
elsif options && options[:force]
|
300
346
|
raise ArgumentError, "Missing block: Calling `Cache#fetch` with `force: true` requires a block."
|
@@ -303,19 +349,29 @@ module ActiveSupport
|
|
303
349
|
end
|
304
350
|
end
|
305
351
|
|
306
|
-
#
|
352
|
+
# Reads data from the cache, using the given key. If there is data in
|
307
353
|
# the cache with the given key, then that data is returned. Otherwise,
|
308
354
|
# +nil+ is returned.
|
309
355
|
#
|
356
|
+
# Note, if data was written with the <tt>:expires_in</tt> or
|
357
|
+
# <tt>:version</tt> options, both of these conditions are applied before
|
358
|
+
# the data is returned.
|
359
|
+
#
|
310
360
|
# Options are passed to the underlying cache implementation.
|
311
361
|
def read(name, options = nil)
|
312
362
|
options = merged_options(options)
|
313
|
-
key
|
363
|
+
key = normalize_key(name, options)
|
364
|
+
version = normalize_version(name, options)
|
365
|
+
|
314
366
|
instrument(:read, name, options) do |payload|
|
315
|
-
entry = read_entry(key, options)
|
367
|
+
entry = read_entry(key, **options, event: payload)
|
368
|
+
|
316
369
|
if entry
|
317
370
|
if entry.expired?
|
318
|
-
delete_entry(key, options)
|
371
|
+
delete_entry(key, **options)
|
372
|
+
payload[:hit] = false if payload
|
373
|
+
nil
|
374
|
+
elsif entry.mismatched?(version)
|
319
375
|
payload[:hit] = false if payload
|
320
376
|
nil
|
321
377
|
else
|
@@ -339,19 +395,24 @@ module ActiveSupport
|
|
339
395
|
options = names.extract_options!
|
340
396
|
options = merged_options(options)
|
341
397
|
|
342
|
-
|
343
|
-
|
344
|
-
|
345
|
-
|
346
|
-
|
347
|
-
|
348
|
-
|
349
|
-
|
350
|
-
|
351
|
-
|
398
|
+
instrument :read_multi, names, options do |payload|
|
399
|
+
read_multi_entries(names, **options, event: payload).tap do |results|
|
400
|
+
payload[:hits] = results.keys
|
401
|
+
end
|
402
|
+
end
|
403
|
+
end
|
404
|
+
|
405
|
+
# Cache Storage API to write multiple values at once.
|
406
|
+
def write_multi(hash, options = nil)
|
407
|
+
options = merged_options(options)
|
408
|
+
|
409
|
+
instrument :write_multi, hash, options do |payload|
|
410
|
+
entries = hash.each_with_object({}) do |(name, value), memo|
|
411
|
+
memo[normalize_key(name, options)] = Entry.new(value, **options.merge(version: normalize_version(name, options)))
|
352
412
|
end
|
413
|
+
|
414
|
+
write_multi_entries entries, **options
|
353
415
|
end
|
354
|
-
results
|
355
416
|
end
|
356
417
|
|
357
418
|
# Fetches data from the cache, using the given keys. If there is data in
|
@@ -362,8 +423,6 @@ module ActiveSupport
|
|
362
423
|
# to the cache. If you do not want to write the cache when the cache is
|
363
424
|
# not found, use #read_multi.
|
364
425
|
#
|
365
|
-
# Options are passed to the underlying cache implementation.
|
366
|
-
#
|
367
426
|
# Returns a hash with the data for each of the names. For example:
|
368
427
|
#
|
369
428
|
# cache.write("bim", "bam")
|
@@ -373,19 +432,36 @@ module ActiveSupport
|
|
373
432
|
# # => { "bim" => "bam",
|
374
433
|
# # "unknown_key" => "Fallback value for key: unknown_key" }
|
375
434
|
#
|
435
|
+
# Options are passed to the underlying cache implementation. For example:
|
436
|
+
#
|
437
|
+
# cache.fetch_multi("fizz", expires_in: 5.seconds) do |key|
|
438
|
+
# "buzz"
|
439
|
+
# end
|
440
|
+
# # => {"fizz"=>"buzz"}
|
441
|
+
# cache.read("fizz")
|
442
|
+
# # => "buzz"
|
443
|
+
# sleep(6)
|
444
|
+
# cache.read("fizz")
|
445
|
+
# # => nil
|
376
446
|
def fetch_multi(*names)
|
377
447
|
raise ArgumentError, "Missing block: `Cache#fetch_multi` requires a block." unless block_given?
|
378
448
|
|
379
449
|
options = names.extract_options!
|
380
450
|
options = merged_options(options)
|
381
|
-
results = read_multi(*names, options)
|
382
451
|
|
383
|
-
names
|
384
|
-
|
385
|
-
|
386
|
-
|
387
|
-
|
452
|
+
instrument :read_multi, names, options do |payload|
|
453
|
+
reads = read_multi_entries(names, **options)
|
454
|
+
writes = {}
|
455
|
+
ordered = names.index_with do |name|
|
456
|
+
reads.fetch(name) { writes[name] = yield(name) }
|
388
457
|
end
|
458
|
+
|
459
|
+
payload[:hits] = reads.keys
|
460
|
+
payload[:super_operation] = :fetch_multi
|
461
|
+
|
462
|
+
write_multi(writes, options)
|
463
|
+
|
464
|
+
ordered
|
389
465
|
end
|
390
466
|
end
|
391
467
|
|
@@ -396,8 +472,8 @@ module ActiveSupport
|
|
396
472
|
options = merged_options(options)
|
397
473
|
|
398
474
|
instrument(:write, name, options) do
|
399
|
-
entry = Entry.new(value, options)
|
400
|
-
write_entry(normalize_key(name, options), entry, options)
|
475
|
+
entry = Entry.new(value, **options.merge(version: normalize_version(name, options)))
|
476
|
+
write_entry(normalize_key(name, options), entry, **options)
|
401
477
|
end
|
402
478
|
end
|
403
479
|
|
@@ -408,7 +484,19 @@ module ActiveSupport
|
|
408
484
|
options = merged_options(options)
|
409
485
|
|
410
486
|
instrument(:delete, name) do
|
411
|
-
delete_entry(normalize_key(name, options), options)
|
487
|
+
delete_entry(normalize_key(name, options), **options)
|
488
|
+
end
|
489
|
+
end
|
490
|
+
|
491
|
+
# Deletes multiple entries in the cache.
|
492
|
+
#
|
493
|
+
# Options are passed to the underlying cache implementation.
|
494
|
+
def delete_multi(names, options = nil)
|
495
|
+
options = merged_options(options)
|
496
|
+
names.map! { |key| normalize_key(key, options) }
|
497
|
+
|
498
|
+
instrument :delete_multi, names do
|
499
|
+
delete_multi_entries(names, **options)
|
412
500
|
end
|
413
501
|
end
|
414
502
|
|
@@ -418,9 +506,9 @@ module ActiveSupport
|
|
418
506
|
def exist?(name, options = nil)
|
419
507
|
options = merged_options(options)
|
420
508
|
|
421
|
-
instrument(:exist?, name) do
|
422
|
-
entry = read_entry(normalize_key(name, options), options)
|
423
|
-
(entry && !entry.expired?) || false
|
509
|
+
instrument(:exist?, name) do |payload|
|
510
|
+
entry = read_entry(normalize_key(name, options), **options, event: payload)
|
511
|
+
(entry && !entry.expired? && !entry.mismatched?(normalize_version(name, options))) || false
|
424
512
|
end
|
425
513
|
end
|
426
514
|
|
@@ -428,7 +516,7 @@ module ActiveSupport
|
|
428
516
|
#
|
429
517
|
# Options are passed to the underlying cache implementation.
|
430
518
|
#
|
431
|
-
#
|
519
|
+
# Some implementations may not support this method.
|
432
520
|
def delete_matched(matcher, options = nil)
|
433
521
|
raise NotImplementedError.new("#{self.class.name} does not support delete_matched")
|
434
522
|
end
|
@@ -437,7 +525,7 @@ module ActiveSupport
|
|
437
525
|
#
|
438
526
|
# Options are passed to the underlying cache implementation.
|
439
527
|
#
|
440
|
-
#
|
528
|
+
# Some implementations may not support this method.
|
441
529
|
def increment(name, amount = 1, options = nil)
|
442
530
|
raise NotImplementedError.new("#{self.class.name} does not support increment")
|
443
531
|
end
|
@@ -446,7 +534,7 @@ module ActiveSupport
|
|
446
534
|
#
|
447
535
|
# Options are passed to the underlying cache implementation.
|
448
536
|
#
|
449
|
-
#
|
537
|
+
# Some implementations may not support this method.
|
450
538
|
def decrement(name, amount = 1, options = nil)
|
451
539
|
raise NotImplementedError.new("#{self.class.name} does not support decrement")
|
452
540
|
end
|
@@ -455,7 +543,7 @@ module ActiveSupport
|
|
455
543
|
#
|
456
544
|
# Options are passed to the underlying cache implementation.
|
457
545
|
#
|
458
|
-
#
|
546
|
+
# Some implementations may not support this method.
|
459
547
|
def cleanup(options = nil)
|
460
548
|
raise NotImplementedError.new("#{self.class.name} does not support cleanup")
|
461
549
|
end
|
@@ -465,7 +553,7 @@ module ActiveSupport
|
|
465
553
|
#
|
466
554
|
# The options hash is passed to the underlying cache implementation.
|
467
555
|
#
|
468
|
-
#
|
556
|
+
# Some implementations may not support this method.
|
469
557
|
def clear(options = nil)
|
470
558
|
raise NotImplementedError.new("#{self.class.name} does not support clear")
|
471
559
|
end
|
@@ -492,28 +580,107 @@ module ActiveSupport
|
|
492
580
|
|
493
581
|
# Reads an entry from the cache implementation. Subclasses must implement
|
494
582
|
# this method.
|
495
|
-
def read_entry(key, options)
|
583
|
+
def read_entry(key, **options)
|
496
584
|
raise NotImplementedError.new
|
497
585
|
end
|
498
586
|
|
499
587
|
# Writes an entry to the cache implementation. Subclasses must implement
|
500
588
|
# this method.
|
501
|
-
def write_entry(key, entry, options)
|
589
|
+
def write_entry(key, entry, **options)
|
502
590
|
raise NotImplementedError.new
|
503
591
|
end
|
504
592
|
|
593
|
+
def serialize_entry(entry)
|
594
|
+
@coder.dump(entry)
|
595
|
+
end
|
596
|
+
|
597
|
+
def deserialize_entry(payload)
|
598
|
+
payload.nil? ? nil : @coder.load(payload)
|
599
|
+
end
|
600
|
+
|
601
|
+
# Reads multiple entries from the cache implementation. Subclasses MAY
|
602
|
+
# implement this method.
|
603
|
+
def read_multi_entries(names, **options)
|
604
|
+
names.each_with_object({}) do |name, results|
|
605
|
+
key = normalize_key(name, options)
|
606
|
+
entry = read_entry(key, **options)
|
607
|
+
|
608
|
+
next unless entry
|
609
|
+
|
610
|
+
version = normalize_version(name, options)
|
611
|
+
|
612
|
+
if entry.expired?
|
613
|
+
delete_entry(key, **options)
|
614
|
+
elsif !entry.mismatched?(version)
|
615
|
+
results[name] = entry.value
|
616
|
+
end
|
617
|
+
end
|
618
|
+
end
|
619
|
+
|
620
|
+
# Writes multiple entries to the cache implementation. Subclasses MAY
|
621
|
+
# implement this method.
|
622
|
+
def write_multi_entries(hash, **options)
|
623
|
+
hash.each do |key, entry|
|
624
|
+
write_entry key, entry, **options
|
625
|
+
end
|
626
|
+
end
|
627
|
+
|
505
628
|
# Deletes an entry from the cache implementation. Subclasses must
|
506
629
|
# implement this method.
|
507
|
-
def delete_entry(key, options)
|
630
|
+
def delete_entry(key, **options)
|
508
631
|
raise NotImplementedError.new
|
509
632
|
end
|
510
633
|
|
634
|
+
# Deletes multiples entries in the cache implementation. Subclasses MAY
|
635
|
+
# implement this method.
|
636
|
+
def delete_multi_entries(entries, **options)
|
637
|
+
entries.count { |key| delete_entry(key, **options) }
|
638
|
+
end
|
639
|
+
|
511
640
|
# Merges the default options with ones specific to a method call.
|
512
641
|
def merged_options(call_options)
|
513
642
|
if call_options
|
514
|
-
options.
|
643
|
+
if options.empty?
|
644
|
+
call_options
|
645
|
+
else
|
646
|
+
options.merge(call_options)
|
647
|
+
end
|
515
648
|
else
|
516
|
-
options
|
649
|
+
options
|
650
|
+
end
|
651
|
+
end
|
652
|
+
|
653
|
+
# Expands and namespaces the cache key. May be overridden by
|
654
|
+
# cache stores to do additional normalization.
|
655
|
+
def normalize_key(key, options = nil)
|
656
|
+
namespace_key expanded_key(key), options
|
657
|
+
end
|
658
|
+
|
659
|
+
# Prefix the key with a namespace string:
|
660
|
+
#
|
661
|
+
# namespace_key 'foo', namespace: 'cache'
|
662
|
+
# # => 'cache:foo'
|
663
|
+
#
|
664
|
+
# With a namespace block:
|
665
|
+
#
|
666
|
+
# namespace_key 'foo', namespace: -> { 'cache' }
|
667
|
+
# # => 'cache:foo'
|
668
|
+
def namespace_key(key, options = nil)
|
669
|
+
options = merged_options(options)
|
670
|
+
namespace = options[:namespace]
|
671
|
+
|
672
|
+
if namespace.respond_to?(:call)
|
673
|
+
namespace = namespace.call
|
674
|
+
end
|
675
|
+
|
676
|
+
if key && key.encoding != Encoding::UTF_8
|
677
|
+
key = key.dup.force_encoding(Encoding::UTF_8)
|
678
|
+
end
|
679
|
+
|
680
|
+
if namespace
|
681
|
+
"#{namespace}:#{key}"
|
682
|
+
else
|
683
|
+
key
|
517
684
|
end
|
518
685
|
end
|
519
686
|
|
@@ -526,40 +693,39 @@ module ActiveSupport
|
|
526
693
|
case key
|
527
694
|
when Array
|
528
695
|
if key.size > 1
|
529
|
-
key
|
696
|
+
key.collect { |element| expanded_key(element) }
|
530
697
|
else
|
531
|
-
key
|
698
|
+
expanded_key(key.first)
|
532
699
|
end
|
533
700
|
when Hash
|
534
|
-
key
|
535
|
-
|
701
|
+
key.collect { |k, v| "#{k}=#{v}" }.sort!
|
702
|
+
else
|
703
|
+
key
|
704
|
+
end.to_param
|
705
|
+
end
|
536
706
|
|
537
|
-
|
707
|
+
def normalize_version(key, options = nil)
|
708
|
+
(options && options[:version].try(:to_param)) || expanded_version(key)
|
538
709
|
end
|
539
710
|
|
540
|
-
|
541
|
-
|
542
|
-
|
543
|
-
key
|
544
|
-
|
545
|
-
|
546
|
-
key = "#{prefix}:#{key}" if prefix
|
547
|
-
key
|
711
|
+
def expanded_version(key)
|
712
|
+
case
|
713
|
+
when key.respond_to?(:cache_version) then key.cache_version.to_param
|
714
|
+
when key.is_a?(Array) then key.map { |element| expanded_version(element) }.tap(&:compact!).to_param
|
715
|
+
when key.respond_to?(:to_a) then expanded_version(key.to_a)
|
716
|
+
end
|
548
717
|
end
|
549
718
|
|
550
719
|
def instrument(operation, key, options = nil)
|
551
|
-
|
720
|
+
if logger && logger.debug? && !silence?
|
721
|
+
logger.debug "Cache #{operation}: #{normalize_key(key, options)}#{options.blank? ? "" : " (#{options.inspect})"}"
|
722
|
+
end
|
552
723
|
|
553
|
-
payload = { key: key }
|
724
|
+
payload = { key: key, store: self.class.name }
|
554
725
|
payload.merge!(options) if options.is_a?(Hash)
|
555
726
|
ActiveSupport::Notifications.instrument("cache_#{operation}.active_support", payload) { yield(payload) }
|
556
727
|
end
|
557
728
|
|
558
|
-
def log
|
559
|
-
return unless logger && logger.debug? && !silence?
|
560
|
-
logger.debug(yield)
|
561
|
-
end
|
562
|
-
|
563
729
|
def handle_expired_entry(entry, key, options)
|
564
730
|
if entry && entry.expired?
|
565
731
|
race_ttl = options[:race_condition_ttl].to_i
|
@@ -569,7 +735,7 @@ module ActiveSupport
|
|
569
735
|
entry.expires_at = Time.now + race_ttl
|
570
736
|
write_entry(key, entry, expires_in: race_ttl * 2)
|
571
737
|
else
|
572
|
-
delete_entry(key, options)
|
738
|
+
delete_entry(key, **options)
|
573
739
|
end
|
574
740
|
entry = nil
|
575
741
|
end
|
@@ -577,7 +743,7 @@ module ActiveSupport
|
|
577
743
|
end
|
578
744
|
|
579
745
|
def get_entry_value(entry, name, options)
|
580
|
-
instrument(:fetch_hit, name, options) {}
|
746
|
+
instrument(:fetch_hit, name, options) { }
|
581
747
|
entry.value
|
582
748
|
end
|
583
749
|
|
@@ -586,39 +752,54 @@ module ActiveSupport
|
|
586
752
|
yield(name)
|
587
753
|
end
|
588
754
|
|
589
|
-
write(name, result, options)
|
755
|
+
write(name, result, options) unless result.nil? && options[:skip_nil]
|
590
756
|
result
|
591
757
|
end
|
592
758
|
end
|
593
759
|
|
594
|
-
|
595
|
-
|
596
|
-
|
760
|
+
module NullCoder # :nodoc:
|
761
|
+
class << self
|
762
|
+
def load(payload)
|
763
|
+
payload
|
764
|
+
end
|
765
|
+
|
766
|
+
def dump(entry)
|
767
|
+
entry
|
768
|
+
end
|
769
|
+
end
|
770
|
+
end
|
771
|
+
|
772
|
+
# This class is used to represent cache entries. Cache entries have a value, an optional
|
773
|
+
# expiration time, and an optional version. The expiration time is used to support the :race_condition_ttl option
|
774
|
+
# on the cache. The version is used to support the :version option on the cache for rejecting
|
775
|
+
# mismatches.
|
597
776
|
#
|
598
777
|
# Since cache entries in most instances will be serialized, the internals of this class are highly optimized
|
599
778
|
# using short instance variable names that are lazily defined.
|
600
779
|
class Entry # :nodoc:
|
601
|
-
|
780
|
+
attr_reader :version
|
602
781
|
|
603
|
-
|
604
|
-
# +:compress+, +:compress_threshold+, and +:expires_in+.
|
605
|
-
def initialize(value, options = {})
|
606
|
-
if should_compress?(value, options)
|
607
|
-
@value = compress(value)
|
608
|
-
@compressed = true
|
609
|
-
else
|
610
|
-
@value = value
|
611
|
-
end
|
782
|
+
DEFAULT_COMPRESS_LIMIT = 1.kilobyte
|
612
783
|
|
784
|
+
# Creates a new cache entry for the specified value. Options supported are
|
785
|
+
# +:compress+, +:compress_threshold+, +:version+ and +:expires_in+.
|
786
|
+
def initialize(value, compress: true, compress_threshold: DEFAULT_COMPRESS_LIMIT, version: nil, expires_in: nil, **)
|
787
|
+
@value = value
|
788
|
+
@version = version
|
613
789
|
@created_at = Time.now.to_f
|
614
|
-
@expires_in =
|
615
|
-
|
790
|
+
@expires_in = expires_in && expires_in.to_f
|
791
|
+
|
792
|
+
compress!(compress_threshold) if compress
|
616
793
|
end
|
617
794
|
|
618
795
|
def value
|
619
796
|
compressed? ? uncompress(@value) : @value
|
620
797
|
end
|
621
798
|
|
799
|
+
def mismatched?(version)
|
800
|
+
@version && version && @version != version
|
801
|
+
end
|
802
|
+
|
622
803
|
# Checks if the entry is expired. The +expires_in+ parameter can override
|
623
804
|
# the value set when the entry was created.
|
624
805
|
def expired?
|
@@ -638,19 +819,15 @@ module ActiveSupport
|
|
638
819
|
end
|
639
820
|
|
640
821
|
# Returns the size of the cached value. This could be less than
|
641
|
-
# <tt>value.
|
642
|
-
def
|
643
|
-
|
644
|
-
|
822
|
+
# <tt>value.bytesize</tt> if the data is compressed.
|
823
|
+
def bytesize
|
824
|
+
case value
|
825
|
+
when NilClass
|
826
|
+
0
|
827
|
+
when String
|
828
|
+
@value.bytesize
|
645
829
|
else
|
646
|
-
|
647
|
-
when NilClass
|
648
|
-
0
|
649
|
-
when String
|
650
|
-
@value.bytesize
|
651
|
-
else
|
652
|
-
@s = Marshal.dump(@value).bytesize
|
653
|
-
end
|
830
|
+
@s ||= Marshal.dump(@value).bytesize
|
654
831
|
end
|
655
832
|
end
|
656
833
|
|
@@ -667,23 +844,30 @@ module ActiveSupport
|
|
667
844
|
end
|
668
845
|
|
669
846
|
private
|
670
|
-
def
|
671
|
-
|
672
|
-
|
673
|
-
|
674
|
-
|
675
|
-
|
847
|
+
def compress!(compress_threshold)
|
848
|
+
case @value
|
849
|
+
when nil, true, false, Numeric
|
850
|
+
uncompressed_size = 0
|
851
|
+
when String
|
852
|
+
uncompressed_size = @value.bytesize
|
853
|
+
else
|
854
|
+
serialized = Marshal.dump(@value)
|
855
|
+
uncompressed_size = serialized.bytesize
|
676
856
|
end
|
677
857
|
|
678
|
-
|
679
|
-
|
858
|
+
if uncompressed_size >= compress_threshold
|
859
|
+
serialized ||= Marshal.dump(@value)
|
860
|
+
compressed = Zlib::Deflate.deflate(serialized)
|
680
861
|
|
681
|
-
|
682
|
-
|
862
|
+
if compressed.bytesize < uncompressed_size
|
863
|
+
@value = compressed
|
864
|
+
@compressed = true
|
865
|
+
end
|
866
|
+
end
|
683
867
|
end
|
684
868
|
|
685
|
-
def
|
686
|
-
|
869
|
+
def compressed?
|
870
|
+
defined?(@compressed)
|
687
871
|
end
|
688
872
|
|
689
873
|
def uncompress(value)
|