activesupport 6.0.6.1 → 6.1.0.rc1
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 +337 -573
- data/MIT-LICENSE +1 -1
- data/README.rdoc +1 -1
- data/lib/active_support/array_inquirer.rb +4 -2
- data/lib/active_support/backtrace_cleaner.rb +3 -3
- data/lib/active_support/benchmarkable.rb +1 -1
- data/lib/active_support/cache/file_store.rb +2 -2
- data/lib/active_support/cache/mem_cache_store.rb +20 -14
- data/lib/active_support/cache/memory_store.rb +38 -26
- data/lib/active_support/cache/redis_cache_store.rb +25 -25
- data/lib/active_support/cache/strategy/local_cache.rb +13 -4
- data/lib/active_support/cache.rb +75 -34
- data/lib/active_support/callbacks.rb +65 -56
- data/lib/active_support/concern.rb +46 -2
- data/lib/active_support/configurable.rb +3 -3
- data/lib/active_support/configuration_file.rb +46 -0
- 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/enumerable.rb +76 -4
- data/lib/active_support/core_ext/hash/conversions.rb +2 -2
- data/lib/active_support/core_ext/hash/deep_transform_values.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 +38 -28
- data/lib/active_support/core_ext/module/introspection.rb +1 -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 +5 -1
- data/lib/active_support/core_ext/object/try.rb +2 -2
- data/lib/active_support/core_ext/range/compare_range.rb +9 -3
- data/lib/active_support/core_ext/range/include_time_with_zone.rb +8 -3
- data/lib/active_support/core_ext/string/access.rb +5 -24
- 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 +8 -38
- data/lib/active_support/core_ext/string/starts_ends_with.rb +2 -2
- data/lib/active_support/core_ext/symbol/starts_ends_with.rb +14 -0
- data/lib/active_support/core_ext/symbol.rb +3 -0
- data/lib/active_support/core_ext/time/calculations.rb +16 -0
- data/lib/active_support/core_ext/time/conversions.rb +1 -0
- data/lib/active_support/core_ext/uri.rb +5 -1
- data/lib/active_support/current_attributes/test_helper.rb +13 -0
- data/lib/active_support/current_attributes.rb +7 -2
- data/lib/active_support/dependencies.rb +38 -24
- 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 +3 -2
- data/lib/active_support/deprecation/proxy_wrappers.rb +2 -2
- data/lib/active_support/deprecation/reporting.rb +50 -7
- data/lib/active_support/deprecation.rb +6 -1
- data/lib/active_support/descendants_tracker.rb +6 -2
- data/lib/active_support/duration/iso8601_serializer.rb +15 -9
- data/lib/active_support/duration.rb +71 -22
- data/lib/active_support/encrypted_file.rb +19 -2
- data/lib/active_support/environment_inquirer.rb +20 -0
- data/lib/active_support/evented_file_update_checker.rb +69 -133
- data/lib/active_support/execution_wrapper.rb +13 -16
- data/lib/active_support/fork_tracker.rb +58 -0
- data/lib/active_support/gem_version.rb +3 -3
- data/lib/active_support/hash_with_indifferent_access.rb +35 -22
- data/lib/active_support/i18n_railtie.rb +14 -19
- data/lib/active_support/inflector/inflections.rb +1 -2
- data/lib/active_support/inflector/methods.rb +35 -31
- data/lib/active_support/inflector/transliterate.rb +4 -4
- data/lib/active_support/json/decoding.rb +4 -4
- data/lib/active_support/json/encoding.rb +5 -1
- data/lib/active_support/key_generator.rb +1 -1
- data/lib/active_support/locale/en.yml +7 -3
- data/lib/active_support/log_subscriber.rb +8 -0
- data/lib/active_support/logger.rb +1 -1
- 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 +4 -7
- data/lib/active_support/message_verifier.rb +5 -5
- data/lib/active_support/messages/rotation_configuration.rb +2 -1
- data/lib/active_support/messages/rotator.rb +6 -5
- data/lib/active_support/multibyte/chars.rb +4 -42
- data/lib/active_support/multibyte/unicode.rb +9 -83
- data/lib/active_support/notifications/fanout.rb +23 -8
- data/lib/active_support/notifications/instrumenter.rb +6 -15
- data/lib/active_support/notifications.rb +31 -4
- data/lib/active_support/number_helper/number_converter.rb +1 -1
- data/lib/active_support/number_helper/number_to_human_converter.rb +1 -1
- data/lib/active_support/number_helper/number_to_human_size_converter.rb +1 -1
- data/lib/active_support/number_helper/number_to_rounded_converter.rb +3 -3
- data/lib/active_support/number_helper/rounding_helper.rb +12 -28
- data/lib/active_support/number_helper.rb +29 -14
- data/lib/active_support/option_merger.rb +2 -1
- data/lib/active_support/ordered_options.rb +8 -2
- data/lib/active_support/parameter_filter.rb +15 -10
- 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/reloader.rb +1 -1
- 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 -2
- 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/server.rb +78 -0
- data/lib/active_support/testing/parallelization/worker.rb +100 -0
- data/lib/active_support/testing/parallelization.rb +12 -95
- data/lib/active_support/testing/time_helpers.rb +40 -3
- data/lib/active_support/time_with_zone.rb +66 -42
- data/lib/active_support/values/time_zone.rb +20 -10
- data/lib/active_support/xml_mini/rexml.rb +8 -1
- data/lib/active_support.rb +13 -1
- metadata +39 -42
- 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/master/activesupport
|
19
19
|
|
20
20
|
|
21
21
|
== License
|
@@ -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
|
@@ -91,7 +91,7 @@ module ActiveSupport
|
|
91
91
|
gems_paths = (Gem.path | [Gem.default_dir]).map { |p| Regexp.escape(p) }
|
92
92
|
return if gems_paths.empty?
|
93
93
|
|
94
|
-
gems_regexp = %r{(#{gems_paths.join('|')})/(bundler/)?gems/([^/]+)-([\w.]+)/(.*)}
|
94
|
+
gems_regexp = %r{\A(#{gems_paths.join('|')})/(bundler/)?gems/([^/]+)-([\w.]+)/(.*)}
|
95
95
|
gems_result = '\3 (\4) \5'
|
96
96
|
add_filter { |line| line.sub(gems_regexp, gems_result) }
|
97
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
|
@@ -74,7 +74,7 @@ module ActiveSupport
|
|
74
74
|
private
|
75
75
|
def read_entry(key, **options)
|
76
76
|
if File.exist?(key)
|
77
|
-
entry = File.open(key) { |f|
|
77
|
+
entry = File.open(key) { |f| deserialize_entry(f.read) }
|
78
78
|
entry if entry.is_a?(Cache::Entry)
|
79
79
|
end
|
80
80
|
rescue => e
|
@@ -85,7 +85,7 @@ module ActiveSupport
|
|
85
85
|
def write_entry(key, entry, **options)
|
86
86
|
return false if options[:unless_exist] && File.exist?(key)
|
87
87
|
ensure_cache_path(File.dirname(key))
|
88
|
-
File.atomic_write(key, cache_path) { |f|
|
88
|
+
File.atomic_write(key, cache_path) { |f| f.write(serialize_entry(entry)) }
|
89
89
|
true
|
90
90
|
end
|
91
91
|
|
@@ -7,6 +7,7 @@ rescue LoadError => e
|
|
7
7
|
raise e
|
8
8
|
end
|
9
9
|
|
10
|
+
require "active_support/core_ext/enumerable"
|
10
11
|
require "active_support/core_ext/marshal"
|
11
12
|
require "active_support/core_ext/array/extract_options"
|
12
13
|
|
@@ -25,6 +26,8 @@ module ActiveSupport
|
|
25
26
|
# MemCacheStore implements the Strategy::LocalCache strategy which implements
|
26
27
|
# an in-memory cache inside of a block.
|
27
28
|
class MemCacheStore < Store
|
29
|
+
DEFAULT_CODER = NullCoder # Dalli automatically Marshal values
|
30
|
+
|
28
31
|
# Provide support for raw values in the local cache strategy.
|
29
32
|
module LocalCacheWithRaw # :nodoc:
|
30
33
|
private
|
@@ -50,16 +53,18 @@ module ActiveSupport
|
|
50
53
|
ESCAPE_KEY_CHARS = /[\x00-\x20%\x7F-\xFF]/n
|
51
54
|
|
52
55
|
# Creates a new Dalli::Client instance with specified addresses and options.
|
53
|
-
#
|
56
|
+
# If no addresses are provided, we give nil to Dalli::Client, so it uses its fallbacks:
|
57
|
+
# - ENV["MEMCACHE_SERVERS"] (if defined)
|
58
|
+
# - "127.0.0.1:11211" (otherwise)
|
54
59
|
#
|
55
60
|
# ActiveSupport::Cache::MemCacheStore.build_mem_cache
|
56
|
-
# # => #<Dalli::Client:0x007f98a47d2028 @servers=["
|
61
|
+
# # => #<Dalli::Client:0x007f98a47d2028 @servers=["127.0.0.1:11211"], @options={}, @ring=nil>
|
57
62
|
# ActiveSupport::Cache::MemCacheStore.build_mem_cache('localhost:10290')
|
58
63
|
# # => #<Dalli::Client:0x007f98a47b3a60 @servers=["localhost:10290"], @options={}, @ring=nil>
|
59
64
|
def self.build_mem_cache(*addresses) # :nodoc:
|
60
65
|
addresses = addresses.flatten
|
61
66
|
options = addresses.extract_options!
|
62
|
-
addresses =
|
67
|
+
addresses = nil if addresses.empty?
|
63
68
|
pool_options = retrieve_pool_options(options)
|
64
69
|
|
65
70
|
if pool_options.empty?
|
@@ -76,8 +81,8 @@ module ActiveSupport
|
|
76
81
|
#
|
77
82
|
# ActiveSupport::Cache::MemCacheStore.new("localhost", "server-downstairs.localnetwork:8229")
|
78
83
|
#
|
79
|
-
# If no addresses are
|
80
|
-
#
|
84
|
+
# If no addresses are provided, but ENV['MEMCACHE_SERVERS'] is defined, it will be used instead. Otherwise,
|
85
|
+
# MemCacheStore will connect to localhost:11211 (the default memcached port).
|
81
86
|
def initialize(*addresses)
|
82
87
|
addresses = addresses.flatten
|
83
88
|
options = addresses.extract_options!
|
@@ -140,21 +145,22 @@ module ActiveSupport
|
|
140
145
|
|
141
146
|
# Write an entry to the cache.
|
142
147
|
def write_entry(key, entry, **options)
|
143
|
-
method = options
|
144
|
-
value = options[:raw] ? entry.value.to_s : entry
|
148
|
+
method = options[:unless_exist] ? :add : :set
|
149
|
+
value = options[:raw] ? entry.value.to_s : serialize_entry(entry)
|
145
150
|
expires_in = options[:expires_in].to_i
|
146
|
-
if expires_in > 0 && !options[:raw]
|
151
|
+
if options[:race_condition_ttl] && expires_in > 0 && !options[:raw]
|
147
152
|
# Set the memcache expire a few minutes in the future to support race condition ttls on read
|
148
153
|
expires_in += 5.minutes
|
149
154
|
end
|
150
155
|
rescue_error_with false do
|
151
|
-
|
156
|
+
# The value "compress: false" prevents duplicate compression within Dalli.
|
157
|
+
@data.with { |c| c.send(method, key, value, expires_in, **options, compress: false) }
|
152
158
|
end
|
153
159
|
end
|
154
160
|
|
155
161
|
# Reads multiple entries from the cache implementation.
|
156
162
|
def read_multi_entries(names, **options)
|
157
|
-
keys_to_names =
|
163
|
+
keys_to_names = names.index_by { |name| normalize_key(name, options) }
|
158
164
|
|
159
165
|
raw_values = @data.with { |c| c.get_multi(keys_to_names.keys) }
|
160
166
|
values = {}
|
@@ -186,10 +192,10 @@ module ActiveSupport
|
|
186
192
|
key
|
187
193
|
end
|
188
194
|
|
189
|
-
def deserialize_entry(
|
190
|
-
|
191
|
-
|
192
|
-
|
195
|
+
def deserialize_entry(payload)
|
196
|
+
entry = super
|
197
|
+
entry = Entry.new(entry, compress: false) if entry && !entry.is_a?(Entry)
|
198
|
+
entry
|
193
199
|
end
|
194
200
|
|
195
201
|
def rescue_error_with(fallback)
|
@@ -18,11 +18,27 @@ module ActiveSupport
|
|
18
18
|
#
|
19
19
|
# MemoryStore is thread-safe.
|
20
20
|
class MemoryStore < Store
|
21
|
+
module DupCoder # :nodoc:
|
22
|
+
class << self
|
23
|
+
def load(entry)
|
24
|
+
entry = entry.dup
|
25
|
+
entry.dup_value!
|
26
|
+
entry
|
27
|
+
end
|
28
|
+
|
29
|
+
def dump(entry)
|
30
|
+
entry.dup_value!
|
31
|
+
entry
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
DEFAULT_CODER = DupCoder
|
37
|
+
|
21
38
|
def initialize(options = nil)
|
22
39
|
options ||= {}
|
23
40
|
super(options)
|
24
41
|
@data = {}
|
25
|
-
@key_access = {}
|
26
42
|
@max_size = options[:size] || 32.megabytes
|
27
43
|
@max_prune_time = options[:max_prune_time] || 2
|
28
44
|
@cache_size = 0
|
@@ -39,7 +55,6 @@ module ActiveSupport
|
|
39
55
|
def clear(options = nil)
|
40
56
|
synchronize do
|
41
57
|
@data.clear
|
42
|
-
@key_access.clear
|
43
58
|
@cache_size = 0
|
44
59
|
end
|
45
60
|
end
|
@@ -65,7 +80,7 @@ module ActiveSupport
|
|
65
80
|
start_time = Concurrent.monotonic_time
|
66
81
|
cleanup
|
67
82
|
instrument(:prune, target_size, from: @cache_size) do
|
68
|
-
keys = synchronize { @
|
83
|
+
keys = synchronize { @data.keys }
|
69
84
|
keys.each do |key|
|
70
85
|
delete_entry(key, **options)
|
71
86
|
return if @cache_size <= target_size || (max_time && Concurrent.monotonic_time - start_time > max_time)
|
@@ -104,7 +119,7 @@ module ActiveSupport
|
|
104
119
|
end
|
105
120
|
|
106
121
|
def inspect # :nodoc:
|
107
|
-
"
|
122
|
+
"#<#{self.class.name} entries=#{@data.size}, size=#{@cache_size}, options=#{@options.inspect}>"
|
108
123
|
end
|
109
124
|
|
110
125
|
# Synchronize calls to the cache. This should be called wherever the underlying cache implementation
|
@@ -116,36 +131,34 @@ module ActiveSupport
|
|
116
131
|
private
|
117
132
|
PER_ENTRY_OVERHEAD = 240
|
118
133
|
|
119
|
-
def cached_size(key,
|
120
|
-
key.to_s.bytesize +
|
134
|
+
def cached_size(key, payload)
|
135
|
+
key.to_s.bytesize + payload.bytesize + PER_ENTRY_OVERHEAD
|
121
136
|
end
|
122
137
|
|
123
138
|
def read_entry(key, **options)
|
124
|
-
entry =
|
139
|
+
entry = nil
|
125
140
|
synchronize do
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
else
|
131
|
-
@key_access.delete(key)
|
141
|
+
payload = @data.delete(key)
|
142
|
+
if payload
|
143
|
+
@data[key] = payload
|
144
|
+
entry = deserialize_entry(payload)
|
132
145
|
end
|
133
146
|
end
|
134
147
|
entry
|
135
148
|
end
|
136
149
|
|
137
150
|
def write_entry(key, entry, **options)
|
138
|
-
entry
|
151
|
+
payload = serialize_entry(entry)
|
139
152
|
synchronize do
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
153
|
+
return false if options[:unless_exist] && @data.key?(key)
|
154
|
+
|
155
|
+
old_payload = @data[key]
|
156
|
+
if old_payload
|
157
|
+
@cache_size -= (old_payload.bytesize - payload.bytesize)
|
144
158
|
else
|
145
|
-
@cache_size += cached_size(key,
|
159
|
+
@cache_size += cached_size(key, payload)
|
146
160
|
end
|
147
|
-
@
|
148
|
-
@data[key] = entry
|
161
|
+
@data[key] = payload
|
149
162
|
prune(@max_size * 0.75, @max_prune_time) if @cache_size > @max_size
|
150
163
|
true
|
151
164
|
end
|
@@ -153,16 +166,15 @@ module ActiveSupport
|
|
153
166
|
|
154
167
|
def delete_entry(key, **options)
|
155
168
|
synchronize do
|
156
|
-
@
|
157
|
-
|
158
|
-
|
159
|
-
!!entry
|
169
|
+
payload = @data.delete(key)
|
170
|
+
@cache_size -= cached_size(key, payload) if payload
|
171
|
+
!!payload
|
160
172
|
end
|
161
173
|
end
|
162
174
|
|
163
175
|
def modify_value(name, amount, options)
|
176
|
+
options = merged_options(options)
|
164
177
|
synchronize do
|
165
|
-
options = merged_options(options)
|
166
178
|
if num = read(name, options)
|
167
179
|
num = num.to_i + amount
|
168
180
|
write(name, num, options)
|
@@ -169,7 +169,7 @@ module ActiveSupport
|
|
169
169
|
# Race condition TTL is not set by default. This can be used to avoid
|
170
170
|
# "thundering herd" cache writes when hot cache entries are expired.
|
171
171
|
# See <tt>ActiveSupport::Cache::Store#fetch</tt> for more.
|
172
|
-
def initialize(namespace: nil, compress: true, compress_threshold: 1.kilobyte, expires_in: nil, race_condition_ttl: nil, error_handler: DEFAULT_ERROR_HANDLER, **redis_options)
|
172
|
+
def initialize(namespace: nil, compress: true, compress_threshold: 1.kilobyte, coder: DEFAULT_CODER, expires_in: nil, race_condition_ttl: nil, error_handler: DEFAULT_ERROR_HANDLER, **redis_options)
|
173
173
|
@redis_options = redis_options
|
174
174
|
|
175
175
|
@max_key_bytesize = MAX_KEY_BYTESIZE
|
@@ -177,7 +177,8 @@ module ActiveSupport
|
|
177
177
|
|
178
178
|
super namespace: namespace,
|
179
179
|
compress: compress, compress_threshold: compress_threshold,
|
180
|
-
expires_in: expires_in, race_condition_ttl: race_condition_ttl
|
180
|
+
expires_in: expires_in, race_condition_ttl: race_condition_ttl,
|
181
|
+
coder: coder
|
181
182
|
end
|
182
183
|
|
183
184
|
def redis
|
@@ -195,7 +196,7 @@ module ActiveSupport
|
|
195
196
|
|
196
197
|
def inspect
|
197
198
|
instance = @redis || @redis_options
|
198
|
-
"
|
199
|
+
"#<#{self.class} options=#{options.inspect} redis=#{instance.inspect}>"
|
199
200
|
end
|
200
201
|
|
201
202
|
# Cache Store API implementation.
|
@@ -238,10 +239,14 @@ module ActiveSupport
|
|
238
239
|
pattern = namespace_key(matcher, options)
|
239
240
|
cursor = "0"
|
240
241
|
# Fetch keys in batches using SCAN to avoid blocking the Redis server.
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
242
|
+
nodes = c.respond_to?(:nodes) ? c.nodes : [c]
|
243
|
+
|
244
|
+
nodes.each do |node|
|
245
|
+
begin
|
246
|
+
cursor, keys = node.scan(cursor, match: pattern, count: SCAN_BATCH_SIZE)
|
247
|
+
node.del(*keys) unless keys.empty?
|
248
|
+
end until cursor == "0"
|
249
|
+
end
|
245
250
|
end
|
246
251
|
end
|
247
252
|
end
|
@@ -414,6 +419,11 @@ module ActiveSupport
|
|
414
419
|
end
|
415
420
|
end
|
416
421
|
|
422
|
+
# Deletes multiple entries in the cache. Returns the number of entries deleted.
|
423
|
+
def delete_multi_entries(entries, **_options)
|
424
|
+
redis.with { |c| c.del(entries) }
|
425
|
+
end
|
426
|
+
|
417
427
|
# Nonstandard store provider API to write multiple values at once.
|
418
428
|
def write_multi_entries(entries, expires_in: nil, **options)
|
419
429
|
if entries.any?
|
@@ -429,11 +439,11 @@ module ActiveSupport
|
|
429
439
|
|
430
440
|
# Truncate keys that exceed 1kB.
|
431
441
|
def normalize_key(key, options)
|
432
|
-
truncate_key super
|
442
|
+
truncate_key super&.b
|
433
443
|
end
|
434
444
|
|
435
445
|
def truncate_key(key)
|
436
|
-
if key.bytesize > max_key_bytesize
|
446
|
+
if key && key.bytesize > max_key_bytesize
|
437
447
|
suffix = ":sha2:#{::Digest::SHA2.hexdigest(key)}"
|
438
448
|
truncate_at = max_key_bytesize - suffix.bytesize
|
439
449
|
"#{key.byteslice(0, truncate_at)}#{suffix}"
|
@@ -442,21 +452,11 @@ module ActiveSupport
|
|
442
452
|
end
|
443
453
|
end
|
444
454
|
|
445
|
-
def deserialize_entry(
|
446
|
-
if
|
447
|
-
|
448
|
-
|
449
|
-
|
450
|
-
if raw != written_raw
|
451
|
-
ActiveSupport::Deprecation.warn(<<-MSG.squish)
|
452
|
-
Using a different value for the raw option when reading and writing
|
453
|
-
to a cache key is deprecated for :redis_cache_store and Rails 6.0
|
454
|
-
will stop automatically detecting the format when reading to avoid
|
455
|
-
marshal loading untrusted raw strings.
|
456
|
-
MSG
|
457
|
-
end
|
458
|
-
|
459
|
-
entry.is_a?(Entry) ? entry : Entry.new(entry)
|
455
|
+
def deserialize_entry(payload, raw:)
|
456
|
+
if payload && raw
|
457
|
+
Entry.new(payload, compress: false)
|
458
|
+
else
|
459
|
+
super(payload)
|
460
460
|
end
|
461
461
|
end
|
462
462
|
|
@@ -464,7 +464,7 @@ module ActiveSupport
|
|
464
464
|
if raw
|
465
465
|
entry.value.to_s
|
466
466
|
else
|
467
|
-
|
467
|
+
super(entry)
|
468
468
|
end
|
469
469
|
end
|
470
470
|
|
@@ -1,6 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require "active_support/core_ext/object/duplicable"
|
4
3
|
require "active_support/core_ext/string/inflections"
|
5
4
|
require "active_support/per_thread_registry"
|
6
5
|
|
@@ -65,8 +64,9 @@ module ActiveSupport
|
|
65
64
|
values
|
66
65
|
end
|
67
66
|
|
68
|
-
def write_entry(key,
|
69
|
-
|
67
|
+
def write_entry(key, entry, **options)
|
68
|
+
entry.dup_value!
|
69
|
+
@data[key] = entry
|
70
70
|
true
|
71
71
|
end
|
72
72
|
|
@@ -75,7 +75,10 @@ module ActiveSupport
|
|
75
75
|
end
|
76
76
|
|
77
77
|
def fetch_entry(key, options = nil) # :nodoc:
|
78
|
-
@data.fetch(key) { @data[key] = yield }
|
78
|
+
entry = @data.fetch(key) { @data[key] = yield }
|
79
|
+
dup_entry = entry.dup
|
80
|
+
dup_entry&.dup_value!
|
81
|
+
dup_entry
|
79
82
|
end
|
80
83
|
end
|
81
84
|
|
@@ -104,6 +107,12 @@ module ActiveSupport
|
|
104
107
|
super
|
105
108
|
end
|
106
109
|
|
110
|
+
def delete_matched(matcher, options = nil) # :nodoc:
|
111
|
+
return super unless cache = local_cache
|
112
|
+
cache.clear
|
113
|
+
super
|
114
|
+
end
|
115
|
+
|
107
116
|
def increment(name, amount = 1, **options) # :nodoc:
|
108
117
|
return super unless local_cache
|
109
118
|
value = bypass_local_cache { super }
|