activesupport 5.2.4.3 → 7.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of activesupport might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/CHANGELOG.md +244 -459
- data/MIT-LICENSE +1 -1
- data/README.rdoc +4 -3
- data/lib/active_support/actionable_error.rb +48 -0
- data/lib/active_support/array_inquirer.rb +2 -2
- data/lib/active_support/backtrace_cleaner.rb +31 -5
- data/lib/active_support/benchmarkable.rb +3 -3
- data/lib/active_support/cache/file_store.rb +47 -41
- data/lib/active_support/cache/mem_cache_store.rb +151 -40
- data/lib/active_support/cache/memory_store.rb +68 -34
- data/lib/active_support/cache/null_store.rb +16 -3
- data/lib/active_support/cache/redis_cache_store.rb +103 -101
- data/lib/active_support/cache/strategy/local_cache.rb +56 -64
- data/lib/active_support/cache.rb +333 -116
- data/lib/active_support/callbacks.rb +244 -128
- data/lib/active_support/code_generator.rb +65 -0
- data/lib/active_support/concern.rb +72 -5
- data/lib/active_support/concurrency/load_interlock_aware_monitor.rb +16 -0
- data/lib/active_support/concurrency/share_lock.rb +2 -3
- data/lib/active_support/configurable.rb +15 -16
- data/lib/active_support/configuration_file.rb +51 -0
- data/lib/active_support/core_ext/array/access.rb +15 -7
- data/lib/active_support/core_ext/array/conversions.rb +18 -17
- data/lib/active_support/core_ext/array/deprecated_conversions.rb +25 -0
- data/lib/active_support/core_ext/array/extract.rb +21 -0
- data/lib/active_support/core_ext/array/grouping.rb +6 -6
- data/lib/active_support/core_ext/array/inquiry.rb +2 -2
- data/lib/active_support/core_ext/array.rb +2 -1
- data/lib/active_support/core_ext/benchmark.rb +2 -2
- data/lib/active_support/core_ext/big_decimal/conversions.rb +1 -1
- data/lib/active_support/core_ext/class/attribute.rb +32 -47
- data/lib/active_support/core_ext/class/subclasses.rb +9 -22
- data/lib/active_support/core_ext/date/blank.rb +1 -1
- data/lib/active_support/core_ext/date/calculations.rb +15 -14
- data/lib/active_support/core_ext/date/conversions.rb +16 -15
- data/lib/active_support/core_ext/date/deprecated_conversions.rb +26 -0
- data/lib/active_support/core_ext/date.rb +1 -0
- data/lib/active_support/core_ext/date_and_time/calculations.rb +41 -51
- data/lib/active_support/core_ext/date_and_time/compatibility.rb +15 -0
- data/lib/active_support/core_ext/date_and_time/zones.rb +0 -1
- data/lib/active_support/core_ext/date_time/blank.rb +1 -1
- data/lib/active_support/core_ext/date_time/calculations.rb +1 -1
- data/lib/active_support/core_ext/date_time/conversions.rb +13 -14
- data/lib/active_support/core_ext/date_time/deprecated_conversions.rb +22 -0
- data/lib/active_support/core_ext/date_time.rb +1 -0
- data/lib/active_support/core_ext/digest/uuid.rb +39 -13
- data/lib/active_support/core_ext/enumerable.rb +241 -76
- data/lib/active_support/core_ext/file/atomic.rb +3 -1
- data/lib/active_support/core_ext/hash/conversions.rb +3 -4
- data/lib/active_support/core_ext/hash/deep_transform_values.rb +46 -0
- data/lib/active_support/core_ext/hash/except.rb +2 -2
- data/lib/active_support/core_ext/hash/indifferent_access.rb +3 -3
- data/lib/active_support/core_ext/hash/keys.rb +2 -31
- data/lib/active_support/core_ext/hash/slice.rb +6 -27
- data/lib/active_support/core_ext/hash.rb +1 -2
- data/lib/active_support/core_ext/integer/multiple.rb +1 -1
- data/lib/active_support/core_ext/kernel/reporting.rb +4 -4
- data/lib/active_support/core_ext/kernel/singleton_class.rb +1 -1
- data/lib/active_support/core_ext/kernel.rb +0 -1
- data/lib/active_support/core_ext/load_error.rb +1 -1
- data/lib/active_support/core_ext/module/attr_internal.rb +2 -2
- data/lib/active_support/core_ext/module/attribute_accessors.rb +32 -39
- data/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb +35 -28
- data/lib/active_support/core_ext/module/concerning.rb +8 -2
- data/lib/active_support/core_ext/module/delegation.rb +70 -33
- data/lib/active_support/core_ext/module/introspection.rb +16 -15
- data/lib/active_support/core_ext/module/redefine_method.rb +8 -17
- data/lib/active_support/core_ext/module.rb +0 -1
- data/lib/active_support/core_ext/name_error.rb +23 -2
- data/lib/active_support/core_ext/numeric/conversions.rb +132 -129
- data/lib/active_support/core_ext/numeric/deprecated_conversions.rb +60 -0
- data/lib/active_support/core_ext/numeric.rb +1 -1
- data/lib/active_support/core_ext/object/acts_like.rb +29 -5
- data/lib/active_support/core_ext/object/blank.rb +3 -4
- data/lib/active_support/core_ext/object/deep_dup.rb +1 -1
- data/lib/active_support/core_ext/object/duplicable.rb +14 -110
- data/lib/active_support/core_ext/object/json.rb +44 -27
- data/lib/active_support/core_ext/object/to_query.rb +2 -2
- data/lib/active_support/core_ext/object/try.rb +24 -14
- data/lib/active_support/core_ext/object/with_options.rb +21 -2
- data/lib/active_support/core_ext/pathname/existence.rb +21 -0
- data/lib/active_support/core_ext/pathname.rb +3 -0
- data/lib/active_support/core_ext/range/compare_range.rb +23 -27
- data/lib/active_support/core_ext/range/conversions.rb +32 -30
- data/lib/active_support/core_ext/range/deprecated_conversions.rb +26 -0
- data/lib/active_support/core_ext/range/each.rb +1 -2
- data/lib/active_support/core_ext/range/include_time_with_zone.rb +4 -20
- data/lib/active_support/core_ext/range/overlaps.rb +1 -1
- data/lib/active_support/core_ext/range.rb +1 -1
- data/lib/active_support/core_ext/regexp.rb +8 -5
- data/lib/active_support/core_ext/securerandom.rb +23 -3
- data/lib/active_support/core_ext/string/access.rb +5 -16
- data/lib/active_support/core_ext/string/conversions.rb +3 -2
- data/lib/active_support/core_ext/string/filters.rb +42 -1
- data/lib/active_support/core_ext/string/inflections.rb +46 -7
- data/lib/active_support/core_ext/string/inquiry.rb +2 -1
- data/lib/active_support/core_ext/string/multibyte.rb +6 -5
- data/lib/active_support/core_ext/string/output_safety.rb +129 -20
- data/lib/active_support/core_ext/string/starts_ends_with.rb +2 -2
- data/lib/active_support/core_ext/string/strip.rb +3 -1
- data/lib/active_support/core_ext/symbol/starts_ends_with.rb +6 -0
- data/lib/active_support/core_ext/symbol.rb +3 -0
- data/lib/active_support/core_ext/time/calculations.rb +59 -10
- data/lib/active_support/core_ext/time/conversions.rb +15 -12
- data/lib/active_support/core_ext/time/deprecated_conversions.rb +22 -0
- data/lib/active_support/core_ext/time/zones.rb +7 -22
- data/lib/active_support/core_ext/time.rb +1 -0
- data/lib/active_support/core_ext/uri.rb +3 -22
- data/lib/active_support/core_ext.rb +2 -1
- data/lib/active_support/current_attributes/test_helper.rb +13 -0
- data/lib/active_support/current_attributes.rb +47 -16
- data/lib/active_support/dependencies/interlock.rb +10 -18
- data/lib/active_support/dependencies/require_dependency.rb +28 -0
- data/lib/active_support/dependencies.rb +60 -715
- data/lib/active_support/deprecation/behaviors.rb +21 -5
- data/lib/active_support/deprecation/disallowed.rb +56 -0
- data/lib/active_support/deprecation/instance_delegator.rb +0 -1
- data/lib/active_support/deprecation/method_wrappers.rb +18 -23
- data/lib/active_support/deprecation/proxy_wrappers.rb +31 -8
- data/lib/active_support/deprecation/reporting.rb +50 -7
- data/lib/active_support/deprecation.rb +7 -2
- data/lib/active_support/descendants_tracker.rb +190 -34
- data/lib/active_support/digest.rb +5 -3
- data/lib/active_support/duration/iso8601_parser.rb +5 -7
- data/lib/active_support/duration/iso8601_serializer.rb +27 -15
- data/lib/active_support/duration.rb +149 -67
- data/lib/active_support/encrypted_configuration.rb +12 -5
- data/lib/active_support/encrypted_file.rb +23 -5
- data/lib/active_support/environment_inquirer.rb +20 -0
- data/lib/active_support/error_reporter.rb +117 -0
- data/lib/active_support/evented_file_update_checker.rb +85 -122
- data/lib/active_support/execution_context/test_helper.rb +13 -0
- data/lib/active_support/execution_context.rb +53 -0
- data/lib/active_support/execution_wrapper.rb +44 -21
- data/lib/active_support/executor/test_helper.rb +7 -0
- data/lib/active_support/file_update_checker.rb +0 -1
- data/lib/active_support/fork_tracker.rb +71 -0
- data/lib/active_support/gem_version.rb +5 -5
- data/lib/active_support/hash_with_indifferent_access.rb +73 -43
- data/lib/active_support/html_safe_translation.rb +43 -0
- data/lib/active_support/i18n.rb +2 -0
- data/lib/active_support/i18n_railtie.rb +15 -8
- data/lib/active_support/inflector/inflections.rb +25 -14
- data/lib/active_support/inflector/methods.rb +38 -71
- data/lib/active_support/inflector/transliterate.rb +47 -18
- data/lib/active_support/isolated_execution_state.rb +72 -0
- data/lib/active_support/json/decoding.rb +25 -26
- data/lib/active_support/json/encoding.rb +14 -6
- data/lib/active_support/key_generator.rb +23 -38
- data/lib/active_support/lazy_load_hooks.rb +19 -5
- data/lib/active_support/locale/en.rb +33 -0
- data/lib/active_support/locale/en.yml +8 -4
- data/lib/active_support/log_subscriber/test_helper.rb +2 -2
- data/lib/active_support/log_subscriber.rb +51 -11
- data/lib/active_support/logger.rb +6 -22
- data/lib/active_support/logger_silence.rb +11 -19
- data/lib/active_support/logger_thread_safe_level.rb +45 -10
- data/lib/active_support/message_encryptor.rb +20 -19
- data/lib/active_support/message_verifier.rb +53 -21
- data/lib/active_support/messages/metadata.rb +13 -4
- data/lib/active_support/messages/rotation_configuration.rb +2 -1
- data/lib/active_support/messages/rotator.rb +10 -9
- data/lib/active_support/multibyte/chars.rb +17 -76
- data/lib/active_support/multibyte/unicode.rb +7 -331
- data/lib/active_support/multibyte.rb +1 -1
- data/lib/active_support/notifications/fanout.rb +163 -37
- data/lib/active_support/notifications/instrumenter.rb +90 -11
- data/lib/active_support/notifications.rb +88 -30
- data/lib/active_support/number_helper/number_converter.rb +6 -9
- data/lib/active_support/number_helper/number_to_currency_converter.rb +12 -12
- data/lib/active_support/number_helper/number_to_delimited_converter.rb +4 -3
- data/lib/active_support/number_helper/number_to_human_converter.rb +4 -3
- data/lib/active_support/number_helper/number_to_human_size_converter.rb +5 -4
- data/lib/active_support/number_helper/number_to_percentage_converter.rb +3 -1
- data/lib/active_support/number_helper/number_to_phone_converter.rb +3 -2
- data/lib/active_support/number_helper/number_to_rounded_converter.rb +12 -7
- data/lib/active_support/number_helper/rounding_helper.rb +12 -32
- data/lib/active_support/number_helper.rb +36 -12
- data/lib/active_support/option_merger.rb +15 -4
- data/lib/active_support/ordered_hash.rb +2 -2
- data/lib/active_support/ordered_options.rb +14 -4
- data/lib/active_support/parameter_filter.rb +138 -0
- data/lib/active_support/per_thread_registry.rb +6 -1
- data/lib/active_support/rails.rb +1 -10
- data/lib/active_support/railtie.rb +77 -5
- data/lib/active_support/reloader.rb +5 -6
- data/lib/active_support/rescuable.rb +8 -8
- data/lib/active_support/ruby_features.rb +7 -0
- data/lib/active_support/secure_compare_rotator.rb +51 -0
- data/lib/active_support/security_utils.rb +19 -12
- data/lib/active_support/string_inquirer.rb +2 -3
- data/lib/active_support/subscriber.rb +79 -46
- data/lib/active_support/tagged_logging.rb +58 -9
- data/lib/active_support/test_case.rb +79 -0
- data/lib/active_support/testing/assertions.rb +62 -11
- data/lib/active_support/testing/deprecation.rb +52 -2
- data/lib/active_support/testing/file_fixtures.rb +2 -0
- data/lib/active_support/testing/isolation.rb +4 -4
- data/lib/active_support/testing/method_call_assertions.rb +32 -5
- data/lib/active_support/testing/parallelization/server.rb +82 -0
- data/lib/active_support/testing/parallelization/worker.rb +103 -0
- data/lib/active_support/testing/parallelization.rb +55 -0
- data/lib/active_support/testing/parallelize_executor.rb +76 -0
- data/lib/active_support/testing/stream.rb +4 -7
- data/lib/active_support/testing/tagged_logging.rb +1 -1
- data/lib/active_support/testing/time_helpers.rb +60 -14
- data/lib/active_support/time_with_zone.rb +139 -64
- data/lib/active_support/values/time_zone.rb +66 -30
- data/lib/active_support/version.rb +1 -1
- data/lib/active_support/xml_mini/jdom.rb +3 -4
- data/lib/active_support/xml_mini/libxml.rb +7 -7
- data/lib/active_support/xml_mini/libxmlsax.rb +5 -5
- data/lib/active_support/xml_mini/nokogiri.rb +6 -6
- data/lib/active_support/xml_mini/nokogirisax.rb +4 -4
- data/lib/active_support/xml_mini/rexml.rb +11 -4
- data/lib/active_support/xml_mini.rb +7 -14
- data/lib/active_support.rb +30 -1
- metadata +64 -35
- data/lib/active_support/core_ext/array/prepend_and_append.rb +0 -9
- data/lib/active_support/core_ext/hash/compact.rb +0 -29
- data/lib/active_support/core_ext/hash/transform_values.rb +0 -32
- data/lib/active_support/core_ext/kernel/agnostics.rb +0 -13
- data/lib/active_support/core_ext/marshal.rb +0 -24
- data/lib/active_support/core_ext/module/reachable.rb +0 -11
- data/lib/active_support/core_ext/numeric/inquiry.rb +0 -28
- data/lib/active_support/core_ext/range/include_range.rb +0 -3
- data/lib/active_support/values/unicode_tables.dat +0 -0
data/lib/active_support/cache.rb
CHANGED
@@ -3,10 +3,12 @@
|
|
3
3
|
require "zlib"
|
4
4
|
require "active_support/core_ext/array/extract_options"
|
5
5
|
require "active_support/core_ext/array/wrap"
|
6
|
+
require "active_support/core_ext/enumerable"
|
6
7
|
require "active_support/core_ext/module/attribute_accessors"
|
7
8
|
require "active_support/core_ext/numeric/bytes"
|
8
9
|
require "active_support/core_ext/numeric/time"
|
9
10
|
require "active_support/core_ext/object/to_param"
|
11
|
+
require "active_support/core_ext/object/try"
|
10
12
|
require "active_support/core_ext/string/inflections"
|
11
13
|
|
12
14
|
module ActiveSupport
|
@@ -20,13 +22,24 @@ module ActiveSupport
|
|
20
22
|
|
21
23
|
# These options mean something to all cache implementations. Individual cache
|
22
24
|
# implementations may support additional options.
|
23
|
-
UNIVERSAL_OPTIONS = [:namespace, :compress, :compress_threshold, :expires_in, :race_condition_ttl]
|
25
|
+
UNIVERSAL_OPTIONS = [:namespace, :compress, :compress_threshold, :expires_in, :expire_in, :expired_in, :race_condition_ttl, :coder, :skip_nil]
|
26
|
+
|
27
|
+
DEFAULT_COMPRESS_LIMIT = 1.kilobyte
|
28
|
+
|
29
|
+
# Mapping of canonical option names to aliases that a store will recognize.
|
30
|
+
OPTION_ALIASES = {
|
31
|
+
expires_in: [:expire_in, :expired_in]
|
32
|
+
}.freeze
|
24
33
|
|
25
34
|
module Strategy
|
26
35
|
autoload :LocalCache, "active_support/cache/strategy/local_cache"
|
27
36
|
end
|
28
37
|
|
38
|
+
@format_version = 6.1
|
39
|
+
|
29
40
|
class << self
|
41
|
+
attr_accessor :format_version
|
42
|
+
|
30
43
|
# Creates a new Store object according to the given options.
|
31
44
|
#
|
32
45
|
# If no arguments are passed to this method, then a new
|
@@ -52,12 +65,19 @@ module ActiveSupport
|
|
52
65
|
#
|
53
66
|
# ActiveSupport::Cache.lookup_store(MyOwnCacheStore.new)
|
54
67
|
# # => returns MyOwnCacheStore.new
|
55
|
-
def lookup_store(*
|
56
|
-
store, *parameters = *Array.wrap(store_option).flatten
|
57
|
-
|
68
|
+
def lookup_store(store = nil, *parameters)
|
58
69
|
case store
|
59
70
|
when Symbol
|
60
|
-
|
71
|
+
options = parameters.extract_options!
|
72
|
+
# clean this up once Ruby 2.7 support is dropped
|
73
|
+
# see https://github.com/rails/rails/pull/41522#discussion_r581186602
|
74
|
+
if options.empty?
|
75
|
+
retrieve_store_class(store).new(*parameters)
|
76
|
+
else
|
77
|
+
retrieve_store_class(store).new(*parameters, **options)
|
78
|
+
end
|
79
|
+
when Array
|
80
|
+
lookup_store(*store)
|
61
81
|
when nil
|
62
82
|
ActiveSupport::Cache::MemoryStore.new
|
63
83
|
else
|
@@ -78,7 +98,7 @@ module ActiveSupport
|
|
78
98
|
#
|
79
99
|
# The +key+ argument can also respond to +cache_key+ or +to_param+.
|
80
100
|
def expand_cache_key(key, namespace = nil)
|
81
|
-
expanded_cache_key =
|
101
|
+
expanded_cache_key = namespace ? +"#{namespace}/" : +""
|
82
102
|
|
83
103
|
if prefix = ENV["RAILS_CACHE_ID"] || ENV["RAILS_APP_VERSION"]
|
84
104
|
expanded_cache_key << "#{prefix}/"
|
@@ -121,7 +141,8 @@ module ActiveSupport
|
|
121
141
|
# Some implementations may not support all methods beyond the basic cache
|
122
142
|
# methods of +fetch+, +write+, +read+, +exist?+, and +delete+.
|
123
143
|
#
|
124
|
-
# ActiveSupport::Cache::Store can store any
|
144
|
+
# ActiveSupport::Cache::Store can store any Ruby object that is supported by
|
145
|
+
# its +coder+'s +dump+ and +load+ methods.
|
125
146
|
#
|
126
147
|
# cache = ActiveSupport::Cache::MemoryStore.new
|
127
148
|
#
|
@@ -129,6 +150,8 @@ module ActiveSupport
|
|
129
150
|
# cache.write('city', "Duckburgh")
|
130
151
|
# cache.read('city') # => "Duckburgh"
|
131
152
|
#
|
153
|
+
# cache.write('not serializable', Proc.new {}) # => TypeError
|
154
|
+
#
|
132
155
|
# Keys are always translated into Strings and are case sensitive. When an
|
133
156
|
# object is specified as a key and has a +cache_key+ method defined, this
|
134
157
|
# method will be called to define the key. Otherwise, the +to_param+
|
@@ -181,7 +204,12 @@ module ActiveSupport
|
|
181
204
|
# except for <tt>:namespace</tt> which can be used to set the global
|
182
205
|
# namespace for the cache.
|
183
206
|
def initialize(options = nil)
|
184
|
-
@options = options ? options
|
207
|
+
@options = options ? normalize_options(options) : {}
|
208
|
+
@options[:compress] = true unless @options.key?(:compress)
|
209
|
+
@options[:compress_threshold] = DEFAULT_COMPRESS_LIMIT unless @options.key?(:compress_threshold)
|
210
|
+
|
211
|
+
@coder = @options.delete(:coder) { default_coder } || NullCoder
|
212
|
+
@coder_supports_compression = @coder.respond_to?(:dump_compressed)
|
185
213
|
end
|
186
214
|
|
187
215
|
# Silences the logger.
|
@@ -229,17 +257,35 @@ module ActiveSupport
|
|
229
257
|
# ask whether you should force a cache write. Otherwise, it's clearer to
|
230
258
|
# just call <tt>Cache#write</tt>.
|
231
259
|
#
|
260
|
+
# Setting <tt>skip_nil: true</tt> will not cache nil result:
|
261
|
+
#
|
262
|
+
# cache.fetch('foo') { nil }
|
263
|
+
# cache.fetch('bar', skip_nil: true) { nil }
|
264
|
+
# cache.exist?('foo') # => true
|
265
|
+
# cache.exist?('bar') # => false
|
266
|
+
#
|
267
|
+
#
|
232
268
|
# Setting <tt>compress: false</tt> disables compression of the cache entry.
|
233
269
|
#
|
234
270
|
# Setting <tt>:expires_in</tt> will set an expiration time on the cache.
|
235
271
|
# All caches support auto-expiring content after a specified number of
|
236
272
|
# seconds. This value can be specified as an option to the constructor
|
237
273
|
# (in which case all entries will be affected), or it can be supplied to
|
238
|
-
# the +fetch+ or +write+ method to
|
274
|
+
# the +fetch+ or +write+ method to affect just one entry.
|
275
|
+
# <tt>:expire_in</tt> and <tt>:expired_in</tt> are aliases for
|
276
|
+
# <tt>:expires_in</tt>.
|
239
277
|
#
|
240
278
|
# cache = ActiveSupport::Cache::MemoryStore.new(expires_in: 5.minutes)
|
241
279
|
# cache.write(key, value, expires_in: 1.minute) # Set a lower value for one entry
|
242
280
|
#
|
281
|
+
# Setting <tt>:expires_at</tt> will set an absolute expiration time on the cache.
|
282
|
+
# All caches support auto-expiring content after a specified number of
|
283
|
+
# seconds. This value can only be supplied to the +fetch+ or +write+ method to
|
284
|
+
# affect just one entry.
|
285
|
+
#
|
286
|
+
# cache = ActiveSupport::Cache::MemoryStore.new
|
287
|
+
# cache.write(key, value, expires_at: Time.now.at_end_of_hour)
|
288
|
+
#
|
243
289
|
# Setting <tt>:version</tt> verifies the cache stored under <tt>name</tt>
|
244
290
|
# is of the same version. nil is returned on mismatches despite contents.
|
245
291
|
# This feature is used to support recyclable cache keys.
|
@@ -303,14 +349,14 @@ module ActiveSupport
|
|
303
349
|
# :bar
|
304
350
|
# end
|
305
351
|
# cache.fetch('foo') # => "bar"
|
306
|
-
def fetch(name, options = nil)
|
352
|
+
def fetch(name, options = nil, &block)
|
307
353
|
if block_given?
|
308
354
|
options = merged_options(options)
|
309
355
|
key = normalize_key(name, options)
|
310
356
|
|
311
357
|
entry = nil
|
312
358
|
instrument(:read, name, options) do |payload|
|
313
|
-
cached_entry = read_entry(key, options) unless options[:force]
|
359
|
+
cached_entry = read_entry(key, **options, event: payload) unless options[:force]
|
314
360
|
entry = handle_expired_entry(cached_entry, key, options)
|
315
361
|
entry = nil if entry && entry.mismatched?(normalize_version(name, options))
|
316
362
|
payload[:super_operation] = :fetch if payload
|
@@ -320,7 +366,7 @@ module ActiveSupport
|
|
320
366
|
if entry
|
321
367
|
get_entry_value(entry, name, options)
|
322
368
|
else
|
323
|
-
save_block_result_to_cache(name, options)
|
369
|
+
save_block_result_to_cache(name, options, &block)
|
324
370
|
end
|
325
371
|
elsif options && options[:force]
|
326
372
|
raise ArgumentError, "Missing block: Calling `Cache#fetch` with `force: true` requires a block."
|
@@ -333,8 +379,9 @@ module ActiveSupport
|
|
333
379
|
# the cache with the given key, then that data is returned. Otherwise,
|
334
380
|
# +nil+ is returned.
|
335
381
|
#
|
336
|
-
# Note, if data was written with the <tt>:expires_in
|
337
|
-
# both of these conditions are applied before
|
382
|
+
# Note, if data was written with the <tt>:expires_in</tt> or
|
383
|
+
# <tt>:version</tt> options, both of these conditions are applied before
|
384
|
+
# the data is returned.
|
338
385
|
#
|
339
386
|
# Options are passed to the underlying cache implementation.
|
340
387
|
def read(name, options = nil)
|
@@ -343,11 +390,11 @@ module ActiveSupport
|
|
343
390
|
version = normalize_version(name, options)
|
344
391
|
|
345
392
|
instrument(:read, name, options) do |payload|
|
346
|
-
entry = read_entry(key, options)
|
393
|
+
entry = read_entry(key, **options, event: payload)
|
347
394
|
|
348
395
|
if entry
|
349
396
|
if entry.expired?
|
350
|
-
delete_entry(key, options)
|
397
|
+
delete_entry(key, **options)
|
351
398
|
payload[:hit] = false if payload
|
352
399
|
nil
|
353
400
|
elsif entry.mismatched?(version)
|
@@ -375,7 +422,7 @@ module ActiveSupport
|
|
375
422
|
options = merged_options(options)
|
376
423
|
|
377
424
|
instrument :read_multi, names, options do |payload|
|
378
|
-
read_multi_entries(names, options).tap do |results|
|
425
|
+
read_multi_entries(names, **options, event: payload).tap do |results|
|
379
426
|
payload[:hits] = results.keys
|
380
427
|
end
|
381
428
|
end
|
@@ -387,10 +434,10 @@ module ActiveSupport
|
|
387
434
|
|
388
435
|
instrument :write_multi, hash, options do |payload|
|
389
436
|
entries = hash.each_with_object({}) do |(name, value), memo|
|
390
|
-
memo[normalize_key(name, options)] = Entry.new(value, options.merge(version: normalize_version(name, options)))
|
437
|
+
memo[normalize_key(name, options)] = Entry.new(value, **options.merge(version: normalize_version(name, options)))
|
391
438
|
end
|
392
439
|
|
393
|
-
write_multi_entries entries, options
|
440
|
+
write_multi_entries entries, **options
|
394
441
|
end
|
395
442
|
end
|
396
443
|
|
@@ -402,8 +449,6 @@ module ActiveSupport
|
|
402
449
|
# to the cache. If you do not want to write the cache when the cache is
|
403
450
|
# not found, use #read_multi.
|
404
451
|
#
|
405
|
-
# Options are passed to the underlying cache implementation.
|
406
|
-
#
|
407
452
|
# Returns a hash with the data for each of the names. For example:
|
408
453
|
#
|
409
454
|
# cache.write("bim", "bam")
|
@@ -413,6 +458,17 @@ module ActiveSupport
|
|
413
458
|
# # => { "bim" => "bam",
|
414
459
|
# # "unknown_key" => "Fallback value for key: unknown_key" }
|
415
460
|
#
|
461
|
+
# Options are passed to the underlying cache implementation. For example:
|
462
|
+
#
|
463
|
+
# cache.fetch_multi("fizz", expires_in: 5.seconds) do |key|
|
464
|
+
# "buzz"
|
465
|
+
# end
|
466
|
+
# # => {"fizz"=>"buzz"}
|
467
|
+
# cache.read("fizz")
|
468
|
+
# # => "buzz"
|
469
|
+
# sleep(6)
|
470
|
+
# cache.read("fizz")
|
471
|
+
# # => nil
|
416
472
|
def fetch_multi(*names)
|
417
473
|
raise ArgumentError, "Missing block: `Cache#fetch_multi` requires a block." unless block_given?
|
418
474
|
|
@@ -420,18 +476,18 @@ module ActiveSupport
|
|
420
476
|
options = merged_options(options)
|
421
477
|
|
422
478
|
instrument :read_multi, names, options do |payload|
|
423
|
-
read_multi_entries(names, options)
|
424
|
-
|
425
|
-
|
479
|
+
reads = read_multi_entries(names, **options)
|
480
|
+
writes = {}
|
481
|
+
ordered = names.index_with do |name|
|
482
|
+
reads.fetch(name) { writes[name] = yield(name) }
|
483
|
+
end
|
426
484
|
|
427
|
-
|
485
|
+
payload[:hits] = reads.keys
|
486
|
+
payload[:super_operation] = :fetch_multi
|
428
487
|
|
429
|
-
|
430
|
-
results[name] = writes[name] = yield(name)
|
431
|
-
end
|
488
|
+
write_multi(writes, options)
|
432
489
|
|
433
|
-
|
434
|
-
end
|
490
|
+
ordered
|
435
491
|
end
|
436
492
|
end
|
437
493
|
|
@@ -442,8 +498,8 @@ module ActiveSupport
|
|
442
498
|
options = merged_options(options)
|
443
499
|
|
444
500
|
instrument(:write, name, options) do
|
445
|
-
entry = Entry.new(value, options.merge(version: normalize_version(name, options)))
|
446
|
-
write_entry(normalize_key(name, options), entry, options)
|
501
|
+
entry = Entry.new(value, **options.merge(version: normalize_version(name, options)))
|
502
|
+
write_entry(normalize_key(name, options), entry, **options)
|
447
503
|
end
|
448
504
|
end
|
449
505
|
|
@@ -454,7 +510,19 @@ module ActiveSupport
|
|
454
510
|
options = merged_options(options)
|
455
511
|
|
456
512
|
instrument(:delete, name) do
|
457
|
-
delete_entry(normalize_key(name, options), options)
|
513
|
+
delete_entry(normalize_key(name, options), **options)
|
514
|
+
end
|
515
|
+
end
|
516
|
+
|
517
|
+
# Deletes multiple entries in the cache.
|
518
|
+
#
|
519
|
+
# Options are passed to the underlying cache implementation.
|
520
|
+
def delete_multi(names, options = nil)
|
521
|
+
options = merged_options(options)
|
522
|
+
names.map! { |key| normalize_key(key, options) }
|
523
|
+
|
524
|
+
instrument :delete_multi, names do
|
525
|
+
delete_multi_entries(names, **options)
|
458
526
|
end
|
459
527
|
end
|
460
528
|
|
@@ -464,17 +532,21 @@ module ActiveSupport
|
|
464
532
|
def exist?(name, options = nil)
|
465
533
|
options = merged_options(options)
|
466
534
|
|
467
|
-
instrument(:exist?, name) do
|
468
|
-
entry = read_entry(normalize_key(name, options), options)
|
535
|
+
instrument(:exist?, name) do |payload|
|
536
|
+
entry = read_entry(normalize_key(name, options), **options, event: payload)
|
469
537
|
(entry && !entry.expired? && !entry.mismatched?(normalize_version(name, options))) || false
|
470
538
|
end
|
471
539
|
end
|
472
540
|
|
541
|
+
def new_entry(value, options = nil) # :nodoc:
|
542
|
+
Entry.new(value, **merged_options(options))
|
543
|
+
end
|
544
|
+
|
473
545
|
# Deletes all entries with keys matching the pattern.
|
474
546
|
#
|
475
547
|
# Options are passed to the underlying cache implementation.
|
476
548
|
#
|
477
|
-
#
|
549
|
+
# Some implementations may not support this method.
|
478
550
|
def delete_matched(matcher, options = nil)
|
479
551
|
raise NotImplementedError.new("#{self.class.name} does not support delete_matched")
|
480
552
|
end
|
@@ -483,7 +555,7 @@ module ActiveSupport
|
|
483
555
|
#
|
484
556
|
# Options are passed to the underlying cache implementation.
|
485
557
|
#
|
486
|
-
#
|
558
|
+
# Some implementations may not support this method.
|
487
559
|
def increment(name, amount = 1, options = nil)
|
488
560
|
raise NotImplementedError.new("#{self.class.name} does not support increment")
|
489
561
|
end
|
@@ -492,7 +564,7 @@ module ActiveSupport
|
|
492
564
|
#
|
493
565
|
# Options are passed to the underlying cache implementation.
|
494
566
|
#
|
495
|
-
#
|
567
|
+
# Some implementations may not support this method.
|
496
568
|
def decrement(name, amount = 1, options = nil)
|
497
569
|
raise NotImplementedError.new("#{self.class.name} does not support decrement")
|
498
570
|
end
|
@@ -501,7 +573,7 @@ module ActiveSupport
|
|
501
573
|
#
|
502
574
|
# Options are passed to the underlying cache implementation.
|
503
575
|
#
|
504
|
-
#
|
576
|
+
# Some implementations may not support this method.
|
505
577
|
def cleanup(options = nil)
|
506
578
|
raise NotImplementedError.new("#{self.class.name} does not support cleanup")
|
507
579
|
end
|
@@ -511,12 +583,16 @@ module ActiveSupport
|
|
511
583
|
#
|
512
584
|
# The options hash is passed to the underlying cache implementation.
|
513
585
|
#
|
514
|
-
#
|
586
|
+
# Some implementations may not support this method.
|
515
587
|
def clear(options = nil)
|
516
588
|
raise NotImplementedError.new("#{self.class.name} does not support clear")
|
517
589
|
end
|
518
590
|
|
519
591
|
private
|
592
|
+
def default_coder
|
593
|
+
Coders[Cache.format_version]
|
594
|
+
end
|
595
|
+
|
520
596
|
# Adds the namespace defined in the options to a pattern designed to
|
521
597
|
# match keys. Implementations that support delete_matched should call
|
522
598
|
# this method to translate a pattern that matches names into one that
|
@@ -538,59 +614,92 @@ module ActiveSupport
|
|
538
614
|
|
539
615
|
# Reads an entry from the cache implementation. Subclasses must implement
|
540
616
|
# this method.
|
541
|
-
def read_entry(key, options)
|
617
|
+
def read_entry(key, **options)
|
542
618
|
raise NotImplementedError.new
|
543
619
|
end
|
544
620
|
|
545
621
|
# Writes an entry to the cache implementation. Subclasses must implement
|
546
622
|
# this method.
|
547
|
-
def write_entry(key, entry, options)
|
623
|
+
def write_entry(key, entry, **options)
|
548
624
|
raise NotImplementedError.new
|
549
625
|
end
|
550
626
|
|
627
|
+
def serialize_entry(entry, **options)
|
628
|
+
options = merged_options(options)
|
629
|
+
if @coder_supports_compression && options[:compress]
|
630
|
+
@coder.dump_compressed(entry, options[:compress_threshold] || DEFAULT_COMPRESS_LIMIT)
|
631
|
+
else
|
632
|
+
@coder.dump(entry)
|
633
|
+
end
|
634
|
+
end
|
635
|
+
|
636
|
+
def deserialize_entry(payload)
|
637
|
+
payload.nil? ? nil : @coder.load(payload)
|
638
|
+
end
|
639
|
+
|
551
640
|
# Reads multiple entries from the cache implementation. Subclasses MAY
|
552
641
|
# implement this method.
|
553
|
-
def read_multi_entries(names, options)
|
554
|
-
|
555
|
-
|
556
|
-
|
642
|
+
def read_multi_entries(names, **options)
|
643
|
+
names.each_with_object({}) do |name, results|
|
644
|
+
key = normalize_key(name, options)
|
645
|
+
entry = read_entry(key, **options)
|
646
|
+
|
647
|
+
next unless entry
|
648
|
+
|
557
649
|
version = normalize_version(name, options)
|
558
|
-
|
559
|
-
|
560
|
-
|
561
|
-
|
562
|
-
|
563
|
-
elsif entry.mismatched?(version)
|
564
|
-
# Skip mismatched versions
|
565
|
-
else
|
566
|
-
results[name] = entry.value
|
567
|
-
end
|
650
|
+
|
651
|
+
if entry.expired?
|
652
|
+
delete_entry(key, **options)
|
653
|
+
elsif !entry.mismatched?(version)
|
654
|
+
results[name] = entry.value
|
568
655
|
end
|
569
656
|
end
|
570
|
-
results
|
571
657
|
end
|
572
658
|
|
573
659
|
# Writes multiple entries to the cache implementation. Subclasses MAY
|
574
660
|
# implement this method.
|
575
|
-
def write_multi_entries(hash, options)
|
661
|
+
def write_multi_entries(hash, **options)
|
576
662
|
hash.each do |key, entry|
|
577
|
-
write_entry key, entry, options
|
663
|
+
write_entry key, entry, **options
|
578
664
|
end
|
579
665
|
end
|
580
666
|
|
581
667
|
# Deletes an entry from the cache implementation. Subclasses must
|
582
668
|
# implement this method.
|
583
|
-
def delete_entry(key, options)
|
669
|
+
def delete_entry(key, **options)
|
584
670
|
raise NotImplementedError.new
|
585
671
|
end
|
586
672
|
|
673
|
+
# Deletes multiples entries in the cache implementation. Subclasses MAY
|
674
|
+
# implement this method.
|
675
|
+
def delete_multi_entries(entries, **options)
|
676
|
+
entries.count { |key| delete_entry(key, **options) }
|
677
|
+
end
|
678
|
+
|
587
679
|
# Merges the default options with ones specific to a method call.
|
588
680
|
def merged_options(call_options)
|
589
681
|
if call_options
|
590
|
-
|
682
|
+
call_options = normalize_options(call_options)
|
683
|
+
if options.empty?
|
684
|
+
call_options
|
685
|
+
else
|
686
|
+
options.merge(call_options)
|
687
|
+
end
|
591
688
|
else
|
592
|
-
options
|
689
|
+
options
|
690
|
+
end
|
691
|
+
end
|
692
|
+
|
693
|
+
# Normalize aliased options to their canonical form
|
694
|
+
def normalize_options(options)
|
695
|
+
options = options.dup
|
696
|
+
OPTION_ALIASES.each do |canonical_name, aliases|
|
697
|
+
alias_key = aliases.detect { |key| options.key?(key) }
|
698
|
+
options[canonical_name] ||= options[alias_key] if alias_key
|
699
|
+
options.except!(*aliases)
|
593
700
|
end
|
701
|
+
|
702
|
+
options
|
594
703
|
end
|
595
704
|
|
596
705
|
# Expands and namespaces the cache key. May be overridden by
|
@@ -616,6 +725,10 @@ module ActiveSupport
|
|
616
725
|
namespace = namespace.call
|
617
726
|
end
|
618
727
|
|
728
|
+
if key && key.encoding != Encoding::UTF_8
|
729
|
+
key = key.dup.force_encoding(Encoding::UTF_8)
|
730
|
+
end
|
731
|
+
|
619
732
|
if namespace
|
620
733
|
"#{namespace}:#{key}"
|
621
734
|
else
|
@@ -632,15 +745,15 @@ module ActiveSupport
|
|
632
745
|
case key
|
633
746
|
when Array
|
634
747
|
if key.size > 1
|
635
|
-
key
|
748
|
+
key.collect { |element| expanded_key(element) }
|
636
749
|
else
|
637
|
-
key
|
750
|
+
expanded_key(key.first)
|
638
751
|
end
|
639
752
|
when Hash
|
640
|
-
key
|
641
|
-
|
642
|
-
|
643
|
-
|
753
|
+
key.collect { |k, v| "#{k}=#{v}" }.sort!
|
754
|
+
else
|
755
|
+
key
|
756
|
+
end.to_param
|
644
757
|
end
|
645
758
|
|
646
759
|
def normalize_version(key, options = nil)
|
@@ -650,34 +763,31 @@ module ActiveSupport
|
|
650
763
|
def expanded_version(key)
|
651
764
|
case
|
652
765
|
when key.respond_to?(:cache_version) then key.cache_version.to_param
|
653
|
-
when key.is_a?(Array) then key.map { |element| expanded_version(element) }.compact.to_param
|
766
|
+
when key.is_a?(Array) then key.map { |element| expanded_version(element) }.tap(&:compact!).to_param
|
654
767
|
when key.respond_to?(:to_a) then expanded_version(key.to_a)
|
655
768
|
end
|
656
769
|
end
|
657
770
|
|
658
771
|
def instrument(operation, key, options = nil)
|
659
|
-
|
772
|
+
if logger && logger.debug? && !silence?
|
773
|
+
logger.debug "Cache #{operation}: #{normalize_key(key, options)}#{options.blank? ? "" : " (#{options.inspect})"}"
|
774
|
+
end
|
660
775
|
|
661
|
-
payload = { key: key }
|
776
|
+
payload = { key: key, store: self.class.name }
|
662
777
|
payload.merge!(options) if options.is_a?(Hash)
|
663
778
|
ActiveSupport::Notifications.instrument("cache_#{operation}.active_support", payload) { yield(payload) }
|
664
779
|
end
|
665
780
|
|
666
|
-
def log
|
667
|
-
return unless logger && logger.debug? && !silence?
|
668
|
-
logger.debug(yield)
|
669
|
-
end
|
670
|
-
|
671
781
|
def handle_expired_entry(entry, key, options)
|
672
782
|
if entry && entry.expired?
|
673
783
|
race_ttl = options[:race_condition_ttl].to_i
|
674
784
|
if (race_ttl > 0) && (Time.now.to_f - entry.expires_at <= race_ttl)
|
675
785
|
# When an entry has a positive :race_condition_ttl defined, put the stale entry back into the cache
|
676
786
|
# for a brief period while the entry is being recalculated.
|
677
|
-
entry.expires_at = Time.now + race_ttl
|
787
|
+
entry.expires_at = Time.now.to_f + race_ttl
|
678
788
|
write_entry(key, entry, expires_in: race_ttl * 2)
|
679
789
|
else
|
680
|
-
delete_entry(key, options)
|
790
|
+
delete_entry(key, **options)
|
681
791
|
end
|
682
792
|
entry = nil
|
683
793
|
end
|
@@ -685,7 +795,7 @@ module ActiveSupport
|
|
685
795
|
end
|
686
796
|
|
687
797
|
def get_entry_value(entry, name, options)
|
688
|
-
instrument(:fetch_hit, name, options) {}
|
798
|
+
instrument(:fetch_hit, name, options) { }
|
689
799
|
entry.value
|
690
800
|
end
|
691
801
|
|
@@ -694,11 +804,103 @@ module ActiveSupport
|
|
694
804
|
yield(name)
|
695
805
|
end
|
696
806
|
|
697
|
-
write(name, result, options)
|
807
|
+
write(name, result, options) unless result.nil? && options[:skip_nil]
|
698
808
|
result
|
699
809
|
end
|
700
810
|
end
|
701
811
|
|
812
|
+
module NullCoder # :nodoc:
|
813
|
+
extend self
|
814
|
+
|
815
|
+
def dump(entry)
|
816
|
+
entry
|
817
|
+
end
|
818
|
+
|
819
|
+
def dump_compressed(entry, threshold)
|
820
|
+
entry.compressed(threshold)
|
821
|
+
end
|
822
|
+
|
823
|
+
def load(payload)
|
824
|
+
payload
|
825
|
+
end
|
826
|
+
end
|
827
|
+
|
828
|
+
module Coders # :nodoc:
|
829
|
+
MARK_61 = "\x04\b".b.freeze # The one set by Marshal.
|
830
|
+
MARK_70_UNCOMPRESSED = "\x00".b.freeze
|
831
|
+
MARK_70_COMPRESSED = "\x01".b.freeze
|
832
|
+
|
833
|
+
class << self
|
834
|
+
def [](version)
|
835
|
+
case version
|
836
|
+
when 6.1
|
837
|
+
Rails61Coder
|
838
|
+
when 7.0
|
839
|
+
Rails70Coder
|
840
|
+
else
|
841
|
+
raise ArgumentError, "Unknown ActiveSupport::Cache.format_version #{Cache.format_version.inspect}"
|
842
|
+
end
|
843
|
+
end
|
844
|
+
end
|
845
|
+
|
846
|
+
module Loader
|
847
|
+
extend self
|
848
|
+
|
849
|
+
def load(payload)
|
850
|
+
if !payload.is_a?(String)
|
851
|
+
ActiveSupport::Cache::Store.logger&.warn %{Payload wasn't a string, was #{payload.class.name} - couldn't unmarshal, so returning nil."}
|
852
|
+
|
853
|
+
return nil
|
854
|
+
elsif payload.start_with?(MARK_70_UNCOMPRESSED)
|
855
|
+
members = Marshal.load(payload.byteslice(1..-1))
|
856
|
+
elsif payload.start_with?(MARK_70_COMPRESSED)
|
857
|
+
members = Marshal.load(Zlib::Inflate.inflate(payload.byteslice(1..-1)))
|
858
|
+
elsif payload.start_with?(MARK_61)
|
859
|
+
return Marshal.load(payload)
|
860
|
+
else
|
861
|
+
ActiveSupport::Cache::Store.logger&.warn %{Invalid cache prefix: #{payload.byteslice(0).inspect}, expected "\\x00" or "\\x01"}
|
862
|
+
|
863
|
+
return nil
|
864
|
+
end
|
865
|
+
Entry.unpack(members)
|
866
|
+
end
|
867
|
+
end
|
868
|
+
|
869
|
+
module Rails61Coder
|
870
|
+
include Loader
|
871
|
+
extend self
|
872
|
+
|
873
|
+
def dump(entry)
|
874
|
+
Marshal.dump(entry)
|
875
|
+
end
|
876
|
+
|
877
|
+
def dump_compressed(entry, threshold)
|
878
|
+
Marshal.dump(entry.compressed(threshold))
|
879
|
+
end
|
880
|
+
end
|
881
|
+
|
882
|
+
module Rails70Coder
|
883
|
+
include Loader
|
884
|
+
extend self
|
885
|
+
|
886
|
+
def dump(entry)
|
887
|
+
MARK_70_UNCOMPRESSED + Marshal.dump(entry.pack)
|
888
|
+
end
|
889
|
+
|
890
|
+
def dump_compressed(entry, threshold)
|
891
|
+
payload = Marshal.dump(entry.pack)
|
892
|
+
if payload.bytesize >= threshold
|
893
|
+
compressed_payload = Zlib::Deflate.deflate(payload)
|
894
|
+
if compressed_payload.bytesize < payload.bytesize
|
895
|
+
return MARK_70_COMPRESSED + compressed_payload
|
896
|
+
end
|
897
|
+
end
|
898
|
+
|
899
|
+
MARK_70_UNCOMPRESSED + payload
|
900
|
+
end
|
901
|
+
end
|
902
|
+
end
|
903
|
+
|
702
904
|
# This class is used to represent cache entries. Cache entries have a value, an optional
|
703
905
|
# expiration time, and an optional version. The expiration time is used to support the :race_condition_ttl option
|
704
906
|
# on the cache. The version is used to support the :version option on the cache for rejecting
|
@@ -707,19 +909,22 @@ module ActiveSupport
|
|
707
909
|
# Since cache entries in most instances will be serialized, the internals of this class are highly optimized
|
708
910
|
# using short instance variable names that are lazily defined.
|
709
911
|
class Entry # :nodoc:
|
710
|
-
|
912
|
+
class << self
|
913
|
+
def unpack(members)
|
914
|
+
new(members[0], expires_at: members[1], version: members[2])
|
915
|
+
end
|
916
|
+
end
|
711
917
|
|
712
|
-
|
918
|
+
attr_reader :version
|
713
919
|
|
714
920
|
# Creates a new cache entry for the specified value. Options supported are
|
715
|
-
# +:
|
716
|
-
def initialize(value,
|
921
|
+
# +:compressed+, +:version+, +:expires_at+ and +:expires_in+.
|
922
|
+
def initialize(value, compressed: false, version: nil, expires_in: nil, expires_at: nil, **)
|
717
923
|
@value = value
|
718
924
|
@version = version
|
719
|
-
@created_at =
|
720
|
-
@expires_in = expires_in && expires_in.to_f
|
721
|
-
|
722
|
-
compress!(compress_threshold) if compress
|
925
|
+
@created_at = 0.0
|
926
|
+
@expires_in = expires_at&.to_f || expires_in && (expires_in.to_f + Time.now.to_f)
|
927
|
+
@compressed = true if compressed
|
723
928
|
end
|
724
929
|
|
725
930
|
def value
|
@@ -749,8 +954,8 @@ module ActiveSupport
|
|
749
954
|
end
|
750
955
|
|
751
956
|
# Returns the size of the cached value. This could be less than
|
752
|
-
# <tt>value.
|
753
|
-
def
|
957
|
+
# <tt>value.bytesize</tt> if the data is compressed.
|
958
|
+
def bytesize
|
754
959
|
case value
|
755
960
|
when NilClass
|
756
961
|
0
|
@@ -761,6 +966,38 @@ module ActiveSupport
|
|
761
966
|
end
|
762
967
|
end
|
763
968
|
|
969
|
+
def compressed? # :nodoc:
|
970
|
+
defined?(@compressed)
|
971
|
+
end
|
972
|
+
|
973
|
+
def compressed(compress_threshold)
|
974
|
+
return self if compressed?
|
975
|
+
|
976
|
+
case @value
|
977
|
+
when nil, true, false, Numeric
|
978
|
+
uncompressed_size = 0
|
979
|
+
when String
|
980
|
+
uncompressed_size = @value.bytesize
|
981
|
+
else
|
982
|
+
serialized = Marshal.dump(@value)
|
983
|
+
uncompressed_size = serialized.bytesize
|
984
|
+
end
|
985
|
+
|
986
|
+
if uncompressed_size >= compress_threshold
|
987
|
+
serialized ||= Marshal.dump(@value)
|
988
|
+
compressed = Zlib::Deflate.deflate(serialized)
|
989
|
+
|
990
|
+
if compressed.bytesize < uncompressed_size
|
991
|
+
return Entry.new(compressed, compressed: true, expires_at: expires_at, version: version)
|
992
|
+
end
|
993
|
+
end
|
994
|
+
self
|
995
|
+
end
|
996
|
+
|
997
|
+
def local?
|
998
|
+
false
|
999
|
+
end
|
1000
|
+
|
764
1001
|
# Duplicates the value in a class. This is used by cache implementations that don't natively
|
765
1002
|
# serialize entries to protect against accidental cache modifications.
|
766
1003
|
def dup_value!
|
@@ -773,33 +1010,13 @@ module ActiveSupport
|
|
773
1010
|
end
|
774
1011
|
end
|
775
1012
|
|
776
|
-
|
777
|
-
|
778
|
-
|
779
|
-
|
780
|
-
|
781
|
-
when String
|
782
|
-
uncompressed_size = @value.bytesize
|
783
|
-
else
|
784
|
-
serialized = Marshal.dump(@value)
|
785
|
-
uncompressed_size = serialized.bytesize
|
786
|
-
end
|
787
|
-
|
788
|
-
if uncompressed_size >= compress_threshold
|
789
|
-
serialized ||= Marshal.dump(@value)
|
790
|
-
compressed = Zlib::Deflate.deflate(serialized)
|
791
|
-
|
792
|
-
if compressed.bytesize < uncompressed_size
|
793
|
-
@value = compressed
|
794
|
-
@compressed = true
|
795
|
-
end
|
796
|
-
end
|
797
|
-
end
|
798
|
-
|
799
|
-
def compressed?
|
800
|
-
defined?(@compressed)
|
801
|
-
end
|
1013
|
+
def pack
|
1014
|
+
members = [value, expires_at, version]
|
1015
|
+
members.pop while !members.empty? && members.last.nil?
|
1016
|
+
members
|
1017
|
+
end
|
802
1018
|
|
1019
|
+
private
|
803
1020
|
def uncompress(value)
|
804
1021
|
Marshal.load(Zlib::Inflate.inflate(value))
|
805
1022
|
end
|