activesupport 6.0.0 → 6.1.3
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 +381 -349
- data/MIT-LICENSE +1 -1
- data/README.rdoc +2 -2
- data/lib/active_support.rb +13 -1
- data/lib/active_support/array_inquirer.rb +4 -2
- data/lib/active_support/backtrace_cleaner.rb +3 -4
- data/lib/active_support/benchmarkable.rb +1 -1
- data/lib/active_support/cache.rb +101 -59
- data/lib/active_support/cache/file_store.rb +11 -11
- data/lib/active_support/cache/mem_cache_store.rb +34 -33
- data/lib/active_support/cache/memory_store.rb +52 -31
- data/lib/active_support/cache/null_store.rb +3 -3
- data/lib/active_support/cache/redis_cache_store.rb +38 -33
- data/lib/active_support/cache/strategy/local_cache.rb +41 -26
- data/lib/active_support/callbacks.rb +65 -59
- data/lib/active_support/concern.rb +46 -2
- data/lib/active_support/concurrency/load_interlock_aware_monitor.rb +18 -0
- data/lib/active_support/concurrency/share_lock.rb +0 -1
- data/lib/active_support/configurable.rb +3 -3
- data/lib/active_support/configuration_file.rb +46 -0
- data/lib/active_support/core_ext.rb +1 -1
- data/lib/active_support/core_ext/array/conversions.rb +5 -5
- data/lib/active_support/core_ext/benchmark.rb +2 -2
- data/lib/active_support/core_ext/class/attribute.rb +34 -44
- data/lib/active_support/core_ext/class/subclasses.rb +17 -38
- data/lib/active_support/core_ext/date/conversions.rb +2 -1
- data/lib/active_support/core_ext/date_and_time/calculations.rb +13 -0
- 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/conversions.rb +0 -1
- data/lib/active_support/core_ext/enumerable.rb +76 -4
- data/lib/active_support/core_ext/hash/conversions.rb +3 -3
- data/lib/active_support/core_ext/hash/deep_transform_values.rb +1 -1
- data/lib/active_support/core_ext/hash/except.rb +1 -1
- data/lib/active_support/core_ext/hash/keys.rb +1 -1
- data/lib/active_support/core_ext/hash/slice.rb +3 -2
- data/lib/active_support/core_ext/load_error.rb +1 -1
- data/lib/active_support/core_ext/marshal.rb +2 -0
- data/lib/active_support/core_ext/module/attr_internal.rb +2 -2
- data/lib/active_support/core_ext/module/attribute_accessors.rb +23 -29
- data/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb +8 -4
- data/lib/active_support/core_ext/module/concerning.rb +8 -2
- data/lib/active_support/core_ext/module/delegation.rb +46 -29
- data/lib/active_support/core_ext/module/introspection.rb +2 -25
- data/lib/active_support/core_ext/name_error.rb +29 -2
- data/lib/active_support/core_ext/numeric/conversions.rb +22 -18
- data/lib/active_support/core_ext/object/deep_dup.rb +1 -1
- data/lib/active_support/core_ext/object/json.rb +13 -2
- data/lib/active_support/core_ext/object/try.rb +4 -2
- data/lib/active_support/core_ext/range/compare_range.rb +15 -3
- data/lib/active_support/core_ext/range/each.rb +0 -1
- data/lib/active_support/core_ext/range/include_time_with_zone.rb +8 -3
- data/lib/active_support/core_ext/regexp.rb +8 -1
- data/lib/active_support/core_ext/string/access.rb +5 -24
- data/lib/active_support/core_ext/string/conversions.rb +1 -0
- data/lib/active_support/core_ext/string/inflections.rb +38 -4
- data/lib/active_support/core_ext/string/inquiry.rb +1 -0
- data/lib/active_support/core_ext/string/multibyte.rb +2 -2
- data/lib/active_support/core_ext/string/output_safety.rb +12 -11
- data/lib/active_support/core_ext/string/starts_ends_with.rb +2 -2
- data/lib/active_support/core_ext/symbol.rb +3 -0
- data/lib/active_support/core_ext/symbol/starts_ends_with.rb +14 -0
- data/lib/active_support/core_ext/time/calculations.rb +27 -3
- data/lib/active_support/core_ext/time/conversions.rb +2 -0
- data/lib/active_support/core_ext/uri.rb +5 -1
- data/lib/active_support/current_attributes.rb +7 -2
- data/lib/active_support/current_attributes/test_helper.rb +13 -0
- data/lib/active_support/dependencies.rb +42 -20
- data/lib/active_support/dependencies/zeitwerk_integration.rb +9 -2
- data/lib/active_support/deprecation.rb +6 -1
- data/lib/active_support/deprecation/behaviors.rb +15 -2
- 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 +13 -6
- data/lib/active_support/deprecation/proxy_wrappers.rb +6 -2
- data/lib/active_support/deprecation/reporting.rb +50 -7
- data/lib/active_support/descendants_tracker.rb +6 -3
- data/lib/active_support/duration.rb +86 -35
- data/lib/active_support/duration/iso8601_parser.rb +0 -1
- data/lib/active_support/duration/iso8601_serializer.rb +15 -10
- data/lib/active_support/encrypted_file.rb +20 -3
- data/lib/active_support/environment_inquirer.rb +20 -0
- data/lib/active_support/evented_file_update_checker.rb +69 -134
- data/lib/active_support/file_update_checker.rb +0 -1
- data/lib/active_support/fork_tracker.rb +62 -0
- data/lib/active_support/gem_version.rb +2 -2
- data/lib/active_support/hash_with_indifferent_access.rb +43 -24
- data/lib/active_support/i18n_railtie.rb +15 -16
- data/lib/active_support/inflector/inflections.rb +1 -3
- data/lib/active_support/inflector/methods.rb +36 -33
- data/lib/active_support/inflector/transliterate.rb +4 -4
- data/lib/active_support/json/decoding.rb +4 -5
- data/lib/active_support/json/encoding.rb +5 -1
- data/lib/active_support/key_generator.rb +1 -1
- data/lib/active_support/lazy_load_hooks.rb +0 -1
- data/lib/active_support/locale/en.rb +4 -2
- data/lib/active_support/locale/en.yml +7 -3
- data/lib/active_support/log_subscriber.rb +8 -1
- data/lib/active_support/logger.rb +2 -2
- data/lib/active_support/logger_silence.rb +2 -26
- data/lib/active_support/logger_thread_safe_level.rb +34 -12
- data/lib/active_support/message_encryptor.rb +5 -8
- data/lib/active_support/message_verifier.rb +7 -7
- data/lib/active_support/messages/metadata.rb +11 -2
- 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 +5 -44
- data/lib/active_support/multibyte/unicode.rb +9 -84
- data/lib/active_support/notifications.rb +32 -5
- data/lib/active_support/notifications/fanout.rb +23 -8
- data/lib/active_support/notifications/instrumenter.rb +7 -16
- data/lib/active_support/number_helper.rb +33 -14
- data/lib/active_support/number_helper/number_converter.rb +5 -6
- data/lib/active_support/number_helper/number_to_currency_converter.rb +2 -7
- data/lib/active_support/number_helper/number_to_delimited_converter.rb +0 -1
- data/lib/active_support/number_helper/number_to_human_converter.rb +1 -2
- data/lib/active_support/number_helper/number_to_human_size_converter.rb +1 -2
- data/lib/active_support/number_helper/number_to_phone_converter.rb +0 -1
- data/lib/active_support/number_helper/number_to_rounded_converter.rb +3 -4
- data/lib/active_support/number_helper/rounding_helper.rb +12 -28
- data/lib/active_support/option_merger.rb +22 -3
- data/lib/active_support/ordered_hash.rb +1 -1
- data/lib/active_support/ordered_options.rb +13 -3
- data/lib/active_support/parameter_filter.rb +17 -13
- data/lib/active_support/per_thread_registry.rb +1 -1
- data/lib/active_support/rails.rb +1 -4
- data/lib/active_support/railtie.rb +23 -1
- data/lib/active_support/rescuable.rb +4 -4
- 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 +4 -3
- data/lib/active_support/subscriber.rb +12 -7
- data/lib/active_support/tagged_logging.rb +29 -4
- data/lib/active_support/testing/assertions.rb +18 -11
- data/lib/active_support/testing/parallelization.rb +12 -89
- 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/stream.rb +0 -1
- data/lib/active_support/testing/time_helpers.rb +40 -5
- data/lib/active_support/time_with_zone.rb +67 -43
- data/lib/active_support/values/time_zone.rb +20 -10
- data/lib/active_support/xml_mini.rb +0 -1
- data/lib/active_support/xml_mini/jdom.rb +0 -1
- data/lib/active_support/xml_mini/rexml.rb +8 -1
- metadata +39 -38
- data/lib/active_support/core_ext/array/prepend_and_append.rb +0 -5
- data/lib/active_support/core_ext/hash/compact.rb +0 -5
- data/lib/active_support/core_ext/hash/transform_values.rb +0 -5
- data/lib/active_support/core_ext/module/reachable.rb +0 -6
- data/lib/active_support/core_ext/numeric/inquiry.rb +0 -5
- data/lib/active_support/core_ext/range/include_range.rb +0 -9
data/MIT-LICENSE
CHANGED
data/README.rdoc
CHANGED
@@ -15,7 +15,7 @@ The latest version of Active Support can be installed with RubyGems:
|
|
15
15
|
|
16
16
|
Source code can be downloaded as part of the Rails project on GitHub:
|
17
17
|
|
18
|
-
* https://github.com/rails/rails/tree/
|
18
|
+
* https://github.com/rails/rails/tree/main/activesupport
|
19
19
|
|
20
20
|
|
21
21
|
== License
|
@@ -37,4 +37,4 @@ Bug reports for the Ruby on Rails project can be filed here:
|
|
37
37
|
|
38
38
|
Feature requests should be discussed on the rails-core mailing list here:
|
39
39
|
|
40
|
-
* https://
|
40
|
+
* https://discuss.rubyonrails.org/c/rubyonrails-core
|
data/lib/active_support.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
#--
|
4
|
-
# Copyright (c) 2005-
|
4
|
+
# Copyright (c) 2005-2020 David Heinemeier Hansson
|
5
5
|
#
|
6
6
|
# Permission is hereby granted, free of charge, to any person obtaining
|
7
7
|
# a copy of this software and associated documentation files (the
|
@@ -35,6 +35,7 @@ module ActiveSupport
|
|
35
35
|
|
36
36
|
autoload :Concern
|
37
37
|
autoload :ActionableError
|
38
|
+
autoload :ConfigurationFile
|
38
39
|
autoload :CurrentAttributes
|
39
40
|
autoload :Dependencies
|
40
41
|
autoload :DescendantsTracker
|
@@ -42,9 +43,11 @@ module ActiveSupport
|
|
42
43
|
autoload :Executor
|
43
44
|
autoload :FileUpdateChecker
|
44
45
|
autoload :EventedFileUpdateChecker
|
46
|
+
autoload :ForkTracker
|
45
47
|
autoload :LogSubscriber
|
46
48
|
autoload :Notifications
|
47
49
|
autoload :Reloader
|
50
|
+
autoload :SecureCompareRotator
|
48
51
|
|
49
52
|
eager_autoload do
|
50
53
|
autoload :BacktraceCleaner
|
@@ -67,6 +70,7 @@ module ActiveSupport
|
|
67
70
|
autoload :OrderedHash
|
68
71
|
autoload :OrderedOptions
|
69
72
|
autoload :StringInquirer
|
73
|
+
autoload :EnvironmentInquirer
|
70
74
|
autoload :TaggedLogging
|
71
75
|
autoload :XmlMini
|
72
76
|
autoload :ArrayInquirer
|
@@ -91,6 +95,14 @@ module ActiveSupport
|
|
91
95
|
def self.to_time_preserves_timezone=(value)
|
92
96
|
DateAndTime::Compatibility.preserve_timezone = value
|
93
97
|
end
|
98
|
+
|
99
|
+
def self.utc_to_local_returns_utc_offset_times
|
100
|
+
DateAndTime::Compatibility.utc_to_local_returns_utc_offset_times
|
101
|
+
end
|
102
|
+
|
103
|
+
def self.utc_to_local_returns_utc_offset_times=(value)
|
104
|
+
DateAndTime::Compatibility.utc_to_local_returns_utc_offset_times = value
|
105
|
+
end
|
94
106
|
end
|
95
107
|
|
96
108
|
autoload :I18n, "active_support/i18n"
|
@@ -1,5 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require "active_support/core_ext/symbol/starts_ends_with"
|
4
|
+
|
3
5
|
module ActiveSupport
|
4
6
|
# Wrapping an array in an +ArrayInquirer+ gives a friendlier way to check
|
5
7
|
# its string-like contents:
|
@@ -34,11 +36,11 @@ module ActiveSupport
|
|
34
36
|
|
35
37
|
private
|
36
38
|
def respond_to_missing?(name, include_private = false)
|
37
|
-
(
|
39
|
+
name.end_with?("?") || super
|
38
40
|
end
|
39
41
|
|
40
42
|
def method_missing(name, *args)
|
41
|
-
if name
|
43
|
+
if name.end_with?("?")
|
42
44
|
any?(name[0..-2])
|
43
45
|
else
|
44
46
|
super
|
@@ -16,7 +16,7 @@ module ActiveSupport
|
|
16
16
|
#
|
17
17
|
# bc = ActiveSupport::BacktraceCleaner.new
|
18
18
|
# bc.add_filter { |line| line.gsub(Rails.root.to_s, '') } # strip the Rails.root prefix
|
19
|
-
# bc.add_silencer { |line|
|
19
|
+
# bc.add_silencer { |line| /puma|rubygems/.match?(line) } # skip any lines from puma or rubygems
|
20
20
|
# bc.clean(exception.backtrace) # perform the cleanup
|
21
21
|
#
|
22
22
|
# To reconfigure an existing BacktraceCleaner (like the default one in Rails)
|
@@ -65,7 +65,7 @@ module ActiveSupport
|
|
65
65
|
# for a given line, it will be excluded from the clean backtrace.
|
66
66
|
#
|
67
67
|
# # Will reject all lines that include the word "puma", like "/gems/puma/server.rb" or "/app/my_puma_server/rb"
|
68
|
-
# backtrace_cleaner.add_silencer { |line|
|
68
|
+
# backtrace_cleaner.add_silencer { |line| /puma/.match?(line) }
|
69
69
|
def add_silencer(&block)
|
70
70
|
@silencers << block
|
71
71
|
end
|
@@ -85,14 +85,13 @@ module ActiveSupport
|
|
85
85
|
end
|
86
86
|
|
87
87
|
private
|
88
|
-
|
89
88
|
FORMATTED_GEMS_PATTERN = /\A[^\/]+ \([\w.]+\) /
|
90
89
|
|
91
90
|
def add_gem_filter
|
92
91
|
gems_paths = (Gem.path | [Gem.default_dir]).map { |p| Regexp.escape(p) }
|
93
92
|
return if gems_paths.empty?
|
94
93
|
|
95
|
-
gems_regexp = %r{(#{gems_paths.join('|')})/(bundler/)?gems/([^/]+)-([\w.]+)/(.*)}
|
94
|
+
gems_regexp = %r{\A(#{gems_paths.join('|')})/(bundler/)?gems/([^/]+)-([\w.]+)/(.*)}
|
96
95
|
gems_result = '\3 (\4) \5'
|
97
96
|
add_filter { |line| line.sub(gems_regexp, gems_result) }
|
98
97
|
end
|
@@ -41,7 +41,7 @@ module ActiveSupport
|
|
41
41
|
|
42
42
|
result = nil
|
43
43
|
ms = Benchmark.ms { result = options[:silence] ? logger.silence { yield } : yield }
|
44
|
-
logger.
|
44
|
+
logger.public_send(options[:level], "%s (%.1fms)" % [ message, ms ])
|
45
45
|
result
|
46
46
|
else
|
47
47
|
yield
|
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,7 +22,7 @@ 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, :race_condition_ttl, :coder]
|
24
26
|
|
25
27
|
module Strategy
|
26
28
|
autoload :LocalCache, "active_support/cache/strategy/local_cache"
|
@@ -52,12 +54,13 @@ module ActiveSupport
|
|
52
54
|
#
|
53
55
|
# ActiveSupport::Cache.lookup_store(MyOwnCacheStore.new)
|
54
56
|
# # => returns MyOwnCacheStore.new
|
55
|
-
def lookup_store(*
|
56
|
-
store, *parameters = *Array.wrap(store_option).flatten
|
57
|
-
|
57
|
+
def lookup_store(store = nil, *parameters)
|
58
58
|
case store
|
59
59
|
when Symbol
|
60
|
-
|
60
|
+
options = parameters.extract_options!
|
61
|
+
retrieve_store_class(store).new(*parameters, **options)
|
62
|
+
when Array
|
63
|
+
lookup_store(*store)
|
61
64
|
when nil
|
62
65
|
ActiveSupport::Cache::MemoryStore.new
|
63
66
|
else
|
@@ -78,7 +81,7 @@ module ActiveSupport
|
|
78
81
|
#
|
79
82
|
# The +key+ argument can also respond to +cache_key+ or +to_param+.
|
80
83
|
def expand_cache_key(key, namespace = nil)
|
81
|
-
expanded_cache_key =
|
84
|
+
expanded_cache_key = namespace ? +"#{namespace}/" : +""
|
82
85
|
|
83
86
|
if prefix = ENV["RAILS_CACHE_ID"] || ENV["RAILS_APP_VERSION"]
|
84
87
|
expanded_cache_key << "#{prefix}/"
|
@@ -155,6 +158,8 @@ module ActiveSupport
|
|
155
158
|
# threshold is configurable with the <tt>:compress_threshold</tt> option,
|
156
159
|
# specified in bytes.
|
157
160
|
class Store
|
161
|
+
DEFAULT_CODER = Marshal
|
162
|
+
|
158
163
|
cattr_accessor :logger, instance_writer: true
|
159
164
|
|
160
165
|
attr_reader :silence, :options
|
@@ -182,6 +187,7 @@ module ActiveSupport
|
|
182
187
|
# namespace for the cache.
|
183
188
|
def initialize(options = nil)
|
184
189
|
@options = options ? options.dup : {}
|
190
|
+
@coder = @options.delete(:coder) { self.class::DEFAULT_CODER } || NullCoder
|
185
191
|
end
|
186
192
|
|
187
193
|
# Silences the logger.
|
@@ -311,14 +317,14 @@ module ActiveSupport
|
|
311
317
|
# :bar
|
312
318
|
# end
|
313
319
|
# cache.fetch('foo') # => "bar"
|
314
|
-
def fetch(name, options = nil)
|
320
|
+
def fetch(name, options = nil, &block)
|
315
321
|
if block_given?
|
316
322
|
options = merged_options(options)
|
317
323
|
key = normalize_key(name, options)
|
318
324
|
|
319
325
|
entry = nil
|
320
326
|
instrument(:read, name, options) do |payload|
|
321
|
-
cached_entry = read_entry(key, options) unless options[:force]
|
327
|
+
cached_entry = read_entry(key, **options, event: payload) unless options[:force]
|
322
328
|
entry = handle_expired_entry(cached_entry, key, options)
|
323
329
|
entry = nil if entry && entry.mismatched?(normalize_version(name, options))
|
324
330
|
payload[:super_operation] = :fetch if payload
|
@@ -328,7 +334,7 @@ module ActiveSupport
|
|
328
334
|
if entry
|
329
335
|
get_entry_value(entry, name, options)
|
330
336
|
else
|
331
|
-
save_block_result_to_cache(name, options)
|
337
|
+
save_block_result_to_cache(name, options, &block)
|
332
338
|
end
|
333
339
|
elsif options && options[:force]
|
334
340
|
raise ArgumentError, "Missing block: Calling `Cache#fetch` with `force: true` requires a block."
|
@@ -352,11 +358,11 @@ module ActiveSupport
|
|
352
358
|
version = normalize_version(name, options)
|
353
359
|
|
354
360
|
instrument(:read, name, options) do |payload|
|
355
|
-
entry = read_entry(key, options)
|
361
|
+
entry = read_entry(key, **options, event: payload)
|
356
362
|
|
357
363
|
if entry
|
358
364
|
if entry.expired?
|
359
|
-
delete_entry(key, options)
|
365
|
+
delete_entry(key, **options)
|
360
366
|
payload[:hit] = false if payload
|
361
367
|
nil
|
362
368
|
elsif entry.mismatched?(version)
|
@@ -384,7 +390,7 @@ module ActiveSupport
|
|
384
390
|
options = merged_options(options)
|
385
391
|
|
386
392
|
instrument :read_multi, names, options do |payload|
|
387
|
-
read_multi_entries(names, options).tap do |results|
|
393
|
+
read_multi_entries(names, **options, event: payload).tap do |results|
|
388
394
|
payload[:hits] = results.keys
|
389
395
|
end
|
390
396
|
end
|
@@ -396,10 +402,10 @@ module ActiveSupport
|
|
396
402
|
|
397
403
|
instrument :write_multi, hash, options do |payload|
|
398
404
|
entries = hash.each_with_object({}) do |(name, value), memo|
|
399
|
-
memo[normalize_key(name, options)] = Entry.new(value, options.merge(version: normalize_version(name, options)))
|
405
|
+
memo[normalize_key(name, options)] = Entry.new(value, **options.merge(version: normalize_version(name, options)))
|
400
406
|
end
|
401
407
|
|
402
|
-
write_multi_entries entries, options
|
408
|
+
write_multi_entries entries, **options
|
403
409
|
end
|
404
410
|
end
|
405
411
|
|
@@ -438,10 +444,10 @@ module ActiveSupport
|
|
438
444
|
options = merged_options(options)
|
439
445
|
|
440
446
|
instrument :read_multi, names, options do |payload|
|
441
|
-
reads = read_multi_entries(names, options)
|
447
|
+
reads = read_multi_entries(names, **options)
|
442
448
|
writes = {}
|
443
|
-
ordered = names.
|
444
|
-
|
449
|
+
ordered = names.index_with do |name|
|
450
|
+
reads.fetch(name) { writes[name] = yield(name) }
|
445
451
|
end
|
446
452
|
|
447
453
|
payload[:hits] = reads.keys
|
@@ -460,8 +466,8 @@ module ActiveSupport
|
|
460
466
|
options = merged_options(options)
|
461
467
|
|
462
468
|
instrument(:write, name, options) do
|
463
|
-
entry = Entry.new(value, options.merge(version: normalize_version(name, options)))
|
464
|
-
write_entry(normalize_key(name, options), entry, options)
|
469
|
+
entry = Entry.new(value, **options.merge(version: normalize_version(name, options)))
|
470
|
+
write_entry(normalize_key(name, options), entry, **options)
|
465
471
|
end
|
466
472
|
end
|
467
473
|
|
@@ -472,7 +478,19 @@ module ActiveSupport
|
|
472
478
|
options = merged_options(options)
|
473
479
|
|
474
480
|
instrument(:delete, name) do
|
475
|
-
delete_entry(normalize_key(name, options), options)
|
481
|
+
delete_entry(normalize_key(name, options), **options)
|
482
|
+
end
|
483
|
+
end
|
484
|
+
|
485
|
+
# Deletes multiple entries in the cache.
|
486
|
+
#
|
487
|
+
# Options are passed to the underlying cache implementation.
|
488
|
+
def delete_multi(names, options = nil)
|
489
|
+
options = merged_options(options)
|
490
|
+
names.map! { |key| normalize_key(key, options) }
|
491
|
+
|
492
|
+
instrument :delete_multi, names do
|
493
|
+
delete_multi_entries(names, **options)
|
476
494
|
end
|
477
495
|
end
|
478
496
|
|
@@ -482,8 +500,8 @@ module ActiveSupport
|
|
482
500
|
def exist?(name, options = nil)
|
483
501
|
options = merged_options(options)
|
484
502
|
|
485
|
-
instrument(:exist?, name) do
|
486
|
-
entry = read_entry(normalize_key(name, options), options)
|
503
|
+
instrument(:exist?, name) do |payload|
|
504
|
+
entry = read_entry(normalize_key(name, options), **options, event: payload)
|
487
505
|
(entry && !entry.expired? && !entry.mismatched?(normalize_version(name, options))) || false
|
488
506
|
end
|
489
507
|
end
|
@@ -556,52 +574,63 @@ module ActiveSupport
|
|
556
574
|
|
557
575
|
# Reads an entry from the cache implementation. Subclasses must implement
|
558
576
|
# this method.
|
559
|
-
def read_entry(key, options)
|
577
|
+
def read_entry(key, **options)
|
560
578
|
raise NotImplementedError.new
|
561
579
|
end
|
562
580
|
|
563
581
|
# Writes an entry to the cache implementation. Subclasses must implement
|
564
582
|
# this method.
|
565
|
-
def write_entry(key, entry, options)
|
583
|
+
def write_entry(key, entry, **options)
|
566
584
|
raise NotImplementedError.new
|
567
585
|
end
|
568
586
|
|
587
|
+
def serialize_entry(entry)
|
588
|
+
@coder.dump(entry)
|
589
|
+
end
|
590
|
+
|
591
|
+
def deserialize_entry(payload)
|
592
|
+
payload.nil? ? nil : @coder.load(payload)
|
593
|
+
end
|
594
|
+
|
569
595
|
# Reads multiple entries from the cache implementation. Subclasses MAY
|
570
596
|
# implement this method.
|
571
|
-
def read_multi_entries(names, options)
|
572
|
-
|
573
|
-
|
574
|
-
|
597
|
+
def read_multi_entries(names, **options)
|
598
|
+
names.each_with_object({}) do |name, results|
|
599
|
+
key = normalize_key(name, options)
|
600
|
+
entry = read_entry(key, **options)
|
601
|
+
|
602
|
+
next unless entry
|
603
|
+
|
575
604
|
version = normalize_version(name, options)
|
576
|
-
|
577
|
-
|
578
|
-
|
579
|
-
|
580
|
-
|
581
|
-
elsif entry.mismatched?(version)
|
582
|
-
# Skip mismatched versions
|
583
|
-
else
|
584
|
-
results[name] = entry.value
|
585
|
-
end
|
605
|
+
|
606
|
+
if entry.expired?
|
607
|
+
delete_entry(key, **options)
|
608
|
+
elsif !entry.mismatched?(version)
|
609
|
+
results[name] = entry.value
|
586
610
|
end
|
587
611
|
end
|
588
|
-
results
|
589
612
|
end
|
590
613
|
|
591
614
|
# Writes multiple entries to the cache implementation. Subclasses MAY
|
592
615
|
# implement this method.
|
593
|
-
def write_multi_entries(hash, options)
|
616
|
+
def write_multi_entries(hash, **options)
|
594
617
|
hash.each do |key, entry|
|
595
|
-
write_entry key, entry, options
|
618
|
+
write_entry key, entry, **options
|
596
619
|
end
|
597
620
|
end
|
598
621
|
|
599
622
|
# Deletes an entry from the cache implementation. Subclasses must
|
600
623
|
# implement this method.
|
601
|
-
def delete_entry(key, options)
|
624
|
+
def delete_entry(key, **options)
|
602
625
|
raise NotImplementedError.new
|
603
626
|
end
|
604
627
|
|
628
|
+
# Deletes multiples entries in the cache implementation. Subclasses MAY
|
629
|
+
# implement this method.
|
630
|
+
def delete_multi_entries(entries, **options)
|
631
|
+
entries.count { |key| delete_entry(key, **options) }
|
632
|
+
end
|
633
|
+
|
605
634
|
# Merges the default options with ones specific to a method call.
|
606
635
|
def merged_options(call_options)
|
607
636
|
if call_options
|
@@ -638,6 +667,10 @@ module ActiveSupport
|
|
638
667
|
namespace = namespace.call
|
639
668
|
end
|
640
669
|
|
670
|
+
if key && key.encoding != Encoding::UTF_8
|
671
|
+
key = key.dup.force_encoding(Encoding::UTF_8)
|
672
|
+
end
|
673
|
+
|
641
674
|
if namespace
|
642
675
|
"#{namespace}:#{key}"
|
643
676
|
else
|
@@ -654,15 +687,15 @@ module ActiveSupport
|
|
654
687
|
case key
|
655
688
|
when Array
|
656
689
|
if key.size > 1
|
657
|
-
key
|
690
|
+
key.collect { |element| expanded_key(element) }
|
658
691
|
else
|
659
|
-
|
692
|
+
expanded_key(key.first)
|
660
693
|
end
|
661
694
|
when Hash
|
662
|
-
key
|
663
|
-
|
664
|
-
|
665
|
-
|
695
|
+
key.collect { |k, v| "#{k}=#{v}" }.sort!
|
696
|
+
else
|
697
|
+
key
|
698
|
+
end.to_param
|
666
699
|
end
|
667
700
|
|
668
701
|
def normalize_version(key, options = nil)
|
@@ -672,24 +705,21 @@ module ActiveSupport
|
|
672
705
|
def expanded_version(key)
|
673
706
|
case
|
674
707
|
when key.respond_to?(:cache_version) then key.cache_version.to_param
|
675
|
-
when key.is_a?(Array) then key.map { |element| expanded_version(element) }.compact.to_param
|
708
|
+
when key.is_a?(Array) then key.map { |element| expanded_version(element) }.tap(&:compact!).to_param
|
676
709
|
when key.respond_to?(:to_a) then expanded_version(key.to_a)
|
677
710
|
end
|
678
711
|
end
|
679
712
|
|
680
713
|
def instrument(operation, key, options = nil)
|
681
|
-
|
714
|
+
if logger && logger.debug? && !silence?
|
715
|
+
logger.debug "Cache #{operation}: #{normalize_key(key, options)}#{options.blank? ? "" : " (#{options.inspect})"}"
|
716
|
+
end
|
682
717
|
|
683
|
-
payload = { key: key }
|
718
|
+
payload = { key: key, store: self.class.name }
|
684
719
|
payload.merge!(options) if options.is_a?(Hash)
|
685
720
|
ActiveSupport::Notifications.instrument("cache_#{operation}.active_support", payload) { yield(payload) }
|
686
721
|
end
|
687
722
|
|
688
|
-
def log
|
689
|
-
return unless logger && logger.debug? && !silence?
|
690
|
-
logger.debug(yield)
|
691
|
-
end
|
692
|
-
|
693
723
|
def handle_expired_entry(entry, key, options)
|
694
724
|
if entry && entry.expired?
|
695
725
|
race_ttl = options[:race_condition_ttl].to_i
|
@@ -699,7 +729,7 @@ module ActiveSupport
|
|
699
729
|
entry.expires_at = Time.now + race_ttl
|
700
730
|
write_entry(key, entry, expires_in: race_ttl * 2)
|
701
731
|
else
|
702
|
-
delete_entry(key, options)
|
732
|
+
delete_entry(key, **options)
|
703
733
|
end
|
704
734
|
entry = nil
|
705
735
|
end
|
@@ -721,6 +751,18 @@ module ActiveSupport
|
|
721
751
|
end
|
722
752
|
end
|
723
753
|
|
754
|
+
module NullCoder # :nodoc:
|
755
|
+
class << self
|
756
|
+
def load(payload)
|
757
|
+
payload
|
758
|
+
end
|
759
|
+
|
760
|
+
def dump(entry)
|
761
|
+
entry
|
762
|
+
end
|
763
|
+
end
|
764
|
+
end
|
765
|
+
|
724
766
|
# This class is used to represent cache entries. Cache entries have a value, an optional
|
725
767
|
# expiration time, and an optional version. The expiration time is used to support the :race_condition_ttl option
|
726
768
|
# on the cache. The version is used to support the :version option on the cache for rejecting
|
@@ -771,8 +813,8 @@ module ActiveSupport
|
|
771
813
|
end
|
772
814
|
|
773
815
|
# Returns the size of the cached value. This could be less than
|
774
|
-
# <tt>value.
|
775
|
-
def
|
816
|
+
# <tt>value.bytesize</tt> if the data is compressed.
|
817
|
+
def bytesize
|
776
818
|
case value
|
777
819
|
when NilClass
|
778
820
|
0
|