activesupport 7.1.5.1 → 7.2.0.beta1
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 +113 -1178
- data/lib/active_support/array_inquirer.rb +1 -1
- data/lib/active_support/backtrace_cleaner.rb +10 -3
- data/lib/active_support/broadcast_logger.rb +18 -19
- data/lib/active_support/cache/file_store.rb +15 -10
- data/lib/active_support/cache/mem_cache_store.rb +16 -74
- data/lib/active_support/cache/memory_store.rb +2 -1
- data/lib/active_support/cache/redis_cache_store.rb +16 -13
- data/lib/active_support/cache/serializer_with_fallback.rb +0 -23
- data/lib/active_support/cache.rb +59 -67
- data/lib/active_support/callbacks.rb +74 -113
- data/lib/active_support/code_generator.rb +10 -15
- data/lib/active_support/core_ext/array/conversions.rb +0 -2
- data/lib/active_support/core_ext/class/subclasses.rb +15 -35
- data/lib/active_support/core_ext/date/blank.rb +4 -0
- data/lib/active_support/core_ext/date/conversions.rb +0 -2
- data/lib/active_support/core_ext/date_and_time/compatibility.rb +12 -9
- data/lib/active_support/core_ext/date_time/blank.rb +4 -0
- data/lib/active_support/core_ext/date_time/compatibility.rb +3 -5
- data/lib/active_support/core_ext/date_time/conversions.rb +0 -4
- data/lib/active_support/core_ext/erb/util.rb +5 -0
- data/lib/active_support/core_ext/hash/keys.rb +4 -4
- data/lib/active_support/core_ext/module/attr_internal.rb +17 -6
- data/lib/active_support/core_ext/module/delegation.rb +20 -163
- data/lib/active_support/core_ext/module/deprecation.rb +1 -4
- data/lib/active_support/core_ext/numeric/conversions.rb +3 -3
- data/lib/active_support/core_ext/object/blank.rb +45 -1
- data/lib/active_support/core_ext/object/instance_variables.rb +11 -19
- data/lib/active_support/core_ext/object/json.rb +4 -6
- data/lib/active_support/core_ext/object/with.rb +5 -3
- data/lib/active_support/core_ext/pathname/blank.rb +4 -0
- data/lib/active_support/core_ext/range/overlap.rb +1 -1
- data/lib/active_support/core_ext/string/conversions.rb +1 -1
- data/lib/active_support/core_ext/string/filters.rb +1 -1
- data/lib/active_support/core_ext/string/output_safety.rb +0 -7
- data/lib/active_support/core_ext/time/calculations.rb +12 -27
- data/lib/active_support/core_ext/time/compatibility.rb +2 -3
- data/lib/active_support/core_ext/time/conversions.rb +0 -2
- data/lib/active_support/core_ext.rb +0 -1
- data/lib/active_support/current_attributes.rb +33 -40
- data/lib/active_support/delegation.rb +188 -0
- data/lib/active_support/dependencies/autoload.rb +0 -12
- data/lib/active_support/deprecation/constant_accessor.rb +1 -3
- data/lib/active_support/deprecation/proxy_wrappers.rb +9 -12
- data/lib/active_support/deprecation/reporting.rb +9 -4
- data/lib/active_support/deprecation.rb +8 -5
- data/lib/active_support/descendants_tracker.rb +9 -87
- data/lib/active_support/duration/iso8601_parser.rb +2 -2
- data/lib/active_support/duration/iso8601_serializer.rb +1 -2
- data/lib/active_support/duration.rb +11 -6
- data/lib/active_support/error_reporter.rb +41 -3
- data/lib/active_support/evented_file_update_checker.rb +0 -1
- data/lib/active_support/execution_wrapper.rb +0 -1
- data/lib/active_support/file_update_checker.rb +1 -1
- data/lib/active_support/fork_tracker.rb +2 -38
- data/lib/active_support/gem_version.rb +3 -3
- data/lib/active_support/hash_with_indifferent_access.rb +6 -8
- data/lib/active_support/html_safe_translation.rb +3 -0
- data/lib/active_support/log_subscriber.rb +0 -12
- data/lib/active_support/logger.rb +15 -2
- data/lib/active_support/message_pack/extensions.rb +15 -2
- data/lib/active_support/multibyte/chars.rb +2 -2
- data/lib/active_support/notifications/fanout.rb +4 -7
- data/lib/active_support/notifications/instrumenter.rb +21 -18
- data/lib/active_support/notifications.rb +28 -27
- data/lib/active_support/number_helper/number_converter.rb +2 -2
- data/lib/active_support/option_merger.rb +2 -2
- data/lib/active_support/ordered_options.rb +53 -15
- data/lib/active_support/proxy_object.rb +8 -5
- data/lib/active_support/railtie.rb +4 -11
- data/lib/active_support/string_inquirer.rb +1 -1
- data/lib/active_support/syntax_error_proxy.rb +11 -1
- data/lib/active_support/test_case.rb +3 -1
- data/lib/active_support/testing/assertions.rb +4 -4
- data/lib/active_support/testing/constant_stubbing.rb +30 -8
- data/lib/active_support/testing/deprecation.rb +5 -12
- data/lib/active_support/testing/isolation.rb +18 -8
- data/lib/active_support/testing/method_call_assertions.rb +2 -16
- data/lib/active_support/testing/strict_warnings.rb +5 -4
- data/lib/active_support/testing/tests_without_assertions.rb +19 -0
- data/lib/active_support/time_with_zone.rb +9 -10
- data/lib/active_support/values/time_zone.rb +1 -1
- data/lib/active_support/xml_mini.rb +11 -2
- data/lib/active_support.rb +7 -8
- metadata +20 -70
- data/lib/active_support/deprecation/instance_delegator.rb +0 -65
- data/lib/active_support/ruby_features.rb +0 -7
@@ -17,7 +17,8 @@ module ActiveSupport
|
|
17
17
|
# can focus on the rest.
|
18
18
|
#
|
19
19
|
# bc = ActiveSupport::BacktraceCleaner.new
|
20
|
-
#
|
20
|
+
# root = "#{Rails.root}/"
|
21
|
+
# bc.add_filter { |line| line.start_with?(root) ? line.from(root.size) : line } # strip the Rails.root prefix
|
21
22
|
# bc.add_silencer { |line| /puma|rubygems/.match?(line) } # skip any lines from puma or rubygems
|
22
23
|
# bc.clean(exception.backtrace) # perform the cleanup
|
23
24
|
#
|
@@ -76,8 +77,9 @@ module ActiveSupport
|
|
76
77
|
# Adds a filter from the block provided. Each line in the backtrace will be
|
77
78
|
# mapped against this filter.
|
78
79
|
#
|
79
|
-
# # Will turn "/my/rails/root/app/models/person.rb" into "
|
80
|
-
#
|
80
|
+
# # Will turn "/my/rails/root/app/models/person.rb" into "app/models/person.rb"
|
81
|
+
# root = "#{Rails.root}/"
|
82
|
+
# backtrace_cleaner.add_filter { |line| line.start_with?(root) ? line.from(root.size) : line }
|
81
83
|
def add_filter(&block)
|
82
84
|
@filters << block
|
83
85
|
end
|
@@ -108,6 +110,11 @@ module ActiveSupport
|
|
108
110
|
private
|
109
111
|
FORMATTED_GEMS_PATTERN = /\A[^\/]+ \([\w.]+\) /
|
110
112
|
|
113
|
+
def initialize_copy(_other)
|
114
|
+
@filters = @filters.dup
|
115
|
+
@silencers = @silencers.dup
|
116
|
+
end
|
117
|
+
|
111
118
|
def add_gem_filter
|
112
119
|
gems_paths = (Gem.path | [Gem.default_dir]).map { |p| Regexp.escape(p) }
|
113
120
|
return if gems_paths.empty?
|
@@ -113,33 +113,33 @@ module ActiveSupport
|
|
113
113
|
dispatch { |logger| logger.<<(message) }
|
114
114
|
end
|
115
115
|
|
116
|
-
def add(
|
117
|
-
dispatch { |logger| logger.add(
|
116
|
+
def add(*args, &block)
|
117
|
+
dispatch { |logger| logger.add(*args, &block) }
|
118
118
|
end
|
119
119
|
alias_method :log, :add
|
120
120
|
|
121
|
-
def debug(
|
122
|
-
dispatch { |logger| logger.debug(
|
121
|
+
def debug(*args, &block)
|
122
|
+
dispatch { |logger| logger.debug(*args, &block) }
|
123
123
|
end
|
124
124
|
|
125
|
-
def info(
|
126
|
-
dispatch { |logger| logger.info(
|
125
|
+
def info(*args, &block)
|
126
|
+
dispatch { |logger| logger.info(*args, &block) }
|
127
127
|
end
|
128
128
|
|
129
|
-
def warn(
|
130
|
-
dispatch { |logger| logger.warn(
|
129
|
+
def warn(*args, &block)
|
130
|
+
dispatch { |logger| logger.warn(*args, &block) }
|
131
131
|
end
|
132
132
|
|
133
|
-
def error(
|
134
|
-
dispatch { |logger| logger.error(
|
133
|
+
def error(*args, &block)
|
134
|
+
dispatch { |logger| logger.error(*args, &block) }
|
135
135
|
end
|
136
136
|
|
137
|
-
def fatal(
|
138
|
-
dispatch { |logger| logger.fatal(
|
137
|
+
def fatal(*args, &block)
|
138
|
+
dispatch { |logger| logger.fatal(*args, &block) }
|
139
139
|
end
|
140
140
|
|
141
|
-
def unknown(
|
142
|
-
dispatch { |logger| logger.unknown(
|
141
|
+
def unknown(*args, &block)
|
142
|
+
dispatch { |logger| logger.unknown(*args, &block) }
|
143
143
|
end
|
144
144
|
|
145
145
|
def formatter=(formatter)
|
@@ -229,18 +229,17 @@ module ActiveSupport
|
|
229
229
|
private
|
230
230
|
def dispatch(&block)
|
231
231
|
@broadcasts.each { |logger| block.call(logger) }
|
232
|
-
true
|
233
232
|
end
|
234
233
|
|
235
|
-
def method_missing(name,
|
234
|
+
def method_missing(name, ...)
|
236
235
|
loggers = @broadcasts.select { |logger| logger.respond_to?(name) }
|
237
236
|
|
238
237
|
if loggers.none?
|
239
|
-
super
|
238
|
+
super
|
240
239
|
elsif loggers.one?
|
241
|
-
loggers.first.send(name,
|
240
|
+
loggers.first.send(name, ...)
|
242
241
|
else
|
243
|
-
loggers.map { |logger| logger.send(name,
|
242
|
+
loggers.map { |logger| logger.send(name, ...) }
|
244
243
|
end
|
245
244
|
end
|
246
245
|
|
@@ -78,8 +78,9 @@ module ActiveSupport
|
|
78
78
|
|
79
79
|
def delete_matched(matcher, options = nil)
|
80
80
|
options = merged_options(options)
|
81
|
+
matcher = key_matcher(matcher, options)
|
82
|
+
|
81
83
|
instrument(:delete_matched, matcher.inspect) do
|
82
|
-
matcher = key_matcher(matcher, options)
|
83
84
|
search_dir(cache_path) do |path|
|
84
85
|
key = file_path_key(path)
|
85
86
|
delete_entry(path, **options) if key.match(matcher)
|
@@ -209,18 +210,22 @@ module ActiveSupport
|
|
209
210
|
# Modifies the amount of an integer value that is stored in the cache.
|
210
211
|
# If the key is not found it is created and set to +amount+.
|
211
212
|
def modify_value(name, amount, options)
|
212
|
-
|
213
|
+
options = merged_options(options)
|
214
|
+
key = normalize_key(name, options)
|
215
|
+
version = normalize_version(name, options)
|
216
|
+
amount = Integer(amount)
|
213
217
|
|
214
|
-
lock_file(
|
215
|
-
|
218
|
+
lock_file(key) do
|
219
|
+
entry = read_entry(key, **options)
|
216
220
|
|
217
|
-
if
|
218
|
-
|
219
|
-
write(name, num, options)
|
220
|
-
num
|
221
|
-
else
|
222
|
-
write(name, Integer(amount), options)
|
221
|
+
if !entry || entry.expired? || entry.mismatched?(version)
|
222
|
+
write(name, amount, options)
|
223
223
|
amount
|
224
|
+
else
|
225
|
+
num = entry.value.to_i + amount
|
226
|
+
entry = Entry.new(num, expires_at: entry.expires_at, version: entry.version)
|
227
|
+
write_entry(key, entry)
|
228
|
+
num
|
224
229
|
end
|
225
230
|
end
|
226
231
|
end
|
@@ -41,46 +41,6 @@ module ActiveSupport
|
|
41
41
|
|
42
42
|
prepend Strategy::LocalCache
|
43
43
|
|
44
|
-
module DupLocalCache
|
45
|
-
class DupLocalStore < DelegateClass(Strategy::LocalCache::LocalStore)
|
46
|
-
def write_entry(_key, entry)
|
47
|
-
if entry.is_a?(Entry)
|
48
|
-
entry.dup_value!
|
49
|
-
end
|
50
|
-
super
|
51
|
-
end
|
52
|
-
|
53
|
-
def fetch_entry(key)
|
54
|
-
entry = super do
|
55
|
-
new_entry = yield
|
56
|
-
if entry.is_a?(Entry)
|
57
|
-
new_entry.dup_value!
|
58
|
-
end
|
59
|
-
new_entry
|
60
|
-
end
|
61
|
-
entry = entry.dup
|
62
|
-
|
63
|
-
if entry.is_a?(Entry)
|
64
|
-
entry.dup_value!
|
65
|
-
end
|
66
|
-
|
67
|
-
entry
|
68
|
-
end
|
69
|
-
end
|
70
|
-
|
71
|
-
private
|
72
|
-
def local_cache
|
73
|
-
if ActiveSupport::Cache.format_version == 6.1
|
74
|
-
if local_cache = super
|
75
|
-
DupLocalStore.new(local_cache)
|
76
|
-
end
|
77
|
-
else
|
78
|
-
super
|
79
|
-
end
|
80
|
-
end
|
81
|
-
end
|
82
|
-
prepend DupLocalCache
|
83
|
-
|
84
44
|
KEY_MAX_SIZE = 250
|
85
45
|
ESCAPE_KEY_CHARS = /[\x00-\x20%\x7F-\xFF]/n
|
86
46
|
|
@@ -114,7 +74,6 @@ module ActiveSupport
|
|
114
74
|
#
|
115
75
|
# If no addresses are provided, but <tt>ENV['MEMCACHE_SERVERS']</tt> is defined, it will be used instead. Otherwise,
|
116
76
|
# +MemCacheStore+ will connect to localhost:11211 (the default memcached port).
|
117
|
-
# Passing a +Dalli::Client+ instance is deprecated and will be removed. Please pass an address instead.
|
118
77
|
def initialize(*addresses)
|
119
78
|
addresses = addresses.flatten
|
120
79
|
options = addresses.extract_options!
|
@@ -126,19 +85,12 @@ module ActiveSupport
|
|
126
85
|
unless [String, Dalli::Client, NilClass].include?(addresses.first.class)
|
127
86
|
raise ArgumentError, "First argument must be an empty array, address, or array of addresses."
|
128
87
|
end
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
else
|
136
|
-
@mem_cache_options = options.dup
|
137
|
-
# The value "compress: false" prevents duplicate compression within Dalli.
|
138
|
-
@mem_cache_options[:compress] = false
|
139
|
-
(OVERRIDDEN_OPTIONS - %i(compress)).each { |name| @mem_cache_options.delete(name) }
|
140
|
-
@data = self.class.build_mem_cache(*(addresses + [@mem_cache_options]))
|
141
|
-
end
|
88
|
+
|
89
|
+
@mem_cache_options = options.dup
|
90
|
+
# The value "compress: false" prevents duplicate compression within Dalli.
|
91
|
+
@mem_cache_options[:compress] = false
|
92
|
+
(OVERRIDDEN_OPTIONS - %i(compress)).each { |name| @mem_cache_options.delete(name) }
|
93
|
+
@data = self.class.build_mem_cache(*(addresses + [@mem_cache_options]))
|
142
94
|
end
|
143
95
|
|
144
96
|
def inspect
|
@@ -179,9 +131,11 @@ module ActiveSupport
|
|
179
131
|
# <tt>raw: true</tt>, will fail and return +nil+.
|
180
132
|
def increment(name, amount = 1, options = nil)
|
181
133
|
options = merged_options(options)
|
182
|
-
|
134
|
+
key = normalize_key(name, options)
|
135
|
+
|
136
|
+
instrument(:increment, key, amount: amount) do
|
183
137
|
rescue_error_with nil do
|
184
|
-
@data.with { |c| c.incr(
|
138
|
+
@data.with { |c| c.incr(key, amount, options[:expires_in], amount) }
|
185
139
|
end
|
186
140
|
end
|
187
141
|
end
|
@@ -203,9 +157,11 @@ module ActiveSupport
|
|
203
157
|
# <tt>raw: true</tt>, will fail and return +nil+.
|
204
158
|
def decrement(name, amount = 1, options = nil)
|
205
159
|
options = merged_options(options)
|
206
|
-
|
160
|
+
key = normalize_key(name, options)
|
161
|
+
|
162
|
+
instrument(:decrement, key, amount: amount) do
|
207
163
|
rescue_error_with nil do
|
208
|
-
@data.with { |c| c.decr(
|
164
|
+
@data.with { |c| c.decr(key, amount, options[:expires_in], 0) }
|
209
165
|
end
|
210
166
|
end
|
211
167
|
end
|
@@ -222,20 +178,6 @@ module ActiveSupport
|
|
222
178
|
end
|
223
179
|
|
224
180
|
private
|
225
|
-
def default_serializer
|
226
|
-
if Cache.format_version == 6.1
|
227
|
-
ActiveSupport.deprecator.warn <<~EOM
|
228
|
-
Support for `config.active_support.cache_format_version = 6.1` has been deprecated and will be removed in Rails 7.2.
|
229
|
-
|
230
|
-
Check the Rails upgrade guide at https://guides.rubyonrails.org/upgrading_ruby_on_rails.html#new-activesupport-cache-serialization-format
|
231
|
-
for more information on how to upgrade.
|
232
|
-
EOM
|
233
|
-
Cache::SerializerWithFallback[:passthrough]
|
234
|
-
else
|
235
|
-
super
|
236
|
-
end
|
237
|
-
end
|
238
|
-
|
239
181
|
# Read an entry from the cache.
|
240
182
|
def read_entry(key, **options)
|
241
183
|
deserialize_entry(read_serialized_entry(key, **options), **options)
|
@@ -259,10 +201,10 @@ module ActiveSupport
|
|
259
201
|
# Set the memcache expire a few minutes in the future to support race condition ttls on read
|
260
202
|
expires_in += 5.minutes
|
261
203
|
end
|
262
|
-
rescue_error_with
|
204
|
+
rescue_error_with nil do
|
263
205
|
# Don't pass compress option to Dalli since we are already dealing with compression.
|
264
206
|
options.delete(:compress)
|
265
|
-
@data.with { |c| c.send(method, key, payload, expires_in, **options) }
|
207
|
+
@data.with { |c| !!c.send(method, key, payload, expires_in, **options) }
|
266
208
|
end
|
267
209
|
end
|
268
210
|
|
@@ -168,8 +168,9 @@ module ActiveSupport
|
|
168
168
|
# Deletes cache entries if the cache key matches a given pattern.
|
169
169
|
def delete_matched(matcher, options = nil)
|
170
170
|
options = merged_options(options)
|
171
|
+
matcher = key_matcher(matcher, options)
|
172
|
+
|
171
173
|
instrument(:delete_matched, matcher.inspect) do
|
172
|
-
matcher = key_matcher(matcher, options)
|
173
174
|
keys = synchronize { @data.keys }
|
174
175
|
keys.each do |key|
|
175
176
|
delete_entry(key, **options) if key.match(matcher)
|
@@ -196,12 +196,13 @@ module ActiveSupport
|
|
196
196
|
#
|
197
197
|
# Failsafe: Raises errors.
|
198
198
|
def delete_matched(matcher, options = nil)
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
199
|
+
unless String === matcher
|
200
|
+
raise ArgumentError, "Only Redis glob strings are supported: #{matcher.inspect}"
|
201
|
+
end
|
202
|
+
pattern = namespace_key(matcher, options)
|
203
|
+
|
204
|
+
instrument :delete_matched, pattern do
|
203
205
|
redis.then do |c|
|
204
|
-
pattern = namespace_key(matcher, options)
|
205
206
|
cursor = "0"
|
206
207
|
# Fetch keys in batches using SCAN to avoid blocking the Redis server.
|
207
208
|
nodes = c.respond_to?(:nodes) ? c.nodes : [c]
|
@@ -234,10 +235,11 @@ module ActiveSupport
|
|
234
235
|
#
|
235
236
|
# Failsafe: Raises errors.
|
236
237
|
def increment(name, amount = 1, options = nil)
|
237
|
-
|
238
|
+
options = merged_options(options)
|
239
|
+
key = normalize_key(name, options)
|
240
|
+
|
241
|
+
instrument :increment, key, amount: amount do
|
238
242
|
failsafe :increment do
|
239
|
-
options = merged_options(options)
|
240
|
-
key = normalize_key(name, options)
|
241
243
|
change_counter(key, amount, options)
|
242
244
|
end
|
243
245
|
end
|
@@ -260,10 +262,11 @@ module ActiveSupport
|
|
260
262
|
#
|
261
263
|
# Failsafe: Raises errors.
|
262
264
|
def decrement(name, amount = 1, options = nil)
|
263
|
-
|
265
|
+
options = merged_options(options)
|
266
|
+
key = normalize_key(name, options)
|
267
|
+
|
268
|
+
instrument :decrement, key, amount: amount do
|
264
269
|
failsafe :decrement do
|
265
|
-
options = merged_options(options)
|
266
|
-
key = normalize_key(name, options)
|
267
270
|
change_counter(key, -amount, options)
|
268
271
|
end
|
269
272
|
end
|
@@ -369,8 +372,8 @@ module ActiveSupport
|
|
369
372
|
if pipeline
|
370
373
|
pipeline.set(key, payload, **modifiers)
|
371
374
|
else
|
372
|
-
failsafe :write_entry, returning:
|
373
|
-
redis.then { |c| c.set
|
375
|
+
failsafe :write_entry, returning: nil do
|
376
|
+
redis.then { |c| !!c.set(key, payload, **modifiers) }
|
374
377
|
end
|
375
378
|
end
|
376
379
|
end
|
@@ -63,28 +63,6 @@ module ActiveSupport
|
|
63
63
|
end
|
64
64
|
end
|
65
65
|
|
66
|
-
module Marshal61WithFallback
|
67
|
-
include SerializerWithFallback
|
68
|
-
extend self
|
69
|
-
|
70
|
-
MARSHAL_SIGNATURE = "\x04\x08".b.freeze
|
71
|
-
|
72
|
-
def dump(entry)
|
73
|
-
Marshal.dump(entry)
|
74
|
-
end
|
75
|
-
|
76
|
-
def dump_compressed(entry, threshold)
|
77
|
-
Marshal.dump(entry.compressed(threshold))
|
78
|
-
end
|
79
|
-
|
80
|
-
alias_method :_load, :marshal_load
|
81
|
-
public :_load
|
82
|
-
|
83
|
-
def dumped?(dumped)
|
84
|
-
dumped.start_with?(MARSHAL_SIGNATURE)
|
85
|
-
end
|
86
|
-
end
|
87
|
-
|
88
66
|
module Marshal70WithFallback
|
89
67
|
include SerializerWithFallback
|
90
68
|
extend self
|
@@ -165,7 +143,6 @@ module ActiveSupport
|
|
165
143
|
|
166
144
|
SERIALIZERS = {
|
167
145
|
passthrough: PassthroughWithFallback,
|
168
|
-
marshal_6_1: Marshal61WithFallback,
|
169
146
|
marshal_7_0: Marshal70WithFallback,
|
170
147
|
marshal_7_1: Marshal71WithFallback,
|
171
148
|
message_pack: MessagePackWithFallback,
|
data/lib/active_support/cache.rb
CHANGED
@@ -52,7 +52,7 @@ module ActiveSupport
|
|
52
52
|
autoload :LocalCache, "active_support/cache/strategy/local_cache"
|
53
53
|
end
|
54
54
|
|
55
|
-
@format_version =
|
55
|
+
@format_version = 7.0
|
56
56
|
|
57
57
|
class << self
|
58
58
|
attr_accessor :format_version
|
@@ -86,13 +86,7 @@ module ActiveSupport
|
|
86
86
|
case store
|
87
87
|
when Symbol
|
88
88
|
options = parameters.extract_options!
|
89
|
-
|
90
|
-
# see https://github.com/rails/rails/pull/41522#discussion_r581186602
|
91
|
-
if options.empty?
|
92
|
-
retrieve_store_class(store).new(*parameters)
|
93
|
-
else
|
94
|
-
retrieve_store_class(store).new(*parameters, **options)
|
95
|
-
end
|
89
|
+
retrieve_store_class(store).new(*parameters, **options)
|
96
90
|
when Array
|
97
91
|
lookup_store(*store)
|
98
92
|
when nil
|
@@ -166,7 +160,7 @@ module ActiveSupport
|
|
166
160
|
# cache = ActiveSupport::Cache::MemoryStore.new
|
167
161
|
#
|
168
162
|
# cache.read('city') # => nil
|
169
|
-
# cache.write('city', "Duckburgh")
|
163
|
+
# cache.write('city', "Duckburgh") # => true
|
170
164
|
# cache.read('city') # => "Duckburgh"
|
171
165
|
#
|
172
166
|
# cache.write('not serializable', Proc.new {}) # => TypeError
|
@@ -206,24 +200,6 @@ module ActiveSupport
|
|
206
200
|
def retrieve_pool_options(options)
|
207
201
|
if options.key?(:pool)
|
208
202
|
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
203
|
else
|
228
204
|
pool_options = true
|
229
205
|
end
|
@@ -344,7 +320,7 @@ module ActiveSupport
|
|
344
320
|
|
345
321
|
# Silences the logger within a block.
|
346
322
|
def mute
|
347
|
-
previous_silence, @silence =
|
323
|
+
previous_silence, @silence = @silence, true
|
348
324
|
yield
|
349
325
|
ensure
|
350
326
|
@silence = previous_silence
|
@@ -411,31 +387,47 @@ module ActiveSupport
|
|
411
387
|
# has elapsed.
|
412
388
|
#
|
413
389
|
# # Set all values to expire after one minute.
|
414
|
-
# cache = ActiveSupport::Cache::MemoryStore.new(expires_in: 1
|
390
|
+
# cache = ActiveSupport::Cache::MemoryStore.new(expires_in: 1)
|
415
391
|
#
|
416
|
-
# cache.write(
|
392
|
+
# cache.write("foo", "original value")
|
417
393
|
# val_1 = nil
|
418
394
|
# val_2 = nil
|
419
|
-
#
|
395
|
+
# p cache.read("foo") # => "original value"
|
420
396
|
#
|
421
|
-
#
|
422
|
-
#
|
397
|
+
# sleep 1 # wait until the cache expires
|
398
|
+
#
|
399
|
+
# t1 = Thread.new do
|
400
|
+
# # fetch does the following:
|
401
|
+
# # 1. gets an recent expired entry
|
402
|
+
# # 2. extends the expiry by 2 seconds (race_condition_ttl)
|
403
|
+
# # 3. regenerates the new value
|
404
|
+
# val_1 = cache.fetch("foo", race_condition_ttl: 2) do
|
423
405
|
# sleep 1
|
424
|
-
#
|
406
|
+
# "new value 1"
|
425
407
|
# end
|
426
408
|
# end
|
427
409
|
#
|
428
|
-
#
|
429
|
-
#
|
430
|
-
#
|
431
|
-
#
|
410
|
+
# # Wait until t1 extends the expiry of the entry
|
411
|
+
# # but before generating the new value
|
412
|
+
# sleep 0.1
|
413
|
+
#
|
414
|
+
# val_2 = cache.fetch("foo", race_condition_ttl: 2) do
|
415
|
+
# # This block won't be executed because t1 extended the expiry
|
416
|
+
# "new value 2"
|
432
417
|
# end
|
433
418
|
#
|
434
|
-
#
|
435
|
-
#
|
436
|
-
#
|
437
|
-
#
|
438
|
-
#
|
419
|
+
# t1.join
|
420
|
+
#
|
421
|
+
# p val_1 # => "new value 1"
|
422
|
+
# p val_2 # => "oritinal value"
|
423
|
+
# p cache.fetch("foo") # => "new value 1"
|
424
|
+
#
|
425
|
+
# # The entry requires 3 seconds to expire (expires_in + race_condition_ttl)
|
426
|
+
# # We have waited 2 seconds already (sleep(1) + t1.join) thus we need to wait 1
|
427
|
+
# # more second to see the entry expire.
|
428
|
+
# sleep 1
|
429
|
+
#
|
430
|
+
# p cache.fetch("foo") # => nil
|
439
431
|
#
|
440
432
|
# ==== Dynamic Options
|
441
433
|
#
|
@@ -456,7 +448,7 @@ module ActiveSupport
|
|
456
448
|
|
457
449
|
entry = nil
|
458
450
|
unless options[:force]
|
459
|
-
instrument(:read,
|
451
|
+
instrument(:read, key, options) do |payload|
|
460
452
|
cached_entry = read_entry(key, **options, event: payload)
|
461
453
|
entry = handle_expired_entry(cached_entry, key, options)
|
462
454
|
if entry
|
@@ -478,7 +470,7 @@ module ActiveSupport
|
|
478
470
|
if entry
|
479
471
|
get_entry_value(entry, name, options)
|
480
472
|
else
|
481
|
-
save_block_result_to_cache(name, options, &block)
|
473
|
+
save_block_result_to_cache(name, key, options, &block)
|
482
474
|
end
|
483
475
|
elsif options && options[:force]
|
484
476
|
raise ArgumentError, "Missing block: Calling `Cache#fetch` with `force: true` requires a block."
|
@@ -508,7 +500,7 @@ module ActiveSupport
|
|
508
500
|
key = normalize_key(name, options)
|
509
501
|
version = normalize_version(name, options)
|
510
502
|
|
511
|
-
instrument(:read,
|
503
|
+
instrument(:read, key, options) do |payload|
|
512
504
|
entry = read_entry(key, **options, event: payload)
|
513
505
|
|
514
506
|
if entry
|
@@ -605,14 +597,14 @@ module ActiveSupport
|
|
605
597
|
options = names.extract_options!
|
606
598
|
options = merged_options(options)
|
607
599
|
|
608
|
-
|
600
|
+
writes = {}
|
601
|
+
ordered = instrument_multi :read_multi, names, options do |payload|
|
609
602
|
if options[:force]
|
610
603
|
reads = {}
|
611
604
|
else
|
612
605
|
reads = read_multi_entries(names, **options)
|
613
606
|
end
|
614
607
|
|
615
|
-
writes = {}
|
616
608
|
ordered = names.index_with do |name|
|
617
609
|
reads.fetch(name) { writes[name] = yield(name) }
|
618
610
|
end
|
@@ -621,15 +613,20 @@ module ActiveSupport
|
|
621
613
|
payload[:hits] = reads.keys
|
622
614
|
payload[:super_operation] = :fetch_multi
|
623
615
|
|
624
|
-
write_multi(writes, options)
|
625
|
-
|
626
616
|
ordered
|
627
617
|
end
|
618
|
+
|
619
|
+
write_multi(writes, options)
|
620
|
+
|
621
|
+
ordered
|
628
622
|
end
|
629
623
|
|
630
624
|
# Writes the value to the cache with the key. The value must be supported
|
631
625
|
# by the +coder+'s +dump+ and +load+ methods.
|
632
626
|
#
|
627
|
+
# Returns +true+ if the write succeeded, +nil+ if there was an error talking
|
628
|
+
# to the cache backend, or +false+ if the write failed for another reason.
|
629
|
+
#
|
633
630
|
# By default, cache entries larger than 1kB are compressed. Compression
|
634
631
|
# allows more data to be stored in the same memory footprint, leading to
|
635
632
|
# fewer cache evictions and higher hit rates.
|
@@ -662,10 +659,11 @@ module ActiveSupport
|
|
662
659
|
# Other options will be handled by the specific cache store implementation.
|
663
660
|
def write(name, value, options = nil)
|
664
661
|
options = merged_options(options)
|
662
|
+
key = normalize_key(name, options)
|
665
663
|
|
666
|
-
instrument(:write,
|
664
|
+
instrument(:write, key, options) do
|
667
665
|
entry = Entry.new(value, **options.merge(version: normalize_version(name, options)))
|
668
|
-
write_entry(
|
666
|
+
write_entry(key, entry, **options)
|
669
667
|
end
|
670
668
|
end
|
671
669
|
|
@@ -675,9 +673,10 @@ module ActiveSupport
|
|
675
673
|
# Options are passed to the underlying cache implementation.
|
676
674
|
def delete(name, options = nil)
|
677
675
|
options = merged_options(options)
|
676
|
+
key = normalize_key(name, options)
|
678
677
|
|
679
|
-
instrument(:delete,
|
680
|
-
delete_entry(
|
678
|
+
instrument(:delete, key) do
|
679
|
+
delete_entry(key, **options)
|
681
680
|
end
|
682
681
|
end
|
683
682
|
|
@@ -701,9 +700,10 @@ module ActiveSupport
|
|
701
700
|
# Options are passed to the underlying cache implementation.
|
702
701
|
def exist?(name, options = nil)
|
703
702
|
options = merged_options(options)
|
703
|
+
key = normalize_key(name, options)
|
704
704
|
|
705
|
-
instrument(:exist?,
|
706
|
-
entry = read_entry(
|
705
|
+
instrument(:exist?, key) do |payload|
|
706
|
+
entry = read_entry(key, **options, event: payload)
|
707
707
|
(entry && !entry.expired? && !entry.mismatched?(normalize_version(name, options))) || false
|
708
708
|
end
|
709
709
|
end
|
@@ -761,14 +761,6 @@ module ActiveSupport
|
|
761
761
|
private
|
762
762
|
def default_serializer
|
763
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
764
|
when 7.0
|
773
765
|
Cache::SerializerWithFallback[:marshal_7_0]
|
774
766
|
when 7.1
|
@@ -1016,7 +1008,7 @@ module ActiveSupport
|
|
1016
1008
|
if multi
|
1017
1009
|
": #{payload[:key].size} key(s) specified"
|
1018
1010
|
elsif payload[:key]
|
1019
|
-
": #{
|
1011
|
+
": #{payload[:key]}"
|
1020
1012
|
end
|
1021
1013
|
|
1022
1014
|
debug_options = " (#{options.inspect})" unless options.blank?
|
@@ -1053,10 +1045,10 @@ module ActiveSupport
|
|
1053
1045
|
entry.value
|
1054
1046
|
end
|
1055
1047
|
|
1056
|
-
def save_block_result_to_cache(name, options)
|
1048
|
+
def save_block_result_to_cache(name, key, options)
|
1057
1049
|
options = options.dup
|
1058
1050
|
|
1059
|
-
result = instrument(:generate,
|
1051
|
+
result = instrument(:generate, key, options) do
|
1060
1052
|
yield(name, WriteOptions.new(options))
|
1061
1053
|
end
|
1062
1054
|
|