activesupport 7.0.4 → 7.1.5.1
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +1076 -230
- data/MIT-LICENSE +1 -1
- data/README.rdoc +6 -6
- data/lib/active_support/actionable_error.rb +3 -1
- data/lib/active_support/array_inquirer.rb +2 -0
- data/lib/active_support/backtrace_cleaner.rb +30 -5
- data/lib/active_support/benchmarkable.rb +1 -0
- data/lib/active_support/broadcast_logger.rb +251 -0
- data/lib/active_support/builder.rb +1 -1
- data/lib/active_support/cache/coder.rb +153 -0
- data/lib/active_support/cache/entry.rb +134 -0
- data/lib/active_support/cache/file_store.rb +37 -10
- data/lib/active_support/cache/mem_cache_store.rb +100 -76
- data/lib/active_support/cache/memory_store.rb +78 -24
- data/lib/active_support/cache/null_store.rb +6 -0
- data/lib/active_support/cache/redis_cache_store.rb +153 -141
- data/lib/active_support/cache/serializer_with_fallback.rb +175 -0
- data/lib/active_support/cache/strategy/local_cache.rb +29 -14
- data/lib/active_support/cache.rb +333 -253
- data/lib/active_support/callbacks.rb +44 -21
- data/lib/active_support/code_generator.rb +15 -10
- data/lib/active_support/concern.rb +4 -2
- data/lib/active_support/concurrency/load_interlock_aware_monitor.rb +42 -3
- data/lib/active_support/concurrency/null_lock.rb +13 -0
- data/lib/active_support/configurable.rb +10 -0
- data/lib/active_support/core_ext/array/conversions.rb +2 -1
- data/lib/active_support/core_ext/array.rb +0 -1
- data/lib/active_support/core_ext/class/subclasses.rb +13 -10
- data/lib/active_support/core_ext/date/calculations.rb +15 -0
- data/lib/active_support/core_ext/date/conversions.rb +2 -1
- data/lib/active_support/core_ext/date.rb +0 -1
- data/lib/active_support/core_ext/date_and_time/calculations.rb +10 -0
- data/lib/active_support/core_ext/date_time/calculations.rb +4 -0
- data/lib/active_support/core_ext/date_time/conversions.rb +6 -2
- data/lib/active_support/core_ext/date_time.rb +0 -1
- data/lib/active_support/core_ext/digest/uuid.rb +1 -10
- data/lib/active_support/core_ext/enumerable.rb +8 -75
- data/lib/active_support/core_ext/erb/util.rb +196 -0
- data/lib/active_support/core_ext/hash/conversions.rb +1 -1
- data/lib/active_support/core_ext/hash/deep_merge.rb +22 -14
- data/lib/active_support/core_ext/hash/deep_transform_values.rb +3 -3
- data/lib/active_support/core_ext/hash/keys.rb +3 -3
- data/lib/active_support/core_ext/integer/inflections.rb +12 -12
- data/lib/active_support/core_ext/module/attribute_accessors.rb +6 -0
- data/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb +34 -16
- data/lib/active_support/core_ext/module/concerning.rb +6 -6
- data/lib/active_support/core_ext/module/delegation.rb +81 -37
- data/lib/active_support/core_ext/module/deprecation.rb +15 -12
- data/lib/active_support/core_ext/module/introspection.rb +0 -1
- data/lib/active_support/core_ext/numeric/bytes.rb +9 -0
- data/lib/active_support/core_ext/numeric/conversions.rb +2 -0
- data/lib/active_support/core_ext/numeric.rb +0 -1
- data/lib/active_support/core_ext/object/deep_dup.rb +16 -0
- data/lib/active_support/core_ext/object/duplicable.rb +25 -16
- data/lib/active_support/core_ext/object/inclusion.rb +13 -5
- data/lib/active_support/core_ext/object/instance_variables.rb +22 -12
- data/lib/active_support/core_ext/object/json.rb +16 -6
- data/lib/active_support/core_ext/object/to_query.rb +0 -2
- data/lib/active_support/core_ext/object/with.rb +44 -0
- data/lib/active_support/core_ext/object/with_options.rb +9 -9
- data/lib/active_support/core_ext/object.rb +1 -0
- data/lib/active_support/core_ext/pathname/blank.rb +16 -0
- data/lib/active_support/core_ext/pathname/existence.rb +2 -0
- data/lib/active_support/core_ext/pathname.rb +1 -0
- data/lib/active_support/core_ext/range/conversions.rb +28 -7
- data/lib/active_support/core_ext/range/overlap.rb +40 -0
- data/lib/active_support/core_ext/range.rb +1 -2
- data/lib/active_support/core_ext/securerandom.rb +24 -12
- data/lib/active_support/core_ext/string/filters.rb +20 -14
- data/lib/active_support/core_ext/string/indent.rb +1 -1
- data/lib/active_support/core_ext/string/inflections.rb +16 -9
- data/lib/active_support/core_ext/string/output_safety.rb +42 -174
- data/lib/active_support/core_ext/thread/backtrace/location.rb +12 -0
- data/lib/active_support/core_ext/time/calculations.rb +22 -2
- data/lib/active_support/core_ext/time/conversions.rb +2 -2
- data/lib/active_support/core_ext/time/zones.rb +7 -8
- data/lib/active_support/core_ext/time.rb +0 -1
- data/lib/active_support/current_attributes.rb +15 -6
- data/lib/active_support/deep_mergeable.rb +53 -0
- data/lib/active_support/dependencies/autoload.rb +17 -12
- data/lib/active_support/deprecation/behaviors.rb +65 -42
- data/lib/active_support/deprecation/constant_accessor.rb +5 -4
- data/lib/active_support/deprecation/deprecators.rb +104 -0
- data/lib/active_support/deprecation/disallowed.rb +6 -8
- data/lib/active_support/deprecation/instance_delegator.rb +31 -4
- data/lib/active_support/deprecation/method_wrappers.rb +6 -23
- data/lib/active_support/deprecation/proxy_wrappers.rb +37 -22
- data/lib/active_support/deprecation/reporting.rb +43 -26
- data/lib/active_support/deprecation.rb +32 -5
- data/lib/active_support/deprecator.rb +7 -0
- data/lib/active_support/descendants_tracker.rb +104 -132
- data/lib/active_support/duration/iso8601_serializer.rb +0 -2
- data/lib/active_support/duration.rb +2 -1
- data/lib/active_support/encrypted_configuration.rb +63 -11
- data/lib/active_support/encrypted_file.rb +16 -12
- data/lib/active_support/environment_inquirer.rb +22 -2
- data/lib/active_support/error_reporter/test_helper.rb +15 -0
- data/lib/active_support/error_reporter.rb +121 -35
- data/lib/active_support/evented_file_update_checker.rb +17 -2
- data/lib/active_support/execution_wrapper.rb +4 -4
- data/lib/active_support/file_update_checker.rb +4 -2
- data/lib/active_support/fork_tracker.rb +10 -2
- data/lib/active_support/gem_version.rb +4 -4
- data/lib/active_support/gzip.rb +2 -0
- data/lib/active_support/hash_with_indifferent_access.rb +35 -17
- data/lib/active_support/html_safe_translation.rb +16 -6
- data/lib/active_support/i18n.rb +1 -1
- data/lib/active_support/i18n_railtie.rb +20 -13
- data/lib/active_support/inflector/inflections.rb +2 -0
- data/lib/active_support/inflector/methods.rb +28 -18
- data/lib/active_support/inflector/transliterate.rb +3 -1
- data/lib/active_support/isolated_execution_state.rb +26 -22
- data/lib/active_support/json/decoding.rb +2 -1
- data/lib/active_support/json/encoding.rb +25 -43
- data/lib/active_support/key_generator.rb +9 -1
- data/lib/active_support/lazy_load_hooks.rb +7 -5
- data/lib/active_support/locale/en.yml +2 -0
- data/lib/active_support/log_subscriber.rb +85 -33
- data/lib/active_support/logger.rb +9 -60
- data/lib/active_support/logger_thread_safe_level.rb +10 -24
- data/lib/active_support/message_encryptor.rb +197 -53
- data/lib/active_support/message_encryptors.rb +141 -0
- data/lib/active_support/message_pack/cache_serializer.rb +23 -0
- data/lib/active_support/message_pack/extensions.rb +292 -0
- data/lib/active_support/message_pack/serializer.rb +63 -0
- data/lib/active_support/message_pack.rb +50 -0
- data/lib/active_support/message_verifier.rb +212 -93
- data/lib/active_support/message_verifiers.rb +135 -0
- data/lib/active_support/messages/codec.rb +65 -0
- data/lib/active_support/messages/metadata.rb +111 -45
- data/lib/active_support/messages/rotation_coordinator.rb +93 -0
- data/lib/active_support/messages/rotator.rb +34 -32
- data/lib/active_support/messages/serializer_with_fallback.rb +158 -0
- data/lib/active_support/multibyte/chars.rb +2 -0
- data/lib/active_support/multibyte/unicode.rb +9 -37
- data/lib/active_support/notifications/fanout.rb +245 -81
- data/lib/active_support/notifications/instrumenter.rb +87 -22
- data/lib/active_support/notifications.rb +3 -3
- data/lib/active_support/number_helper/number_converter.rb +14 -5
- data/lib/active_support/number_helper/number_to_currency_converter.rb +6 -6
- data/lib/active_support/number_helper/number_to_human_size_converter.rb +3 -3
- data/lib/active_support/number_helper/number_to_phone_converter.rb +1 -0
- data/lib/active_support/number_helper.rb +379 -317
- data/lib/active_support/ordered_hash.rb +3 -3
- data/lib/active_support/ordered_options.rb +14 -0
- data/lib/active_support/parameter_filter.rb +103 -84
- data/lib/active_support/proxy_object.rb +2 -0
- data/lib/active_support/railtie.rb +33 -21
- data/lib/active_support/reloader.rb +12 -4
- data/lib/active_support/rescuable.rb +2 -0
- data/lib/active_support/secure_compare_rotator.rb +16 -9
- data/lib/active_support/string_inquirer.rb +3 -1
- data/lib/active_support/subscriber.rb +9 -27
- data/lib/active_support/syntax_error_proxy.rb +60 -0
- data/lib/active_support/tagged_logging.rb +64 -24
- data/lib/active_support/test_case.rb +153 -6
- data/lib/active_support/testing/assertions.rb +26 -10
- data/lib/active_support/testing/autorun.rb +0 -2
- data/lib/active_support/testing/constant_stubbing.rb +32 -0
- data/lib/active_support/testing/deprecation.rb +25 -25
- data/lib/active_support/testing/error_reporter_assertions.rb +107 -0
- data/lib/active_support/testing/isolation.rb +29 -28
- data/lib/active_support/testing/method_call_assertions.rb +21 -8
- data/lib/active_support/testing/parallelize_executor.rb +8 -3
- data/lib/active_support/testing/setup_and_teardown.rb +2 -0
- data/lib/active_support/testing/stream.rb +1 -1
- data/lib/active_support/testing/strict_warnings.rb +39 -0
- data/lib/active_support/testing/time_helpers.rb +37 -15
- data/lib/active_support/time_with_zone.rb +8 -37
- data/lib/active_support/values/time_zone.rb +18 -7
- data/lib/active_support/version.rb +1 -1
- data/lib/active_support/xml_mini/jdom.rb +3 -10
- data/lib/active_support/xml_mini/nokogiri.rb +1 -1
- data/lib/active_support/xml_mini/nokogirisax.rb +1 -1
- data/lib/active_support/xml_mini/rexml.rb +1 -1
- data/lib/active_support/xml_mini.rb +2 -2
- data/lib/active_support.rb +14 -3
- metadata +148 -19
- data/lib/active_support/core_ext/array/deprecated_conversions.rb +0 -25
- data/lib/active_support/core_ext/date/deprecated_conversions.rb +0 -26
- data/lib/active_support/core_ext/date_time/deprecated_conversions.rb +0 -22
- data/lib/active_support/core_ext/numeric/deprecated_conversions.rb +0 -60
- data/lib/active_support/core_ext/range/deprecated_conversions.rb +0 -26
- data/lib/active_support/core_ext/range/include_time_with_zone.rb +0 -7
- data/lib/active_support/core_ext/range/overlaps.rb +0 -10
- data/lib/active_support/core_ext/time/deprecated_conversions.rb +0 -22
- data/lib/active_support/core_ext/uri.rb +0 -5
- data/lib/active_support/per_thread_registry.rb +0 -65
data/lib/active_support/cache.rb
CHANGED
@@ -2,14 +2,15 @@
|
|
2
2
|
|
3
3
|
require "zlib"
|
4
4
|
require "active_support/core_ext/array/extract_options"
|
5
|
-
require "active_support/core_ext/array/wrap"
|
6
5
|
require "active_support/core_ext/enumerable"
|
7
6
|
require "active_support/core_ext/module/attribute_accessors"
|
8
7
|
require "active_support/core_ext/numeric/bytes"
|
9
|
-
require "active_support/core_ext/numeric/time"
|
10
8
|
require "active_support/core_ext/object/to_param"
|
11
9
|
require "active_support/core_ext/object/try"
|
12
10
|
require "active_support/core_ext/string/inflections"
|
11
|
+
require_relative "cache/coder"
|
12
|
+
require_relative "cache/entry"
|
13
|
+
require_relative "cache/serializer_with_fallback"
|
13
14
|
|
14
15
|
module ActiveSupport
|
15
16
|
# See ActiveSupport::Cache::Store for documentation.
|
@@ -22,15 +23,31 @@ module ActiveSupport
|
|
22
23
|
|
23
24
|
# These options mean something to all cache implementations. Individual cache
|
24
25
|
# implementations may support additional options.
|
25
|
-
UNIVERSAL_OPTIONS = [
|
26
|
-
|
27
|
-
|
26
|
+
UNIVERSAL_OPTIONS = [
|
27
|
+
:coder,
|
28
|
+
:compress,
|
29
|
+
:compress_threshold,
|
30
|
+
:compressor,
|
31
|
+
:expire_in,
|
32
|
+
:expired_in,
|
33
|
+
:expires_in,
|
34
|
+
:namespace,
|
35
|
+
:race_condition_ttl,
|
36
|
+
:serializer,
|
37
|
+
:skip_nil,
|
38
|
+
]
|
28
39
|
|
29
40
|
# Mapping of canonical option names to aliases that a store will recognize.
|
30
41
|
OPTION_ALIASES = {
|
31
42
|
expires_in: [:expire_in, :expired_in]
|
32
43
|
}.freeze
|
33
44
|
|
45
|
+
DEFAULT_COMPRESS_LIMIT = 1.kilobyte
|
46
|
+
|
47
|
+
# Raised by coders when the cache entry can't be deserialized.
|
48
|
+
# This error is treated as a cache miss.
|
49
|
+
DeserializationError = Class.new(StandardError)
|
50
|
+
|
34
51
|
module Strategy
|
35
52
|
autoload :LocalCache, "active_support/cache/strategy/local_cache"
|
36
53
|
end
|
@@ -132,6 +149,8 @@ module ActiveSupport
|
|
132
149
|
end
|
133
150
|
end
|
134
151
|
|
152
|
+
# = Active Support \Cache \Store
|
153
|
+
#
|
135
154
|
# An abstract cache store class. There are multiple cache store
|
136
155
|
# implementations, each having its own additional features. See the classes
|
137
156
|
# under the ActiveSupport::Cache module, e.g.
|
@@ -141,8 +160,8 @@ module ActiveSupport
|
|
141
160
|
# Some implementations may not support all methods beyond the basic cache
|
142
161
|
# methods of #fetch, #write, #read, #exist?, and #delete.
|
143
162
|
#
|
144
|
-
# ActiveSupport::Cache::Store can store any Ruby object that is supported
|
145
|
-
# its +coder+'s +dump+ and +load+ methods.
|
163
|
+
# +ActiveSupport::Cache::Store+ can store any Ruby object that is supported
|
164
|
+
# by its +coder+'s +dump+ and +load+ methods.
|
146
165
|
#
|
147
166
|
# cache = ActiveSupport::Cache::MemoryStore.new
|
148
167
|
#
|
@@ -174,24 +193,55 @@ module ActiveSupport
|
|
174
193
|
#
|
175
194
|
class Store
|
176
195
|
cattr_accessor :logger, instance_writer: true
|
196
|
+
cattr_accessor :raise_on_invalid_cache_expiration_time, default: false
|
177
197
|
|
178
198
|
attr_reader :silence, :options
|
179
199
|
alias :silence? :silence
|
180
200
|
|
181
201
|
class << self
|
182
202
|
private
|
203
|
+
DEFAULT_POOL_OPTIONS = { size: 5, timeout: 5 }.freeze
|
204
|
+
private_constant :DEFAULT_POOL_OPTIONS
|
205
|
+
|
183
206
|
def retrieve_pool_options(options)
|
184
|
-
|
185
|
-
pool_options
|
186
|
-
|
207
|
+
if options.key?(:pool)
|
208
|
+
pool_options = options.delete(:pool)
|
209
|
+
elsif options.key?(:pool_size) || options.key?(:pool_timeout)
|
210
|
+
pool_options = {}
|
211
|
+
|
212
|
+
if options.key?(:pool_size)
|
213
|
+
ActiveSupport.deprecator.warn(<<~MSG)
|
214
|
+
Using :pool_size is deprecated and will be removed in Rails 7.2.
|
215
|
+
Use `pool: { size: #{options[:pool_size].inspect} }` instead.
|
216
|
+
MSG
|
217
|
+
pool_options[:size] = options.delete(:pool_size)
|
218
|
+
end
|
219
|
+
|
220
|
+
if options.key?(:pool_timeout)
|
221
|
+
ActiveSupport.deprecator.warn(<<~MSG)
|
222
|
+
Using :pool_timeout is deprecated and will be removed in Rails 7.2.
|
223
|
+
Use `pool: { timeout: #{options[:pool_timeout].inspect} }` instead.
|
224
|
+
MSG
|
225
|
+
pool_options[:timeout] = options.delete(:pool_timeout)
|
226
|
+
end
|
227
|
+
else
|
228
|
+
pool_options = true
|
187
229
|
end
|
188
|
-
end
|
189
230
|
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
231
|
+
case pool_options
|
232
|
+
when false, nil
|
233
|
+
return false
|
234
|
+
when true
|
235
|
+
pool_options = DEFAULT_POOL_OPTIONS
|
236
|
+
when Hash
|
237
|
+
pool_options[:size] = Integer(pool_options[:size]) if pool_options.key?(:size)
|
238
|
+
pool_options[:timeout] = Float(pool_options[:timeout]) if pool_options.key?(:timeout)
|
239
|
+
pool_options = DEFAULT_POOL_OPTIONS.merge(pool_options)
|
240
|
+
else
|
241
|
+
raise TypeError, "Invalid :pool argument, expected Hash, got: #{pool_options.inspect}"
|
242
|
+
end
|
243
|
+
|
244
|
+
pool_options unless pool_options.empty?
|
195
245
|
end
|
196
246
|
end
|
197
247
|
|
@@ -199,21 +249,90 @@ module ActiveSupport
|
|
199
249
|
#
|
200
250
|
# ==== Options
|
201
251
|
#
|
202
|
-
#
|
203
|
-
#
|
204
|
-
# applications.
|
205
|
-
#
|
206
|
-
#
|
207
|
-
#
|
252
|
+
# [+:namespace+]
|
253
|
+
# Sets the namespace for the cache. This option is especially useful if
|
254
|
+
# your application shares a cache with other applications.
|
255
|
+
#
|
256
|
+
# [+:serializer+]
|
257
|
+
# The serializer for cached values. Must respond to +dump+ and +load+.
|
258
|
+
#
|
259
|
+
# The default serializer depends on the cache format version (set via
|
260
|
+
# +config.active_support.cache_format_version+ when using Rails). The
|
261
|
+
# default serializer for each format version includes a fallback
|
262
|
+
# mechanism to deserialize values from any format version. This behavior
|
263
|
+
# makes it easy to migrate between format versions without invalidating
|
264
|
+
# the entire cache.
|
265
|
+
#
|
266
|
+
# You can also specify <tt>serializer: :message_pack</tt> to use a
|
267
|
+
# preconfigured serializer based on ActiveSupport::MessagePack. The
|
268
|
+
# +:message_pack+ serializer includes the same deserialization fallback
|
269
|
+
# mechanism, allowing easy migration from (or to) the default
|
270
|
+
# serializer. The +:message_pack+ serializer may improve performance,
|
271
|
+
# but it requires the +msgpack+ gem.
|
272
|
+
#
|
273
|
+
# [+:compressor+]
|
274
|
+
# The compressor for serialized cache values. Must respond to +deflate+
|
275
|
+
# and +inflate+.
|
276
|
+
#
|
277
|
+
# The default compressor is +Zlib+. To define a new custom compressor
|
278
|
+
# that also decompresses old cache entries, you can check compressed
|
279
|
+
# values for Zlib's <tt>"\x78"</tt> signature:
|
280
|
+
#
|
281
|
+
# module MyCompressor
|
282
|
+
# def self.deflate(dumped)
|
283
|
+
# # compression logic... (make sure result does not start with "\x78"!)
|
284
|
+
# end
|
285
|
+
#
|
286
|
+
# def self.inflate(compressed)
|
287
|
+
# if compressed.start_with?("\x78")
|
288
|
+
# Zlib.inflate(compressed)
|
289
|
+
# else
|
290
|
+
# # decompression logic...
|
291
|
+
# end
|
292
|
+
# end
|
293
|
+
# end
|
294
|
+
#
|
295
|
+
# ActiveSupport::Cache.lookup_store(:redis_cache_store, compressor: MyCompressor)
|
296
|
+
#
|
297
|
+
# [+:coder+]
|
298
|
+
# The coder for serializing and (optionally) compressing cache entries.
|
299
|
+
# Must respond to +dump+ and +load+.
|
300
|
+
#
|
301
|
+
# The default coder composes the serializer and compressor, and includes
|
302
|
+
# some performance optimizations. If you only need to override the
|
303
|
+
# serializer or compressor, you should specify the +:serializer+ or
|
304
|
+
# +:compressor+ options instead.
|
305
|
+
#
|
306
|
+
# If the store can handle cache entries directly, you may also specify
|
307
|
+
# <tt>coder: nil</tt> to omit the serializer, compressor, and coder. For
|
308
|
+
# example, if you are using ActiveSupport::Cache::MemoryStore and can
|
309
|
+
# guarantee that cache values will not be mutated, you can specify
|
310
|
+
# <tt>coder: nil</tt> to avoid the overhead of safeguarding against
|
311
|
+
# mutation.
|
312
|
+
#
|
313
|
+
# The +:coder+ option is mutally exclusive with the +:serializer+ and
|
314
|
+
# +:compressor+ options. Specifying them together will raise an
|
315
|
+
# +ArgumentError+.
|
208
316
|
#
|
209
317
|
# Any other specified options are treated as default options for the
|
210
318
|
# relevant cache operations, such as #read, #write, and #fetch.
|
211
319
|
def initialize(options = nil)
|
212
|
-
@options = options ? normalize_options(options) : {}
|
320
|
+
@options = options ? validate_options(normalize_options(options)) : {}
|
321
|
+
|
213
322
|
@options[:compress] = true unless @options.key?(:compress)
|
214
|
-
@options[:compress_threshold]
|
323
|
+
@options[:compress_threshold] ||= DEFAULT_COMPRESS_LIMIT
|
324
|
+
|
325
|
+
@coder = @options.delete(:coder) do
|
326
|
+
legacy_serializer = Cache.format_version < 7.1 && !@options[:serializer]
|
327
|
+
serializer = @options.delete(:serializer) || default_serializer
|
328
|
+
serializer = Cache::SerializerWithFallback[serializer] if serializer.is_a?(Symbol)
|
329
|
+
compressor = @options.delete(:compressor) { Zlib }
|
330
|
+
|
331
|
+
Cache::Coder.new(serializer, compressor, legacy_serializer: legacy_serializer)
|
332
|
+
end
|
333
|
+
|
334
|
+
@coder ||= Cache::SerializerWithFallback[:passthrough]
|
215
335
|
|
216
|
-
@coder = @options.delete(:coder) { default_coder } || NullCoder
|
217
336
|
@coder_supports_compression = @coder.respond_to?(:dump_compressed)
|
218
337
|
end
|
219
338
|
|
@@ -251,8 +370,8 @@ module ActiveSupport
|
|
251
370
|
#
|
252
371
|
# ==== Options
|
253
372
|
#
|
254
|
-
# Internally, +fetch+ calls
|
255
|
-
# miss. Thus, +fetch+ supports the same options as #read and #write.
|
373
|
+
# Internally, +fetch+ calls +read_entry+, and calls +write_entry+ on a
|
374
|
+
# cache miss. Thus, +fetch+ supports the same options as #read and #write.
|
256
375
|
# Additionally, +fetch+ supports the following options:
|
257
376
|
#
|
258
377
|
# * <tt>force: true</tt> - Forces a cache "miss," meaning we treat the
|
@@ -318,18 +437,42 @@ module ActiveSupport
|
|
318
437
|
# val_1 # => "new value 1"
|
319
438
|
# val_2 # => "original value"
|
320
439
|
#
|
440
|
+
# ==== Dynamic Options
|
441
|
+
#
|
442
|
+
# In some cases it may be necessary to dynamically compute options based
|
443
|
+
# on the cached value. To support this, an ActiveSupport::Cache::WriteOptions
|
444
|
+
# instance is passed as the second argument to the block. For example:
|
445
|
+
#
|
446
|
+
# cache.fetch("authentication-token:#{user.id}") do |key, options|
|
447
|
+
# token = authenticate_to_service
|
448
|
+
# options.expires_at = token.expires_at
|
449
|
+
# token
|
450
|
+
# end
|
451
|
+
#
|
321
452
|
def fetch(name, options = nil, &block)
|
322
453
|
if block_given?
|
323
454
|
options = merged_options(options)
|
324
455
|
key = normalize_key(name, options)
|
325
456
|
|
326
457
|
entry = nil
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
|
458
|
+
unless options[:force]
|
459
|
+
instrument(:read, name, options) do |payload|
|
460
|
+
cached_entry = read_entry(key, **options, event: payload)
|
461
|
+
entry = handle_expired_entry(cached_entry, key, options)
|
462
|
+
if entry
|
463
|
+
if entry.mismatched?(normalize_version(name, options))
|
464
|
+
entry = nil
|
465
|
+
else
|
466
|
+
begin
|
467
|
+
entry.value
|
468
|
+
rescue DeserializationError
|
469
|
+
entry = nil
|
470
|
+
end
|
471
|
+
end
|
472
|
+
end
|
473
|
+
payload[:super_operation] = :fetch if payload
|
474
|
+
payload[:hit] = !!entry if payload
|
475
|
+
end
|
333
476
|
end
|
334
477
|
|
335
478
|
if entry
|
@@ -354,6 +497,7 @@ module ActiveSupport
|
|
354
497
|
#
|
355
498
|
# ==== Options
|
356
499
|
#
|
500
|
+
# * +:namespace+ - Replace the store namespace for this call.
|
357
501
|
# * +:version+ - Specifies a version for the cache entry. If the cached
|
358
502
|
# version does not match the requested version, the read will be treated
|
359
503
|
# as a cache miss. This feature is used to support recyclable cache keys.
|
@@ -377,7 +521,12 @@ module ActiveSupport
|
|
377
521
|
nil
|
378
522
|
else
|
379
523
|
payload[:hit] = true if payload
|
380
|
-
|
524
|
+
begin
|
525
|
+
entry.value
|
526
|
+
rescue DeserializationError
|
527
|
+
payload[:hit] = false
|
528
|
+
nil
|
529
|
+
end
|
381
530
|
end
|
382
531
|
else
|
383
532
|
payload[:hit] = false if payload
|
@@ -393,10 +542,12 @@ module ActiveSupport
|
|
393
542
|
#
|
394
543
|
# Returns a hash mapping the names provided to the values found.
|
395
544
|
def read_multi(*names)
|
545
|
+
return {} if names.empty?
|
546
|
+
|
396
547
|
options = names.extract_options!
|
397
548
|
options = merged_options(options)
|
398
549
|
|
399
|
-
|
550
|
+
instrument_multi :read_multi, names, options do |payload|
|
400
551
|
read_multi_entries(names, **options, event: payload).tap do |results|
|
401
552
|
payload[:hits] = results.keys
|
402
553
|
end
|
@@ -405,9 +556,11 @@ module ActiveSupport
|
|
405
556
|
|
406
557
|
# Cache Storage API to write multiple values at once.
|
407
558
|
def write_multi(hash, options = nil)
|
559
|
+
return hash if hash.empty?
|
560
|
+
|
408
561
|
options = merged_options(options)
|
409
562
|
|
410
|
-
|
563
|
+
instrument_multi :write_multi, hash, options do |payload|
|
411
564
|
entries = hash.each_with_object({}) do |(name, value), memo|
|
412
565
|
memo[normalize_key(name, options)] = Entry.new(value, **options.merge(version: normalize_version(name, options)))
|
413
566
|
end
|
@@ -433,7 +586,8 @@ module ActiveSupport
|
|
433
586
|
# # => { "bim" => "bam",
|
434
587
|
# # "unknown_key" => "Fallback value for key: unknown_key" }
|
435
588
|
#
|
436
|
-
#
|
589
|
+
# You may also specify additional options via the +options+ argument. See #fetch for details.
|
590
|
+
# Other options are passed to the underlying cache implementation. For example:
|
437
591
|
#
|
438
592
|
# cache.fetch_multi("fizz", expires_in: 5.seconds) do |key|
|
439
593
|
# "buzz"
|
@@ -446,16 +600,23 @@ module ActiveSupport
|
|
446
600
|
# # => nil
|
447
601
|
def fetch_multi(*names)
|
448
602
|
raise ArgumentError, "Missing block: `Cache#fetch_multi` requires a block." unless block_given?
|
603
|
+
return {} if names.empty?
|
449
604
|
|
450
605
|
options = names.extract_options!
|
451
606
|
options = merged_options(options)
|
452
607
|
|
453
|
-
|
454
|
-
|
608
|
+
instrument_multi :read_multi, names, options do |payload|
|
609
|
+
if options[:force]
|
610
|
+
reads = {}
|
611
|
+
else
|
612
|
+
reads = read_multi_entries(names, **options)
|
613
|
+
end
|
614
|
+
|
455
615
|
writes = {}
|
456
616
|
ordered = names.index_with do |name|
|
457
617
|
reads.fetch(name) { writes[name] = yield(name) }
|
458
618
|
end
|
619
|
+
writes.compact! if options[:skip_nil]
|
459
620
|
|
460
621
|
payload[:hits] = reads.keys
|
461
622
|
payload[:super_operation] = :fetch_multi
|
@@ -508,7 +669,8 @@ module ActiveSupport
|
|
508
669
|
end
|
509
670
|
end
|
510
671
|
|
511
|
-
# Deletes an entry in the cache. Returns +true+ if an entry is deleted
|
672
|
+
# Deletes an entry in the cache. Returns +true+ if an entry is deleted
|
673
|
+
# and +false+ otherwise.
|
512
674
|
#
|
513
675
|
# Options are passed to the underlying cache implementation.
|
514
676
|
def delete(name, options = nil)
|
@@ -519,14 +681,17 @@ module ActiveSupport
|
|
519
681
|
end
|
520
682
|
end
|
521
683
|
|
522
|
-
# Deletes multiple entries in the cache.
|
684
|
+
# Deletes multiple entries in the cache. Returns the number of deleted
|
685
|
+
# entries.
|
523
686
|
#
|
524
687
|
# Options are passed to the underlying cache implementation.
|
525
688
|
def delete_multi(names, options = nil)
|
689
|
+
return 0 if names.empty?
|
690
|
+
|
526
691
|
options = merged_options(options)
|
527
692
|
names.map! { |key| normalize_key(key, options) }
|
528
693
|
|
529
|
-
|
694
|
+
instrument_multi :delete_multi, names do
|
530
695
|
delete_multi_entries(names, **options)
|
531
696
|
end
|
532
697
|
end
|
@@ -594,8 +759,23 @@ module ActiveSupport
|
|
594
759
|
end
|
595
760
|
|
596
761
|
private
|
597
|
-
def
|
598
|
-
|
762
|
+
def default_serializer
|
763
|
+
case Cache.format_version
|
764
|
+
when 6.1
|
765
|
+
ActiveSupport.deprecator.warn <<~EOM
|
766
|
+
Support for `config.active_support.cache_format_version = 6.1` has been deprecated and will be removed in Rails 7.2.
|
767
|
+
|
768
|
+
Check the Rails upgrade guide at https://guides.rubyonrails.org/upgrading_ruby_on_rails.html#new-activesupport-cache-serialization-format
|
769
|
+
for more information on how to upgrade.
|
770
|
+
EOM
|
771
|
+
Cache::SerializerWithFallback[:marshal_6_1]
|
772
|
+
when 7.0
|
773
|
+
Cache::SerializerWithFallback[:marshal_7_0]
|
774
|
+
when 7.1
|
775
|
+
Cache::SerializerWithFallback[:marshal_7_1]
|
776
|
+
else
|
777
|
+
raise ArgumentError, "Unrecognized ActiveSupport::Cache.format_version: #{Cache.format_version.inspect}"
|
778
|
+
end
|
599
779
|
end
|
600
780
|
|
601
781
|
# Adds the namespace defined in the options to a pattern designed to
|
@@ -632,14 +812,16 @@ module ActiveSupport
|
|
632
812
|
def serialize_entry(entry, **options)
|
633
813
|
options = merged_options(options)
|
634
814
|
if @coder_supports_compression && options[:compress]
|
635
|
-
@coder.dump_compressed(entry, options[:compress_threshold]
|
815
|
+
@coder.dump_compressed(entry, options[:compress_threshold])
|
636
816
|
else
|
637
817
|
@coder.dump(entry)
|
638
818
|
end
|
639
819
|
end
|
640
820
|
|
641
|
-
def deserialize_entry(payload)
|
821
|
+
def deserialize_entry(payload, **)
|
642
822
|
payload.nil? ? nil : @coder.load(payload)
|
823
|
+
rescue DeserializationError
|
824
|
+
nil
|
643
825
|
end
|
644
826
|
|
645
827
|
# Reads multiple entries from the cache implementation. Subclasses MAY
|
@@ -685,6 +867,22 @@ module ActiveSupport
|
|
685
867
|
def merged_options(call_options)
|
686
868
|
if call_options
|
687
869
|
call_options = normalize_options(call_options)
|
870
|
+
if call_options.key?(:expires_in) && call_options.key?(:expires_at)
|
871
|
+
raise ArgumentError, "Either :expires_in or :expires_at can be supplied, but not both"
|
872
|
+
end
|
873
|
+
|
874
|
+
expires_at = call_options.delete(:expires_at)
|
875
|
+
call_options[:expires_in] = (expires_at - Time.now) if expires_at
|
876
|
+
|
877
|
+
if call_options[:expires_in].is_a?(Time)
|
878
|
+
expires_in = call_options[:expires_in]
|
879
|
+
raise ArgumentError.new("expires_in parameter should not be a Time. Did you mean to use expires_at? Got: #{expires_in}")
|
880
|
+
end
|
881
|
+
if call_options[:expires_in]&.negative?
|
882
|
+
expires_in = call_options.delete(:expires_in)
|
883
|
+
handle_invalid_expires_in("Cache expiration time is invalid, cannot be negative: #{expires_in}")
|
884
|
+
end
|
885
|
+
|
688
886
|
if options.empty?
|
689
887
|
call_options
|
690
888
|
else
|
@@ -695,6 +893,16 @@ module ActiveSupport
|
|
695
893
|
end
|
696
894
|
end
|
697
895
|
|
896
|
+
def handle_invalid_expires_in(message)
|
897
|
+
error = ArgumentError.new(message)
|
898
|
+
if ActiveSupport::Cache::Store.raise_on_invalid_cache_expiration_time
|
899
|
+
raise error
|
900
|
+
else
|
901
|
+
ActiveSupport.error_reporter&.report(error, handled: true, severity: :warning)
|
902
|
+
logger.error("#{error.class}: #{error.message}") if logger
|
903
|
+
end
|
904
|
+
end
|
905
|
+
|
698
906
|
# Normalize aliased options to their canonical form
|
699
907
|
def normalize_options(options)
|
700
908
|
options = options.dup
|
@@ -707,10 +915,31 @@ module ActiveSupport
|
|
707
915
|
options
|
708
916
|
end
|
709
917
|
|
710
|
-
|
711
|
-
|
918
|
+
def validate_options(options)
|
919
|
+
if options.key?(:coder) && options[:serializer]
|
920
|
+
raise ArgumentError, "Cannot specify :serializer and :coder options together"
|
921
|
+
end
|
922
|
+
|
923
|
+
if options.key?(:coder) && options[:compressor]
|
924
|
+
raise ArgumentError, "Cannot specify :compressor and :coder options together"
|
925
|
+
end
|
926
|
+
|
927
|
+
if Cache.format_version < 7.1 && !options[:serializer] && options[:compressor]
|
928
|
+
raise ArgumentError, "Cannot specify :compressor option when using" \
|
929
|
+
" default serializer and cache format version is < 7.1"
|
930
|
+
end
|
931
|
+
|
932
|
+
options
|
933
|
+
end
|
934
|
+
|
935
|
+
# Expands and namespaces the cache key.
|
936
|
+
# Raises an exception when the key is +nil+ or an empty string.
|
937
|
+
# May be overridden by cache stores to do additional normalization.
|
712
938
|
def normalize_key(key, options = nil)
|
713
|
-
|
939
|
+
str_key = expanded_key(key)
|
940
|
+
raise(ArgumentError, "key cannot be blank") if !str_key || str_key.empty?
|
941
|
+
|
942
|
+
namespace_key str_key, options
|
714
943
|
end
|
715
944
|
|
716
945
|
# Prefix the key with a namespace string:
|
@@ -773,14 +1002,33 @@ module ActiveSupport
|
|
773
1002
|
end
|
774
1003
|
end
|
775
1004
|
|
776
|
-
def instrument(operation, key, options = nil)
|
1005
|
+
def instrument(operation, key, options = nil, &block)
|
1006
|
+
_instrument(operation, key: key, options: options, &block)
|
1007
|
+
end
|
1008
|
+
|
1009
|
+
def instrument_multi(operation, keys, options = nil, &block)
|
1010
|
+
_instrument(operation, multi: true, key: keys, options: options, &block)
|
1011
|
+
end
|
1012
|
+
|
1013
|
+
def _instrument(operation, multi: false, options: nil, **payload, &block)
|
777
1014
|
if logger && logger.debug? && !silence?
|
778
|
-
|
1015
|
+
debug_key =
|
1016
|
+
if multi
|
1017
|
+
": #{payload[:key].size} key(s) specified"
|
1018
|
+
elsif payload[:key]
|
1019
|
+
": #{normalize_key(payload[:key], options)}"
|
1020
|
+
end
|
1021
|
+
|
1022
|
+
debug_options = " (#{options.inspect})" unless options.blank?
|
1023
|
+
|
1024
|
+
logger.debug "Cache #{operation}#{debug_key}#{debug_options}"
|
779
1025
|
end
|
780
1026
|
|
781
|
-
payload =
|
1027
|
+
payload[:store] = self.class.name
|
782
1028
|
payload.merge!(options) if options.is_a?(Hash)
|
783
|
-
ActiveSupport::Notifications.instrument("cache_#{operation}.active_support", payload)
|
1029
|
+
ActiveSupport::Notifications.instrument("cache_#{operation}.active_support", payload) do
|
1030
|
+
block&.call(payload)
|
1031
|
+
end
|
784
1032
|
end
|
785
1033
|
|
786
1034
|
def handle_expired_entry(entry, key, options)
|
@@ -790,7 +1038,8 @@ module ActiveSupport
|
|
790
1038
|
# When an entry has a positive :race_condition_ttl defined, put the stale entry back into the cache
|
791
1039
|
# for a brief period while the entry is being recalculated.
|
792
1040
|
entry.expires_at = Time.now.to_f + race_ttl
|
793
|
-
|
1041
|
+
options[:expires_in] = race_ttl * 2
|
1042
|
+
write_entry(key, entry, **options)
|
794
1043
|
else
|
795
1044
|
delete_entry(key, **options)
|
796
1045
|
end
|
@@ -800,13 +1049,15 @@ module ActiveSupport
|
|
800
1049
|
end
|
801
1050
|
|
802
1051
|
def get_entry_value(entry, name, options)
|
803
|
-
instrument(:fetch_hit, name, options)
|
1052
|
+
instrument(:fetch_hit, name, options)
|
804
1053
|
entry.value
|
805
1054
|
end
|
806
1055
|
|
807
1056
|
def save_block_result_to_cache(name, options)
|
1057
|
+
options = options.dup
|
1058
|
+
|
808
1059
|
result = instrument(:generate, name, options) do
|
809
|
-
yield(name)
|
1060
|
+
yield(name, WriteOptions.new(options))
|
810
1061
|
end
|
811
1062
|
|
812
1063
|
write(name, result, options) unless result.nil? && options[:skip_nil]
|
@@ -814,217 +1065,46 @@ module ActiveSupport
|
|
814
1065
|
end
|
815
1066
|
end
|
816
1067
|
|
817
|
-
|
818
|
-
|
819
|
-
|
820
|
-
|
821
|
-
|
822
|
-
|
823
|
-
|
824
|
-
def dump_compressed(entry, threshold)
|
825
|
-
entry.compressed(threshold)
|
826
|
-
end
|
827
|
-
|
828
|
-
def load(payload)
|
829
|
-
payload
|
830
|
-
end
|
831
|
-
end
|
832
|
-
|
833
|
-
module Coders # :nodoc:
|
834
|
-
MARK_61 = "\x04\b".b.freeze # The one set by Marshal.
|
835
|
-
MARK_70_UNCOMPRESSED = "\x00".b.freeze
|
836
|
-
MARK_70_COMPRESSED = "\x01".b.freeze
|
837
|
-
|
838
|
-
class << self
|
839
|
-
def [](version)
|
840
|
-
case version
|
841
|
-
when 6.1
|
842
|
-
Rails61Coder
|
843
|
-
when 7.0
|
844
|
-
Rails70Coder
|
845
|
-
else
|
846
|
-
raise ArgumentError, "Unknown ActiveSupport::Cache.format_version: #{Cache.format_version.inspect}"
|
847
|
-
end
|
848
|
-
end
|
849
|
-
end
|
850
|
-
|
851
|
-
module Loader
|
852
|
-
extend self
|
853
|
-
|
854
|
-
def load(payload)
|
855
|
-
if !payload.is_a?(String)
|
856
|
-
ActiveSupport::Cache::Store.logger&.warn %{Payload wasn't a string, was #{payload.class.name} - couldn't unmarshal, so returning nil."}
|
857
|
-
|
858
|
-
return nil
|
859
|
-
elsif payload.start_with?(MARK_70_UNCOMPRESSED)
|
860
|
-
members = Marshal.load(payload.byteslice(1..-1))
|
861
|
-
elsif payload.start_with?(MARK_70_COMPRESSED)
|
862
|
-
members = Marshal.load(Zlib::Inflate.inflate(payload.byteslice(1..-1)))
|
863
|
-
elsif payload.start_with?(MARK_61)
|
864
|
-
return Marshal.load(payload)
|
865
|
-
else
|
866
|
-
ActiveSupport::Cache::Store.logger&.warn %{Invalid cache prefix: #{payload.byteslice(0).inspect}, expected "\\x00" or "\\x01"}
|
867
|
-
|
868
|
-
return nil
|
869
|
-
end
|
870
|
-
Entry.unpack(members)
|
871
|
-
end
|
872
|
-
end
|
873
|
-
|
874
|
-
module Rails61Coder
|
875
|
-
include Loader
|
876
|
-
extend self
|
877
|
-
|
878
|
-
def dump(entry)
|
879
|
-
Marshal.dump(entry)
|
880
|
-
end
|
881
|
-
|
882
|
-
def dump_compressed(entry, threshold)
|
883
|
-
Marshal.dump(entry.compressed(threshold))
|
884
|
-
end
|
885
|
-
end
|
886
|
-
|
887
|
-
module Rails70Coder
|
888
|
-
include Loader
|
889
|
-
extend self
|
890
|
-
|
891
|
-
def dump(entry)
|
892
|
-
MARK_70_UNCOMPRESSED + Marshal.dump(entry.pack)
|
893
|
-
end
|
894
|
-
|
895
|
-
def dump_compressed(entry, threshold)
|
896
|
-
payload = Marshal.dump(entry.pack)
|
897
|
-
if payload.bytesize >= threshold
|
898
|
-
compressed_payload = Zlib::Deflate.deflate(payload)
|
899
|
-
if compressed_payload.bytesize < payload.bytesize
|
900
|
-
return MARK_70_COMPRESSED + compressed_payload
|
901
|
-
end
|
902
|
-
end
|
903
|
-
|
904
|
-
MARK_70_UNCOMPRESSED + payload
|
905
|
-
end
|
906
|
-
end
|
907
|
-
end
|
908
|
-
|
909
|
-
# This class is used to represent cache entries. Cache entries have a value, an optional
|
910
|
-
# expiration time, and an optional version. The expiration time is used to support the :race_condition_ttl option
|
911
|
-
# on the cache. The version is used to support the :version option on the cache for rejecting
|
912
|
-
# mismatches.
|
913
|
-
#
|
914
|
-
# Since cache entries in most instances will be serialized, the internals of this class are highly optimized
|
915
|
-
# using short instance variable names that are lazily defined.
|
916
|
-
class Entry # :nodoc:
|
917
|
-
class << self
|
918
|
-
def unpack(members)
|
919
|
-
new(members[0], expires_at: members[1], version: members[2])
|
920
|
-
end
|
1068
|
+
# Enables the dynamic configuration of Cache entry options while ensuring
|
1069
|
+
# that conflicting options are not both set. When a block is given to
|
1070
|
+
# ActiveSupport::Cache::Store#fetch, the second argument will be an
|
1071
|
+
# instance of +WriteOptions+.
|
1072
|
+
class WriteOptions
|
1073
|
+
def initialize(options) # :nodoc:
|
1074
|
+
@options = options
|
921
1075
|
end
|
922
1076
|
|
923
|
-
|
924
|
-
|
925
|
-
# Creates a new cache entry for the specified value. Options supported are
|
926
|
-
# +:compressed+, +:version+, +:expires_at+ and +:expires_in+.
|
927
|
-
def initialize(value, compressed: false, version: nil, expires_in: nil, expires_at: nil, **)
|
928
|
-
@value = value
|
929
|
-
@version = version
|
930
|
-
@created_at = 0.0
|
931
|
-
@expires_in = expires_at&.to_f || expires_in && (expires_in.to_f + Time.now.to_f)
|
932
|
-
@compressed = true if compressed
|
1077
|
+
def version
|
1078
|
+
@options[:version]
|
933
1079
|
end
|
934
1080
|
|
935
|
-
def
|
936
|
-
|
1081
|
+
def version=(version)
|
1082
|
+
@options[:version] = version
|
937
1083
|
end
|
938
1084
|
|
939
|
-
def
|
940
|
-
@
|
1085
|
+
def expires_in
|
1086
|
+
@options[:expires_in]
|
941
1087
|
end
|
942
1088
|
|
943
|
-
#
|
944
|
-
#
|
945
|
-
|
946
|
-
|
1089
|
+
# Sets the Cache entry's +expires_in+ value. If an +expires_at+ option was
|
1090
|
+
# previously set, this will unset it since +expires_in+ and +expires_at+
|
1091
|
+
# cannot both be set.
|
1092
|
+
def expires_in=(expires_in)
|
1093
|
+
@options.delete(:expires_at)
|
1094
|
+
@options[:expires_in] = expires_in
|
947
1095
|
end
|
948
1096
|
|
949
1097
|
def expires_at
|
950
|
-
@
|
951
|
-
end
|
952
|
-
|
953
|
-
def expires_at=(value)
|
954
|
-
if value
|
955
|
-
@expires_in = value.to_f - @created_at
|
956
|
-
else
|
957
|
-
@expires_in = nil
|
958
|
-
end
|
959
|
-
end
|
960
|
-
|
961
|
-
# Returns the size of the cached value. This could be less than
|
962
|
-
# <tt>value.bytesize</tt> if the data is compressed.
|
963
|
-
def bytesize
|
964
|
-
case value
|
965
|
-
when NilClass
|
966
|
-
0
|
967
|
-
when String
|
968
|
-
@value.bytesize
|
969
|
-
else
|
970
|
-
@s ||= Marshal.dump(@value).bytesize
|
971
|
-
end
|
972
|
-
end
|
973
|
-
|
974
|
-
def compressed? # :nodoc:
|
975
|
-
defined?(@compressed)
|
976
|
-
end
|
977
|
-
|
978
|
-
def compressed(compress_threshold)
|
979
|
-
return self if compressed?
|
980
|
-
|
981
|
-
case @value
|
982
|
-
when nil, true, false, Numeric
|
983
|
-
uncompressed_size = 0
|
984
|
-
when String
|
985
|
-
uncompressed_size = @value.bytesize
|
986
|
-
else
|
987
|
-
serialized = Marshal.dump(@value)
|
988
|
-
uncompressed_size = serialized.bytesize
|
989
|
-
end
|
990
|
-
|
991
|
-
if uncompressed_size >= compress_threshold
|
992
|
-
serialized ||= Marshal.dump(@value)
|
993
|
-
compressed = Zlib::Deflate.deflate(serialized)
|
994
|
-
|
995
|
-
if compressed.bytesize < uncompressed_size
|
996
|
-
return Entry.new(compressed, compressed: true, expires_at: expires_at, version: version)
|
997
|
-
end
|
998
|
-
end
|
999
|
-
self
|
1000
|
-
end
|
1001
|
-
|
1002
|
-
def local?
|
1003
|
-
false
|
1098
|
+
@options[:expires_at]
|
1004
1099
|
end
|
1005
1100
|
|
1006
|
-
#
|
1007
|
-
#
|
1008
|
-
|
1009
|
-
|
1010
|
-
|
1011
|
-
|
1012
|
-
else
|
1013
|
-
@value = Marshal.load(Marshal.dump(@value))
|
1014
|
-
end
|
1015
|
-
end
|
1101
|
+
# Sets the Cache entry's +expires_at+ value. If an +expires_in+ option was
|
1102
|
+
# previously set, this will unset it since +expires_at+ and +expires_in+
|
1103
|
+
# cannot both be set.
|
1104
|
+
def expires_at=(expires_at)
|
1105
|
+
@options.delete(:expires_in)
|
1106
|
+
@options[:expires_at] = expires_at
|
1016
1107
|
end
|
1017
|
-
|
1018
|
-
def pack
|
1019
|
-
members = [value, expires_at, version]
|
1020
|
-
members.pop while !members.empty? && members.last.nil?
|
1021
|
-
members
|
1022
|
-
end
|
1023
|
-
|
1024
|
-
private
|
1025
|
-
def uncompress(value)
|
1026
|
-
Marshal.load(Zlib::Inflate.inflate(value))
|
1027
|
-
end
|
1028
1108
|
end
|
1029
1109
|
end
|
1030
1110
|
end
|