activesupport 7.2.3 → 8.0.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 +41 -385
- data/README.rdoc +1 -1
- data/lib/active_support/backtrace_cleaner.rb +2 -2
- data/lib/active_support/benchmark.rb +21 -0
- data/lib/active_support/benchmarkable.rb +3 -2
- data/lib/active_support/broadcast_logger.rb +74 -61
- data/lib/active_support/cache/file_store.rb +14 -4
- data/lib/active_support/cache/mem_cache_store.rb +15 -13
- data/lib/active_support/cache/memory_store.rb +9 -5
- data/lib/active_support/cache/null_store.rb +2 -2
- data/lib/active_support/cache/redis_cache_store.rb +6 -3
- data/lib/active_support/cache/strategy/local_cache.rb +20 -56
- data/lib/active_support/cache.rb +17 -12
- data/lib/active_support/callbacks.rb +3 -5
- data/lib/active_support/class_attribute.rb +26 -0
- data/lib/active_support/code_generator.rb +9 -0
- data/lib/active_support/concurrency/share_lock.rb +0 -1
- data/lib/active_support/configuration_file.rb +15 -6
- data/lib/active_support/core_ext/benchmark.rb +6 -10
- data/lib/active_support/core_ext/class/attribute.rb +12 -21
- data/lib/active_support/core_ext/date/conversions.rb +2 -0
- data/lib/active_support/core_ext/date_and_time/compatibility.rb +2 -2
- data/lib/active_support/core_ext/date_time/conversions.rb +2 -4
- data/lib/active_support/core_ext/enumerable.rb +13 -20
- data/lib/active_support/core_ext/erb/util.rb +2 -2
- data/lib/active_support/core_ext/hash/except.rb +0 -12
- data/lib/active_support/core_ext/module/introspection.rb +0 -3
- data/lib/active_support/core_ext/object/json.rb +18 -14
- data/lib/active_support/core_ext/object/try.rb +2 -2
- data/lib/active_support/core_ext/range.rb +0 -1
- data/lib/active_support/core_ext/securerandom.rb +8 -24
- data/lib/active_support/core_ext/string/filters.rb +3 -3
- data/lib/active_support/core_ext/string/multibyte.rb +3 -3
- data/lib/active_support/core_ext/time/calculations.rb +14 -2
- data/lib/active_support/core_ext/time/compatibility.rb +1 -9
- data/lib/active_support/core_ext/time/conversions.rb +2 -0
- data/lib/active_support/core_ext/time/zones.rb +1 -1
- data/lib/active_support/current_attributes.rb +7 -14
- data/lib/active_support/deprecation.rb +1 -1
- data/lib/active_support/encrypted_configuration.rb +20 -2
- data/lib/active_support/error_reporter.rb +27 -6
- data/lib/active_support/execution_wrapper.rb +1 -1
- data/lib/active_support/file_update_checker.rb +1 -1
- data/lib/active_support/gem_version.rb +4 -4
- data/lib/active_support/hash_with_indifferent_access.rb +31 -31
- data/lib/active_support/i18n_railtie.rb +19 -10
- data/lib/active_support/isolated_execution_state.rb +0 -1
- data/lib/active_support/json/decoding.rb +1 -1
- data/lib/active_support/json/encoding.rb +7 -25
- data/lib/active_support/lazy_load_hooks.rb +1 -1
- data/lib/active_support/message_encryptors.rb +2 -2
- data/lib/active_support/message_verifier.rb +0 -9
- data/lib/active_support/message_verifiers.rb +3 -5
- data/lib/active_support/messages/rotator.rb +0 -5
- data/lib/active_support/multibyte/chars.rb +1 -4
- data/lib/active_support/number_helper.rb +22 -0
- data/lib/active_support/railtie.rb +4 -0
- data/lib/active_support/tagged_logging.rb +5 -0
- data/lib/active_support/testing/assertions.rb +72 -21
- data/lib/active_support/testing/isolation.rb +0 -2
- data/lib/active_support/testing/parallelization/server.rb +2 -15
- data/lib/active_support/testing/parallelization/worker.rb +2 -2
- data/lib/active_support/testing/parallelization.rb +1 -12
- data/lib/active_support/testing/strict_warnings.rb +43 -0
- data/lib/active_support/testing/time_helpers.rb +2 -1
- data/lib/active_support/time_with_zone.rb +22 -13
- data/lib/active_support/values/time_zone.rb +17 -15
- data/lib/active_support/xml_mini.rb +0 -2
- data/lib/active_support.rb +10 -2
- metadata +27 -8
- data/lib/active_support/core_ext/range/sole.rb +0 -17
|
@@ -76,6 +76,7 @@ module ActiveSupport
|
|
|
76
76
|
|
|
77
77
|
# Returns all the logger that are part of this broadcast.
|
|
78
78
|
attr_reader :broadcasts
|
|
79
|
+
attr_reader :formatter
|
|
79
80
|
attr_accessor :progname
|
|
80
81
|
|
|
81
82
|
def initialize(*loggers)
|
|
@@ -104,119 +105,131 @@ module ActiveSupport
|
|
|
104
105
|
@broadcasts.delete(logger)
|
|
105
106
|
end
|
|
106
107
|
|
|
107
|
-
def
|
|
108
|
-
@broadcasts.
|
|
109
|
-
logger.local_level = level if logger.respond_to?(:local_level=)
|
|
110
|
-
end
|
|
108
|
+
def level
|
|
109
|
+
@broadcasts.map(&:level).min
|
|
111
110
|
end
|
|
112
111
|
|
|
113
|
-
def
|
|
114
|
-
|
|
112
|
+
def <<(message)
|
|
113
|
+
dispatch { |logger| logger.<<(message) }
|
|
114
|
+
end
|
|
115
115
|
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
end.first
|
|
116
|
+
def add(...)
|
|
117
|
+
dispatch { |logger| logger.add(...) }
|
|
119
118
|
end
|
|
119
|
+
alias_method :log, :add
|
|
120
120
|
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
level= sev_threshold= close
|
|
124
|
-
formatter formatter=
|
|
125
|
-
] # :nodoc:
|
|
126
|
-
LOGGER_METHODS.each do |method|
|
|
127
|
-
class_eval <<-RUBY, __FILE__, __LINE__ + 1
|
|
128
|
-
def #{method}(...)
|
|
129
|
-
dispatch(:#{method}, ...)
|
|
130
|
-
end
|
|
131
|
-
RUBY
|
|
121
|
+
def debug(...)
|
|
122
|
+
dispatch { |logger| logger.debug(...) }
|
|
132
123
|
end
|
|
133
124
|
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
125
|
+
def info(...)
|
|
126
|
+
dispatch { |logger| logger.info(...) }
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
def warn(...)
|
|
130
|
+
dispatch { |logger| logger.warn(...) }
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
def error(...)
|
|
134
|
+
dispatch { |logger| logger.error(...) }
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
def fatal(...)
|
|
138
|
+
dispatch { |logger| logger.fatal(...) }
|
|
137
139
|
end
|
|
138
140
|
|
|
139
|
-
|
|
140
|
-
|
|
141
|
+
def unknown(...)
|
|
142
|
+
dispatch { |logger| logger.unknown(...) }
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
def formatter=(formatter)
|
|
146
|
+
dispatch { |logger| logger.formatter = formatter }
|
|
147
|
+
|
|
148
|
+
@formatter = formatter
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
def level=(level)
|
|
152
|
+
dispatch { |logger| logger.level = level }
|
|
153
|
+
end
|
|
154
|
+
alias_method :sev_threshold=, :level=
|
|
155
|
+
|
|
156
|
+
def local_level=(level)
|
|
157
|
+
dispatch do |logger|
|
|
158
|
+
logger.local_level = level if logger.respond_to?(:local_level=)
|
|
159
|
+
end
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
def close
|
|
163
|
+
dispatch { |logger| logger.close }
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
# +True+ if the log level allows entries with severity Logger::DEBUG to be written
|
|
167
|
+
# to at least one broadcast. +False+ otherwise.
|
|
141
168
|
def debug?
|
|
142
169
|
@broadcasts.any? { |logger| logger.debug? }
|
|
143
170
|
end
|
|
144
171
|
|
|
145
|
-
# Sets the log level to
|
|
172
|
+
# Sets the log level to Logger::DEBUG for the whole broadcast.
|
|
146
173
|
def debug!
|
|
147
|
-
dispatch
|
|
174
|
+
dispatch { |logger| logger.debug! }
|
|
148
175
|
end
|
|
149
176
|
|
|
150
|
-
# True if the log level allows entries with severity
|
|
151
|
-
# to at least one broadcast. False otherwise.
|
|
177
|
+
# +True+ if the log level allows entries with severity Logger::INFO to be written
|
|
178
|
+
# to at least one broadcast. +False+ otherwise.
|
|
152
179
|
def info?
|
|
153
180
|
@broadcasts.any? { |logger| logger.info? }
|
|
154
181
|
end
|
|
155
182
|
|
|
156
|
-
# Sets the log level to
|
|
183
|
+
# Sets the log level to Logger::INFO for the whole broadcast.
|
|
157
184
|
def info!
|
|
158
|
-
dispatch
|
|
185
|
+
dispatch { |logger| logger.info! }
|
|
159
186
|
end
|
|
160
187
|
|
|
161
|
-
# True if the log level allows entries with severity
|
|
162
|
-
# to at least one broadcast. False otherwise.
|
|
188
|
+
# +True+ if the log level allows entries with severity Logger::WARN to be written
|
|
189
|
+
# to at least one broadcast. +False+ otherwise.
|
|
163
190
|
def warn?
|
|
164
191
|
@broadcasts.any? { |logger| logger.warn? }
|
|
165
192
|
end
|
|
166
193
|
|
|
167
|
-
# Sets the log level to
|
|
194
|
+
# Sets the log level to Logger::WARN for the whole broadcast.
|
|
168
195
|
def warn!
|
|
169
|
-
dispatch
|
|
196
|
+
dispatch { |logger| logger.warn! }
|
|
170
197
|
end
|
|
171
198
|
|
|
172
|
-
# True if the log level allows entries with severity
|
|
173
|
-
# to at least one broadcast. False otherwise.
|
|
199
|
+
# +True+ if the log level allows entries with severity Logger::ERROR to be written
|
|
200
|
+
# to at least one broadcast. +False+ otherwise.
|
|
174
201
|
def error?
|
|
175
202
|
@broadcasts.any? { |logger| logger.error? }
|
|
176
203
|
end
|
|
177
204
|
|
|
178
|
-
# Sets the log level to
|
|
205
|
+
# Sets the log level to Logger::ERROR for the whole broadcast.
|
|
179
206
|
def error!
|
|
180
|
-
dispatch
|
|
207
|
+
dispatch { |logger| logger.error! }
|
|
181
208
|
end
|
|
182
209
|
|
|
183
|
-
# True if the log level allows entries with severity
|
|
184
|
-
# to at least one broadcast. False otherwise.
|
|
210
|
+
# +True+ if the log level allows entries with severity Logger::FATAL to be written
|
|
211
|
+
# to at least one broadcast. +False+ otherwise.
|
|
185
212
|
def fatal?
|
|
186
213
|
@broadcasts.any? { |logger| logger.fatal? }
|
|
187
214
|
end
|
|
188
215
|
|
|
189
|
-
# Sets the log level to
|
|
216
|
+
# Sets the log level to Logger::FATAL for the whole broadcast.
|
|
190
217
|
def fatal!
|
|
191
|
-
dispatch
|
|
218
|
+
dispatch { |logger| logger.fatal! }
|
|
192
219
|
end
|
|
193
220
|
|
|
194
221
|
def initialize_copy(other)
|
|
195
222
|
@broadcasts = []
|
|
196
223
|
@progname = other.progname.dup
|
|
224
|
+
@formatter = other.formatter.dup
|
|
197
225
|
|
|
198
226
|
broadcast_to(*other.broadcasts.map(&:dup))
|
|
199
227
|
end
|
|
200
228
|
|
|
201
229
|
private
|
|
202
|
-
def dispatch(
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
# as normal, but subsequent loggers won't re-execute the block.
|
|
206
|
-
# Instead, the initial result is immediately returned.
|
|
207
|
-
called, result = false, nil
|
|
208
|
-
block = proc { |*args, **kwargs|
|
|
209
|
-
if called then result
|
|
210
|
-
else
|
|
211
|
-
called = true
|
|
212
|
-
result = yield(*args, **kwargs)
|
|
213
|
-
end
|
|
214
|
-
}
|
|
215
|
-
end
|
|
216
|
-
|
|
217
|
-
@broadcasts.map { |logger|
|
|
218
|
-
logger.send(method, *args, **kwargs, &block)
|
|
219
|
-
}.first
|
|
230
|
+
def dispatch(&block)
|
|
231
|
+
@broadcasts.each { |logger| block.call(logger) }
|
|
232
|
+
true
|
|
220
233
|
end
|
|
221
234
|
|
|
222
235
|
def method_missing(name, ...)
|
|
@@ -57,8 +57,13 @@ module ActiveSupport
|
|
|
57
57
|
# cache.write("baz", 5)
|
|
58
58
|
# cache.increment("baz") # => 6
|
|
59
59
|
#
|
|
60
|
-
def increment(name, amount = 1,
|
|
61
|
-
|
|
60
|
+
def increment(name, amount = 1, options = nil)
|
|
61
|
+
options = merged_options(options)
|
|
62
|
+
key = normalize_key(name, options)
|
|
63
|
+
|
|
64
|
+
instrument(:increment, key, amount: amount) do
|
|
65
|
+
modify_value(name, amount, options)
|
|
66
|
+
end
|
|
62
67
|
end
|
|
63
68
|
|
|
64
69
|
# Decrement a cached integer value. Returns the updated value.
|
|
@@ -72,8 +77,13 @@ module ActiveSupport
|
|
|
72
77
|
# cache.write("baz", 5)
|
|
73
78
|
# cache.decrement("baz") # => 4
|
|
74
79
|
#
|
|
75
|
-
def decrement(name, amount = 1,
|
|
76
|
-
|
|
80
|
+
def decrement(name, amount = 1, options = nil)
|
|
81
|
+
options = merged_options(options)
|
|
82
|
+
key = normalize_key(name, options)
|
|
83
|
+
|
|
84
|
+
instrument(:decrement, key, amount: amount) do
|
|
85
|
+
modify_value(name, -amount, options)
|
|
86
|
+
end
|
|
77
87
|
end
|
|
78
88
|
|
|
79
89
|
def delete_matched(matcher, options = nil)
|
|
@@ -212,24 +212,26 @@ module ActiveSupport
|
|
|
212
212
|
def read_multi_entries(names, **options)
|
|
213
213
|
keys_to_names = names.index_by { |name| normalize_key(name, options) }
|
|
214
214
|
|
|
215
|
-
|
|
216
|
-
|
|
215
|
+
raw_values = begin
|
|
216
|
+
@data.with { |c| c.get_multi(keys_to_names.keys) }
|
|
217
|
+
rescue Dalli::UnmarshalError
|
|
218
|
+
{}
|
|
219
|
+
end
|
|
217
220
|
|
|
218
|
-
|
|
221
|
+
values = {}
|
|
219
222
|
|
|
220
|
-
|
|
221
|
-
|
|
223
|
+
raw_values.each do |key, value|
|
|
224
|
+
entry = deserialize_entry(value, raw: options[:raw])
|
|
222
225
|
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
end
|
|
226
|
+
unless entry.nil? || entry.expired? || entry.mismatched?(normalize_version(keys_to_names[key], options))
|
|
227
|
+
begin
|
|
228
|
+
values[keys_to_names[key]] = entry.value
|
|
229
|
+
rescue DeserializationError
|
|
228
230
|
end
|
|
229
231
|
end
|
|
230
|
-
|
|
231
|
-
values
|
|
232
232
|
end
|
|
233
|
+
|
|
234
|
+
values
|
|
233
235
|
end
|
|
234
236
|
|
|
235
237
|
# Delete an entry from the cache.
|
|
@@ -274,7 +276,7 @@ module ActiveSupport
|
|
|
274
276
|
|
|
275
277
|
def rescue_error_with(fallback)
|
|
276
278
|
yield
|
|
277
|
-
rescue Dalli::DalliError
|
|
279
|
+
rescue Dalli::DalliError => error
|
|
278
280
|
logger.error("DalliError (#{error}): #{error.message}") if logger
|
|
279
281
|
ActiveSupport.error_reporter&.report(
|
|
280
282
|
error,
|
|
@@ -146,8 +146,10 @@ module ActiveSupport
|
|
|
146
146
|
# cache.write("baz", 5)
|
|
147
147
|
# cache.increment("baz") # => 6
|
|
148
148
|
#
|
|
149
|
-
def increment(name, amount = 1,
|
|
150
|
-
|
|
149
|
+
def increment(name, amount = 1, options = nil)
|
|
150
|
+
instrument(:increment, name, amount: amount) do
|
|
151
|
+
modify_value(name, amount, options)
|
|
152
|
+
end
|
|
151
153
|
end
|
|
152
154
|
|
|
153
155
|
# Decrement a cached integer value. Returns the updated value.
|
|
@@ -161,8 +163,10 @@ module ActiveSupport
|
|
|
161
163
|
# cache.write("baz", 5)
|
|
162
164
|
# cache.decrement("baz") # => 4
|
|
163
165
|
#
|
|
164
|
-
def decrement(name, amount = 1,
|
|
165
|
-
|
|
166
|
+
def decrement(name, amount = 1, options = nil)
|
|
167
|
+
instrument(:decrement, name, amount: amount) do
|
|
168
|
+
modify_value(name, -amount, options)
|
|
169
|
+
end
|
|
166
170
|
end
|
|
167
171
|
|
|
168
172
|
# Deletes cache entries if the cache key matches a given pattern.
|
|
@@ -234,7 +238,7 @@ module ActiveSupport
|
|
|
234
238
|
|
|
235
239
|
# Modifies the amount of an integer value that is stored in the cache.
|
|
236
240
|
# If the key is not found it is created and set to +amount+.
|
|
237
|
-
def modify_value(name, amount,
|
|
241
|
+
def modify_value(name, amount, options)
|
|
238
242
|
options = merged_options(options)
|
|
239
243
|
key = normalize_key(name, options)
|
|
240
244
|
version = normalize_version(name, options)
|
|
@@ -25,10 +25,10 @@ module ActiveSupport
|
|
|
25
25
|
def cleanup(options = nil)
|
|
26
26
|
end
|
|
27
27
|
|
|
28
|
-
def increment(name, amount = 1,
|
|
28
|
+
def increment(name, amount = 1, options = nil)
|
|
29
29
|
end
|
|
30
30
|
|
|
31
|
-
def decrement(name, amount = 1,
|
|
31
|
+
def decrement(name, amount = 1, options = nil)
|
|
32
32
|
end
|
|
33
33
|
|
|
34
34
|
def delete_matched(matcher, options = nil)
|
|
@@ -173,9 +173,12 @@ module ActiveSupport
|
|
|
173
173
|
return {} if names.empty?
|
|
174
174
|
|
|
175
175
|
options = names.extract_options!
|
|
176
|
-
|
|
176
|
+
options = merged_options(options)
|
|
177
|
+
keys = names.map { |name| normalize_key(name, options) }
|
|
178
|
+
|
|
179
|
+
instrument_multi(:read_multi, keys, options) do |payload|
|
|
177
180
|
read_multi_entries(names, **options).tap do |results|
|
|
178
|
-
payload[:hits] = results.keys
|
|
181
|
+
payload[:hits] = results.keys.map { |name| normalize_key(name, options) }
|
|
179
182
|
end
|
|
180
183
|
end
|
|
181
184
|
end
|
|
@@ -480,7 +483,7 @@ module ActiveSupport
|
|
|
480
483
|
|
|
481
484
|
def failsafe(method, returning: nil)
|
|
482
485
|
yield
|
|
483
|
-
rescue ::Redis::BaseError
|
|
486
|
+
rescue ::Redis::BaseError => error
|
|
484
487
|
@error_handler&.call(method: method, exception: error, returning: returning)
|
|
485
488
|
returning
|
|
486
489
|
end
|
|
@@ -94,52 +94,26 @@ module ActiveSupport
|
|
|
94
94
|
super
|
|
95
95
|
end
|
|
96
96
|
|
|
97
|
-
def increment(name, amount = 1,
|
|
97
|
+
def increment(name, amount = 1, options = nil) # :nodoc:
|
|
98
98
|
return super unless local_cache
|
|
99
99
|
value = bypass_local_cache { super }
|
|
100
|
-
|
|
100
|
+
if options
|
|
101
|
+
write_cache_value(name, value, raw: true, **options)
|
|
102
|
+
else
|
|
103
|
+
write_cache_value(name, value, raw: true)
|
|
104
|
+
end
|
|
101
105
|
value
|
|
102
106
|
end
|
|
103
107
|
|
|
104
|
-
def decrement(name, amount = 1,
|
|
108
|
+
def decrement(name, amount = 1, options = nil) # :nodoc:
|
|
105
109
|
return super unless local_cache
|
|
106
110
|
value = bypass_local_cache { super }
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
def fetch_multi(*names, &block) # :nodoc:
|
|
112
|
-
return super if local_cache.nil? || names.empty?
|
|
113
|
-
|
|
114
|
-
options = names.extract_options!
|
|
115
|
-
options = merged_options(options)
|
|
116
|
-
|
|
117
|
-
keys_to_names = names.index_by { |name| normalize_key(name, options) }
|
|
118
|
-
|
|
119
|
-
local_entries = local_cache.read_multi_entries(keys_to_names.keys)
|
|
120
|
-
results = local_entries.each_with_object({}) do |(key, value), result|
|
|
121
|
-
# If we recorded a miss in the local cache, `#fetch_multi` will forward
|
|
122
|
-
# that key to the real store, and the entry will be replaced
|
|
123
|
-
# local_cache.delete_entry(key)
|
|
124
|
-
next if value.nil?
|
|
125
|
-
|
|
126
|
-
entry = deserialize_entry(value, **options)
|
|
127
|
-
|
|
128
|
-
normalized_key = keys_to_names[key]
|
|
129
|
-
if entry.nil?
|
|
130
|
-
result[normalized_key] = nil
|
|
131
|
-
elsif entry.expired? || entry.mismatched?(normalize_version(normalized_key, options))
|
|
132
|
-
local_cache.delete_entry(key)
|
|
133
|
-
else
|
|
134
|
-
result[normalized_key] = entry.value
|
|
135
|
-
end
|
|
111
|
+
if options
|
|
112
|
+
write_cache_value(name, value, raw: true, **options)
|
|
113
|
+
else
|
|
114
|
+
write_cache_value(name, value, raw: true)
|
|
136
115
|
end
|
|
137
|
-
|
|
138
|
-
if results.size < names.size
|
|
139
|
-
results.merge!(super(*(names - results.keys), options, &block))
|
|
140
|
-
end
|
|
141
|
-
|
|
142
|
-
results
|
|
116
|
+
value
|
|
143
117
|
end
|
|
144
118
|
|
|
145
119
|
private
|
|
@@ -163,27 +137,17 @@ module ActiveSupport
|
|
|
163
137
|
keys_to_names = names.index_by { |name| normalize_key(name, options) }
|
|
164
138
|
|
|
165
139
|
local_entries = local_cache.read_multi_entries(keys_to_names.keys)
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
entry = deserialize_entry(value, **options)
|
|
171
|
-
|
|
172
|
-
normalized_key = keys_to_names[key]
|
|
173
|
-
if entry.nil?
|
|
174
|
-
result[normalized_key] = nil
|
|
175
|
-
elsif entry.expired? || entry.mismatched?(normalize_version(normalized_key, options))
|
|
176
|
-
local_cache.delete_entry(key)
|
|
177
|
-
else
|
|
178
|
-
result[normalized_key] = entry.value
|
|
179
|
-
end
|
|
140
|
+
local_entries.transform_keys! { |key| keys_to_names[key] }
|
|
141
|
+
local_entries.transform_values! do |payload|
|
|
142
|
+
deserialize_entry(payload, **options)&.value
|
|
180
143
|
end
|
|
144
|
+
missed_names = names - local_entries.keys
|
|
181
145
|
|
|
182
|
-
if
|
|
183
|
-
|
|
146
|
+
if missed_names.any?
|
|
147
|
+
local_entries.merge!(super(missed_names, **options))
|
|
148
|
+
else
|
|
149
|
+
local_entries
|
|
184
150
|
end
|
|
185
|
-
|
|
186
|
-
results
|
|
187
151
|
end
|
|
188
152
|
|
|
189
153
|
def write_serialized_entry(key, payload, **)
|
data/lib/active_support/cache.rb
CHANGED
|
@@ -35,7 +35,6 @@ module ActiveSupport
|
|
|
35
35
|
:race_condition_ttl,
|
|
36
36
|
:serializer,
|
|
37
37
|
:skip_nil,
|
|
38
|
-
:raw,
|
|
39
38
|
]
|
|
40
39
|
|
|
41
40
|
# Mapping of canonical option names to aliases that a store will recognize.
|
|
@@ -387,7 +386,7 @@ module ActiveSupport
|
|
|
387
386
|
# process can try to generate a new value after the extended time window
|
|
388
387
|
# has elapsed.
|
|
389
388
|
#
|
|
390
|
-
# # Set all values to expire after one
|
|
389
|
+
# # Set all values to expire after one minute.
|
|
391
390
|
# cache = ActiveSupport::Cache::MemoryStore.new(expires_in: 1)
|
|
392
391
|
#
|
|
393
392
|
# cache.write("foo", "original value")
|
|
@@ -539,10 +538,11 @@ module ActiveSupport
|
|
|
539
538
|
|
|
540
539
|
options = names.extract_options!
|
|
541
540
|
options = merged_options(options)
|
|
541
|
+
keys = names.map { |name| normalize_key(name, options) }
|
|
542
542
|
|
|
543
|
-
instrument_multi :read_multi,
|
|
543
|
+
instrument_multi :read_multi, keys, options do |payload|
|
|
544
544
|
read_multi_entries(names, **options, event: payload).tap do |results|
|
|
545
|
-
payload[:hits] = results.keys
|
|
545
|
+
payload[:hits] = results.keys.map { |name| normalize_key(name, options) }
|
|
546
546
|
end
|
|
547
547
|
end
|
|
548
548
|
end
|
|
@@ -552,8 +552,9 @@ module ActiveSupport
|
|
|
552
552
|
return hash if hash.empty?
|
|
553
553
|
|
|
554
554
|
options = merged_options(options)
|
|
555
|
+
normalized_hash = hash.transform_keys { |key| normalize_key(key, options) }
|
|
555
556
|
|
|
556
|
-
instrument_multi :write_multi,
|
|
557
|
+
instrument_multi :write_multi, normalized_hash, options do |payload|
|
|
557
558
|
entries = hash.each_with_object({}) do |(name, value), memo|
|
|
558
559
|
memo[normalize_key(name, options)] = Entry.new(value, **options.merge(version: normalize_version(name, options)))
|
|
559
560
|
end
|
|
@@ -597,9 +598,9 @@ module ActiveSupport
|
|
|
597
598
|
|
|
598
599
|
options = names.extract_options!
|
|
599
600
|
options = merged_options(options)
|
|
600
|
-
|
|
601
|
+
keys = names.map { |name| normalize_key(name, options) }
|
|
601
602
|
writes = {}
|
|
602
|
-
ordered = instrument_multi :read_multi,
|
|
603
|
+
ordered = instrument_multi :read_multi, keys, options do |payload|
|
|
603
604
|
if options[:force]
|
|
604
605
|
reads = {}
|
|
605
606
|
else
|
|
@@ -611,7 +612,7 @@ module ActiveSupport
|
|
|
611
612
|
end
|
|
612
613
|
writes.compact! if options[:skip_nil]
|
|
613
614
|
|
|
614
|
-
payload[:hits] = reads.keys
|
|
615
|
+
payload[:hits] = reads.keys.map { |name| normalize_key(name, options) }
|
|
615
616
|
payload[:super_operation] = :fetch_multi
|
|
616
617
|
|
|
617
618
|
ordered
|
|
@@ -944,9 +945,12 @@ module ActiveSupport
|
|
|
944
945
|
#
|
|
945
946
|
# namespace_key 'foo', namespace: -> { 'cache' }
|
|
946
947
|
# # => 'cache:foo'
|
|
947
|
-
def namespace_key(key,
|
|
948
|
-
|
|
949
|
-
|
|
948
|
+
def namespace_key(key, call_options = nil)
|
|
949
|
+
namespace = if call_options&.key?(:namespace)
|
|
950
|
+
call_options[:namespace]
|
|
951
|
+
else
|
|
952
|
+
options[:namespace]
|
|
953
|
+
end
|
|
950
954
|
|
|
951
955
|
if namespace.respond_to?(:call)
|
|
952
956
|
namespace = namespace.call
|
|
@@ -1031,7 +1035,8 @@ module ActiveSupport
|
|
|
1031
1035
|
# When an entry has a positive :race_condition_ttl defined, put the stale entry back into the cache
|
|
1032
1036
|
# for a brief period while the entry is being recalculated.
|
|
1033
1037
|
entry.expires_at = Time.now.to_f + race_ttl
|
|
1034
|
-
|
|
1038
|
+
options[:expires_in] = race_ttl * 2
|
|
1039
|
+
write_entry(key, entry, **options)
|
|
1035
1040
|
else
|
|
1036
1041
|
delete_entry(key, **options)
|
|
1037
1042
|
end
|
|
@@ -6,7 +6,6 @@ require "active_support/core_ext/array/extract_options"
|
|
|
6
6
|
require "active_support/core_ext/class/attribute"
|
|
7
7
|
require "active_support/core_ext/string/filters"
|
|
8
8
|
require "active_support/core_ext/object/blank"
|
|
9
|
-
require "thread"
|
|
10
9
|
|
|
11
10
|
module ActiveSupport
|
|
12
11
|
# = Active Support \Callbacks
|
|
@@ -67,7 +66,7 @@ module ActiveSupport
|
|
|
67
66
|
|
|
68
67
|
included do
|
|
69
68
|
extend ActiveSupport::DescendantsTracker
|
|
70
|
-
class_attribute :__callbacks, instance_writer: false, default: {}
|
|
69
|
+
class_attribute :__callbacks, instance_writer: false, instance_predicate: false, default: {}
|
|
71
70
|
end
|
|
72
71
|
|
|
73
72
|
CALLBACK_FILTER_TYPES = [:before, :after, :around].freeze
|
|
@@ -499,10 +498,9 @@ module ActiveSupport
|
|
|
499
498
|
when Conditionals::Value
|
|
500
499
|
ProcCall.new(filter)
|
|
501
500
|
when ::Proc
|
|
502
|
-
|
|
503
|
-
when 2
|
|
501
|
+
if filter.arity > 1
|
|
504
502
|
InstanceExec2.new(filter)
|
|
505
|
-
|
|
503
|
+
elsif filter.arity > 0
|
|
506
504
|
InstanceExec1.new(filter)
|
|
507
505
|
else
|
|
508
506
|
InstanceExec0.new(filter)
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module ActiveSupport
|
|
4
|
+
module ClassAttribute # :nodoc:
|
|
5
|
+
class << self
|
|
6
|
+
def redefine(owner, name, value)
|
|
7
|
+
if owner.singleton_class?
|
|
8
|
+
owner.redefine_method(name) { value }
|
|
9
|
+
owner.send(:public, name)
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
owner.redefine_singleton_method(name) { value }
|
|
13
|
+
owner.singleton_class.send(:public, name)
|
|
14
|
+
|
|
15
|
+
owner.redefine_singleton_method("#{name}=") do |new_value|
|
|
16
|
+
if owner.equal?(self)
|
|
17
|
+
value = new_value
|
|
18
|
+
else
|
|
19
|
+
::ActiveSupport::ClassAttribute.redefine(self, name, new_value)
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
owner.singleton_class.send(:public, "#{name}=")
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
@@ -55,6 +55,11 @@ module ActiveSupport
|
|
|
55
55
|
@path = path
|
|
56
56
|
@line = line
|
|
57
57
|
@namespaces = Hash.new { |h, k| h[k] = MethodSet.new(k) }
|
|
58
|
+
@sources = []
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def class_eval
|
|
62
|
+
yield @sources
|
|
58
63
|
end
|
|
59
64
|
|
|
60
65
|
def define_cached_method(canonical_name, namespace:, as: nil, &block)
|
|
@@ -65,6 +70,10 @@ module ActiveSupport
|
|
|
65
70
|
@namespaces.each_value do |method_set|
|
|
66
71
|
method_set.apply(@owner, @path, @line - 1)
|
|
67
72
|
end
|
|
73
|
+
|
|
74
|
+
unless @sources.empty?
|
|
75
|
+
@owner.class_eval("# frozen_string_literal: true\n" + @sources.join(";"), @path, @line - 1)
|
|
76
|
+
end
|
|
68
77
|
end
|
|
69
78
|
end
|
|
70
79
|
end
|
|
@@ -19,11 +19,20 @@ module ActiveSupport
|
|
|
19
19
|
end
|
|
20
20
|
|
|
21
21
|
def parse(context: nil, **options)
|
|
22
|
-
source = render(context)
|
|
23
|
-
|
|
24
|
-
|
|
22
|
+
source = @content.include?("<%") ? render(context) : @content
|
|
23
|
+
|
|
24
|
+
if source == @content
|
|
25
|
+
if YAML.respond_to?(:unsafe_load)
|
|
26
|
+
YAML.unsafe_load_file(@content_path, **options) || {}
|
|
27
|
+
else
|
|
28
|
+
YAML.load_file(@content_path, **options) || {}
|
|
29
|
+
end
|
|
25
30
|
else
|
|
26
|
-
YAML.
|
|
31
|
+
if YAML.respond_to?(:unsafe_load)
|
|
32
|
+
YAML.unsafe_load(source, **options) || {}
|
|
33
|
+
else
|
|
34
|
+
YAML.load(source, **options) || {}
|
|
35
|
+
end
|
|
27
36
|
end
|
|
28
37
|
rescue Psych::SyntaxError => error
|
|
29
38
|
raise "YAML syntax error occurred while parsing #{@content_path}. " \
|
|
@@ -33,8 +42,7 @@ module ActiveSupport
|
|
|
33
42
|
|
|
34
43
|
private
|
|
35
44
|
def read(content_path)
|
|
36
|
-
require "yaml"
|
|
37
|
-
require "erb"
|
|
45
|
+
require "yaml" unless defined?(YAML)
|
|
38
46
|
|
|
39
47
|
File.read(content_path).tap do |content|
|
|
40
48
|
if content.include?("\u00A0")
|
|
@@ -44,6 +52,7 @@ module ActiveSupport
|
|
|
44
52
|
end
|
|
45
53
|
|
|
46
54
|
def render(context)
|
|
55
|
+
require "erb" unless defined?(ERB)
|
|
47
56
|
erb = ERB.new(@content).tap { |e| e.filename = @content_path }
|
|
48
57
|
context ? erb.result(context) : erb.result
|
|
49
58
|
end
|