activesupport 8.0.0 → 8.1.0
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 +391 -67
- data/README.rdoc +1 -1
- data/lib/active_support/backtrace_cleaner.rb +72 -1
- data/lib/active_support/broadcast_logger.rb +61 -74
- data/lib/active_support/cache/file_store.rb +2 -2
- data/lib/active_support/cache/mem_cache_store.rb +26 -28
- data/lib/active_support/cache/memory_store.rb +5 -5
- data/lib/active_support/cache/null_store.rb +2 -2
- data/lib/active_support/cache/redis_cache_store.rb +37 -31
- data/lib/active_support/cache/strategy/local_cache.rb +72 -27
- data/lib/active_support/cache/strategy/local_cache_middleware.rb +7 -7
- data/lib/active_support/cache.rb +72 -9
- data/lib/active_support/callbacks.rb +27 -11
- data/lib/active_support/class_attribute.rb +15 -8
- data/lib/active_support/concurrency/load_interlock_aware_monitor.rb +8 -62
- data/lib/active_support/concurrency/thread_monitor.rb +55 -0
- data/lib/active_support/configurable.rb +34 -0
- data/lib/active_support/continuous_integration.rb +145 -0
- data/lib/active_support/core_ext/array/conversions.rb +3 -3
- data/lib/active_support/core_ext/array.rb +7 -7
- data/lib/active_support/core_ext/benchmark.rb +4 -11
- data/lib/active_support/core_ext/big_decimal.rb +1 -1
- data/lib/active_support/core_ext/class/attribute.rb +20 -5
- data/lib/active_support/core_ext/class.rb +2 -2
- data/lib/active_support/core_ext/date.rb +5 -5
- data/lib/active_support/core_ext/date_and_time/compatibility.rb +0 -35
- data/lib/active_support/core_ext/date_time/compatibility.rb +3 -5
- data/lib/active_support/core_ext/date_time/conversions.rb +4 -2
- data/lib/active_support/core_ext/date_time.rb +5 -5
- data/lib/active_support/core_ext/digest.rb +1 -1
- data/lib/active_support/core_ext/enumerable.rb +17 -5
- data/lib/active_support/core_ext/erb/util.rb +5 -5
- data/lib/active_support/core_ext/file.rb +1 -1
- data/lib/active_support/core_ext/hash/deep_merge.rb +1 -0
- data/lib/active_support/core_ext/hash.rb +8 -8
- data/lib/active_support/core_ext/integer.rb +3 -3
- data/lib/active_support/core_ext/kernel.rb +3 -3
- data/lib/active_support/core_ext/module/introspection.rb +3 -0
- data/lib/active_support/core_ext/module.rb +11 -11
- data/lib/active_support/core_ext/numeric.rb +3 -3
- data/lib/active_support/core_ext/object/json.rb +8 -1
- data/lib/active_support/core_ext/object/to_query.rb +7 -1
- data/lib/active_support/core_ext/object/try.rb +2 -2
- data/lib/active_support/core_ext/object.rb +13 -13
- data/lib/active_support/core_ext/pathname.rb +2 -2
- data/lib/active_support/core_ext/range/overlap.rb +3 -3
- data/lib/active_support/core_ext/range/sole.rb +17 -0
- data/lib/active_support/core_ext/range.rb +4 -4
- data/lib/active_support/core_ext/securerandom.rb +24 -8
- data/lib/active_support/core_ext/string/filters.rb +3 -3
- data/lib/active_support/core_ext/string/multibyte.rb +12 -3
- data/lib/active_support/core_ext/string/output_safety.rb +19 -12
- data/lib/active_support/core_ext/string.rb +13 -13
- data/lib/active_support/core_ext/symbol.rb +1 -1
- data/lib/active_support/core_ext/time/calculations.rb +0 -7
- data/lib/active_support/core_ext/time/compatibility.rb +2 -27
- data/lib/active_support/core_ext/time.rb +5 -5
- data/lib/active_support/core_ext.rb +1 -1
- data/lib/active_support/current_attributes/test_helper.rb +2 -2
- data/lib/active_support/current_attributes.rb +27 -17
- data/lib/active_support/dependencies/interlock.rb +11 -5
- data/lib/active_support/dependencies.rb +6 -1
- data/lib/active_support/deprecation/reporting.rb +4 -2
- data/lib/active_support/deprecation.rb +1 -1
- data/lib/active_support/editor.rb +70 -0
- data/lib/active_support/error_reporter.rb +61 -8
- data/lib/active_support/event_reporter/test_helper.rb +32 -0
- data/lib/active_support/event_reporter.rb +592 -0
- data/lib/active_support/evented_file_update_checker.rb +5 -1
- data/lib/active_support/execution_context.rb +64 -7
- data/lib/active_support/execution_wrapper.rb +1 -1
- data/lib/active_support/file_update_checker.rb +8 -6
- data/lib/active_support/gem_version.rb +1 -1
- data/lib/active_support/gzip.rb +1 -0
- data/lib/active_support/hash_with_indifferent_access.rb +47 -24
- data/lib/active_support/i18n_railtie.rb +1 -2
- data/lib/active_support/inflector/inflections.rb +31 -15
- data/lib/active_support/inflector/transliterate.rb +6 -8
- data/lib/active_support/isolated_execution_state.rb +12 -15
- data/lib/active_support/json/decoding.rb +6 -4
- data/lib/active_support/json/encoding.rb +155 -19
- data/lib/active_support/lazy_load_hooks.rb +1 -1
- data/lib/active_support/log_subscriber.rb +2 -6
- data/lib/active_support/logger_thread_safe_level.rb +6 -3
- data/lib/active_support/message_encryptors.rb +54 -2
- data/lib/active_support/message_pack/extensions.rb +5 -0
- data/lib/active_support/message_verifier.rb +9 -0
- data/lib/active_support/message_verifiers.rb +57 -3
- data/lib/active_support/messages/rotation_coordinator.rb +9 -0
- data/lib/active_support/messages/rotator.rb +10 -0
- data/lib/active_support/multibyte/chars.rb +12 -2
- data/lib/active_support/multibyte.rb +4 -0
- data/lib/active_support/notifications/fanout.rb +64 -42
- data/lib/active_support/notifications/instrumenter.rb +1 -1
- data/lib/active_support/railtie.rb +32 -13
- data/lib/active_support/structured_event_subscriber.rb +99 -0
- data/lib/active_support/subscriber.rb +0 -5
- data/lib/active_support/syntax_error_proxy.rb +3 -0
- data/lib/active_support/test_case.rb +61 -6
- data/lib/active_support/testing/assertions.rb +34 -6
- data/lib/active_support/testing/error_reporter_assertions.rb +18 -1
- data/lib/active_support/testing/event_reporter_assertions.rb +227 -0
- data/lib/active_support/testing/notification_assertions.rb +92 -0
- data/lib/active_support/testing/parallelization/server.rb +15 -2
- data/lib/active_support/testing/parallelization/worker.rb +4 -2
- data/lib/active_support/testing/parallelization.rb +25 -1
- data/lib/active_support/testing/tests_without_assertions.rb +1 -1
- data/lib/active_support/testing/time_helpers.rb +7 -3
- data/lib/active_support/time_with_zone.rb +23 -23
- data/lib/active_support/values/time_zone.rb +8 -1
- data/lib/active_support/xml_mini.rb +3 -2
- data/lib/active_support.rb +20 -15
- metadata +27 -23
- data/lib/active_support/core_ext/range/each.rb +0 -24
- data/lib/active_support/testing/strict_warnings.rb +0 -43
|
@@ -149,12 +149,6 @@ module ActiveSupport
|
|
|
149
149
|
log_exception(event.name, e)
|
|
150
150
|
end
|
|
151
151
|
|
|
152
|
-
def publish_event(event)
|
|
153
|
-
super if logger
|
|
154
|
-
rescue => e
|
|
155
|
-
log_exception(event.name, e)
|
|
156
|
-
end
|
|
157
|
-
|
|
158
152
|
attr_writer :event_levels # :nodoc:
|
|
159
153
|
|
|
160
154
|
private
|
|
@@ -184,6 +178,8 @@ module ActiveSupport
|
|
|
184
178
|
end
|
|
185
179
|
|
|
186
180
|
def log_exception(name, e)
|
|
181
|
+
ActiveSupport.error_reporter.report(e, source: name)
|
|
182
|
+
|
|
187
183
|
if logger
|
|
188
184
|
logger.error "Could not log #{name.inspect} event. #{e.class}: #{e.message} #{e.backtrace}"
|
|
189
185
|
end
|
|
@@ -7,6 +7,11 @@ module ActiveSupport
|
|
|
7
7
|
module LoggerThreadSafeLevel # :nodoc:
|
|
8
8
|
extend ActiveSupport::Concern
|
|
9
9
|
|
|
10
|
+
def initialize(...)
|
|
11
|
+
super
|
|
12
|
+
@local_level_key = :"logger_thread_safe_level_#{object_id}"
|
|
13
|
+
end
|
|
14
|
+
|
|
10
15
|
def local_level
|
|
11
16
|
IsolatedExecutionState[local_level_key]
|
|
12
17
|
end
|
|
@@ -40,8 +45,6 @@ module ActiveSupport
|
|
|
40
45
|
end
|
|
41
46
|
|
|
42
47
|
private
|
|
43
|
-
|
|
44
|
-
@local_level_key ||= :"logger_thread_safe_level_#{object_id}"
|
|
45
|
-
end
|
|
48
|
+
attr_reader :local_level_key
|
|
46
49
|
end
|
|
47
50
|
end
|
|
@@ -26,10 +26,13 @@ module ActiveSupport
|
|
|
26
26
|
# as the first rotation and <tt>transitional = true</tt>. Then, after all
|
|
27
27
|
# servers have been updated, perform a second rolling deploy with
|
|
28
28
|
# <tt>transitional = false</tt>.
|
|
29
|
+
#
|
|
30
|
+
#--
|
|
31
|
+
# Implemented by ActiveSupport::Messages::RotationCoordinator#transitional
|
|
29
32
|
|
|
30
33
|
##
|
|
31
|
-
# :method:
|
|
32
|
-
# :call-seq:
|
|
34
|
+
# :singleton-method: new
|
|
35
|
+
# :call-seq: new(&secret_generator)
|
|
33
36
|
#
|
|
34
37
|
# Initializes a new instance. +secret_generator+ must accept a salt and a
|
|
35
38
|
# +secret_length+ kwarg, and return a suitable secret (string) or secrets
|
|
@@ -43,6 +46,9 @@ module ActiveSupport
|
|
|
43
46
|
# end
|
|
44
47
|
#
|
|
45
48
|
# encryptors.rotate(base: "...")
|
|
49
|
+
#
|
|
50
|
+
#--
|
|
51
|
+
# Implemented by ActiveSupport::Messages::RotationCoordinator#initialize
|
|
46
52
|
|
|
47
53
|
##
|
|
48
54
|
# :method: []
|
|
@@ -51,12 +57,18 @@ module ActiveSupport
|
|
|
51
57
|
# Returns a MessageEncryptor configured with a secret derived from the
|
|
52
58
|
# given +salt+, and options from #rotate. MessageEncryptor instances will
|
|
53
59
|
# be memoized, so the same +salt+ will return the same instance.
|
|
60
|
+
#
|
|
61
|
+
#--
|
|
62
|
+
# Implemented by ActiveSupport::Messages::RotationCoordinator#[]
|
|
54
63
|
|
|
55
64
|
##
|
|
56
65
|
# :method: []=
|
|
57
66
|
# :call-seq: []=(salt, encryptor)
|
|
58
67
|
#
|
|
59
68
|
# Overrides a MessageEncryptor instance associated with a given +salt+.
|
|
69
|
+
#
|
|
70
|
+
#--
|
|
71
|
+
# Implemented by ActiveSupport::Messages::RotationCoordinator#[]=
|
|
60
72
|
|
|
61
73
|
##
|
|
62
74
|
# :method: rotate
|
|
@@ -106,18 +118,55 @@ module ActiveSupport
|
|
|
106
118
|
#
|
|
107
119
|
# # Uses `serializer: Marshal, url_safe: false`.
|
|
108
120
|
# encryptors[:baz]
|
|
121
|
+
#
|
|
122
|
+
#--
|
|
123
|
+
# Implemented by ActiveSupport::Messages::RotationCoordinator#rotate
|
|
124
|
+
|
|
125
|
+
##
|
|
126
|
+
# :method: prepend
|
|
127
|
+
# :call-seq:
|
|
128
|
+
# prepend(**options)
|
|
129
|
+
# prepend(&block)
|
|
130
|
+
#
|
|
131
|
+
# Just like #rotate, but prepends the given options or block to the list of
|
|
132
|
+
# option sets.
|
|
133
|
+
#
|
|
134
|
+
# This can be useful when you have an already-configured +MessageEncryptors+
|
|
135
|
+
# instance, but you want to override the way messages are encrypted.
|
|
136
|
+
#
|
|
137
|
+
# module ThirdParty
|
|
138
|
+
# ENCRYPTORS = ActiveSupport::MessageEncryptors.new { ... }.
|
|
139
|
+
# rotate(serializer: Marshal, url_safe: true).
|
|
140
|
+
# rotate(serializer: Marshal, url_safe: false)
|
|
141
|
+
# end
|
|
142
|
+
#
|
|
143
|
+
# ThirdParty.ENCRYPTORS.prepend(serializer: JSON, url_safe: true)
|
|
144
|
+
#
|
|
145
|
+
# # Uses `serializer: JSON, url_safe: true`.
|
|
146
|
+
# # Falls back to `serializer: Marshal, url_safe: true` or
|
|
147
|
+
# # `serializer: Marshal, url_safe: false`.
|
|
148
|
+
# ThirdParty.ENCRYPTORS[:foo]
|
|
149
|
+
#
|
|
150
|
+
#--
|
|
151
|
+
# Implemented by ActiveSupport::Messages::RotationCoordinator#prepend
|
|
109
152
|
|
|
110
153
|
##
|
|
111
154
|
# :method: rotate_defaults
|
|
112
155
|
# :call-seq: rotate_defaults
|
|
113
156
|
#
|
|
114
157
|
# Invokes #rotate with the default options.
|
|
158
|
+
#
|
|
159
|
+
#--
|
|
160
|
+
# Implemented by ActiveSupport::Messages::RotationCoordinator#rotate_defaults
|
|
115
161
|
|
|
116
162
|
##
|
|
117
163
|
# :method: clear_rotations
|
|
118
164
|
# :call-seq: clear_rotations
|
|
119
165
|
#
|
|
120
166
|
# Clears the list of option sets.
|
|
167
|
+
#
|
|
168
|
+
#--
|
|
169
|
+
# Implemented by ActiveSupport::Messages::RotationCoordinator#clear_rotations
|
|
121
170
|
|
|
122
171
|
##
|
|
123
172
|
# :method: on_rotation
|
|
@@ -129,6 +178,9 @@ module ActiveSupport
|
|
|
129
178
|
# For example, this callback could log each time it is called, and thus
|
|
130
179
|
# indicate whether old option sets are still in use or can be removed from
|
|
131
180
|
# rotation.
|
|
181
|
+
#
|
|
182
|
+
#--
|
|
183
|
+
# Implemented by ActiveSupport::Messages::RotationCoordinator#on_rotation
|
|
132
184
|
|
|
133
185
|
##
|
|
134
186
|
private
|
|
@@ -7,6 +7,7 @@ require "pathname"
|
|
|
7
7
|
require "uri/generic"
|
|
8
8
|
require "msgpack/bigint"
|
|
9
9
|
require "active_support/hash_with_indifferent_access"
|
|
10
|
+
require "active_support/core_ext/string/output_safety"
|
|
10
11
|
require "active_support/time"
|
|
11
12
|
|
|
12
13
|
module ActiveSupport
|
|
@@ -102,6 +103,10 @@ module ActiveSupport
|
|
|
102
103
|
packer: method(:write_hash_with_indifferent_access),
|
|
103
104
|
unpacker: method(:read_hash_with_indifferent_access),
|
|
104
105
|
recursive: true
|
|
106
|
+
|
|
107
|
+
registry.register_type 18, ActiveSupport::SafeBuffer,
|
|
108
|
+
packer: :to_s,
|
|
109
|
+
unpacker: :new
|
|
105
110
|
end
|
|
106
111
|
|
|
107
112
|
def install_unregistered_type_error(registry)
|
|
@@ -154,6 +154,8 @@ module ActiveSupport
|
|
|
154
154
|
# not URL-safe. In other words, they can contain "+" and "/". If you want to
|
|
155
155
|
# generate URL-safe strings (in compliance with "Base 64 Encoding with URL
|
|
156
156
|
# and Filename Safe Alphabet" in RFC 4648), you can pass +true+.
|
|
157
|
+
# Note that MessageVerifier will always accept both URL-safe and URL-unsafe
|
|
158
|
+
# encoded messages, to allow a smooth transition between the two settings.
|
|
157
159
|
#
|
|
158
160
|
# [+:force_legacy_metadata_serializer+]
|
|
159
161
|
# Whether to use the legacy metadata serializer, which serializes the
|
|
@@ -318,6 +320,13 @@ module ActiveSupport
|
|
|
318
320
|
end
|
|
319
321
|
|
|
320
322
|
private
|
|
323
|
+
def decode(encoded, url_safe: @url_safe)
|
|
324
|
+
catch :invalid_message_format do
|
|
325
|
+
return super
|
|
326
|
+
end
|
|
327
|
+
super(encoded, url_safe: !url_safe)
|
|
328
|
+
end
|
|
329
|
+
|
|
321
330
|
def sign_encoded(encoded)
|
|
322
331
|
digest = generate_digest(encoded)
|
|
323
332
|
encoded << SEPARATOR << digest
|
|
@@ -26,10 +26,13 @@ module ActiveSupport
|
|
|
26
26
|
# as the first rotation and <tt>transitional = true</tt>. Then, after all
|
|
27
27
|
# servers have been updated, perform a second rolling deploy with
|
|
28
28
|
# <tt>transitional = false</tt>.
|
|
29
|
+
#
|
|
30
|
+
#--
|
|
31
|
+
# Implemented by ActiveSupport::Messages::RotationCoordinator#transitional
|
|
29
32
|
|
|
30
33
|
##
|
|
31
|
-
# :method:
|
|
32
|
-
# :call-seq:
|
|
34
|
+
# :singleton-method: new
|
|
35
|
+
# :call-seq: new(&secret_generator)
|
|
33
36
|
#
|
|
34
37
|
# Initializes a new instance. +secret_generator+ must accept a salt, and
|
|
35
38
|
# return a suitable secret (string). +secret_generator+ may also accept
|
|
@@ -42,6 +45,9 @@ module ActiveSupport
|
|
|
42
45
|
# end
|
|
43
46
|
#
|
|
44
47
|
# verifiers.rotate(base: "...")
|
|
48
|
+
#
|
|
49
|
+
#--
|
|
50
|
+
# Implemented by ActiveSupport::Messages::RotationCoordinator#initialize
|
|
45
51
|
|
|
46
52
|
##
|
|
47
53
|
# :method: []
|
|
@@ -50,16 +56,24 @@ module ActiveSupport
|
|
|
50
56
|
# Returns a MessageVerifier configured with a secret derived from the
|
|
51
57
|
# given +salt+, and options from #rotate. MessageVerifier instances will
|
|
52
58
|
# be memoized, so the same +salt+ will return the same instance.
|
|
59
|
+
#
|
|
60
|
+
#--
|
|
61
|
+
# Implemented by ActiveSupport::Messages::RotationCoordinator#[]
|
|
53
62
|
|
|
54
63
|
##
|
|
55
64
|
# :method: []=
|
|
56
65
|
# :call-seq: []=(salt, verifier)
|
|
57
66
|
#
|
|
58
67
|
# Overrides a MessageVerifier instance associated with a given +salt+.
|
|
68
|
+
#
|
|
69
|
+
#--
|
|
70
|
+
# Implemented by ActiveSupport::Messages::RotationCoordinator#[]=
|
|
59
71
|
|
|
60
72
|
##
|
|
61
73
|
# :method: rotate
|
|
62
|
-
# :call-seq:
|
|
74
|
+
# :call-seq:
|
|
75
|
+
# rotate(**options)
|
|
76
|
+
# rotate(&block)
|
|
63
77
|
#
|
|
64
78
|
# Adds +options+ to the list of option sets. Messages will be signed using
|
|
65
79
|
# the first set in the list. When verifying, however, each set will be
|
|
@@ -102,18 +116,55 @@ module ActiveSupport
|
|
|
102
116
|
#
|
|
103
117
|
# # Uses `serializer: Marshal, url_safe: false`.
|
|
104
118
|
# verifiers[:baz]
|
|
119
|
+
#
|
|
120
|
+
#--
|
|
121
|
+
# Implemented by ActiveSupport::Messages::RotationCoordinator#rotate
|
|
122
|
+
|
|
123
|
+
##
|
|
124
|
+
# :method: prepend
|
|
125
|
+
# :call-seq:
|
|
126
|
+
# prepend(**options)
|
|
127
|
+
# prepend(&block)
|
|
128
|
+
#
|
|
129
|
+
# Just like #rotate, but prepends the given options or block to the list of
|
|
130
|
+
# option sets.
|
|
131
|
+
#
|
|
132
|
+
# This can be useful when you have an already-configured +MessageVerifiers+
|
|
133
|
+
# instance, but you want to override the way messages are signed.
|
|
134
|
+
#
|
|
135
|
+
# module ThirdParty
|
|
136
|
+
# VERIFIERS = ActiveSupport::MessageVerifiers.new { ... }.
|
|
137
|
+
# rotate(serializer: Marshal, url_safe: true).
|
|
138
|
+
# rotate(serializer: Marshal, url_safe: false)
|
|
139
|
+
# end
|
|
140
|
+
#
|
|
141
|
+
# ThirdParty.VERIFIERS.prepend(serializer: JSON, url_safe: true)
|
|
142
|
+
#
|
|
143
|
+
# # Uses `serializer: JSON, url_safe: true`.
|
|
144
|
+
# # Falls back to `serializer: Marshal, url_safe: true` or
|
|
145
|
+
# # `serializer: Marshal, url_safe: false`.
|
|
146
|
+
# ThirdParty.VERIFIERS[:foo]
|
|
147
|
+
#
|
|
148
|
+
#--
|
|
149
|
+
# Implemented by ActiveSupport::Messages::RotationCoordinator#prepend
|
|
105
150
|
|
|
106
151
|
##
|
|
107
152
|
# :method: rotate_defaults
|
|
108
153
|
# :call-seq: rotate_defaults
|
|
109
154
|
#
|
|
110
155
|
# Invokes #rotate with the default options.
|
|
156
|
+
#
|
|
157
|
+
#--
|
|
158
|
+
# Implemented by ActiveSupport::Messages::RotationCoordinator#rotate_defaults
|
|
111
159
|
|
|
112
160
|
##
|
|
113
161
|
# :method: clear_rotations
|
|
114
162
|
# :call-seq: clear_rotations
|
|
115
163
|
#
|
|
116
164
|
# Clears the list of option sets.
|
|
165
|
+
#
|
|
166
|
+
#--
|
|
167
|
+
# Implemented by ActiveSupport::Messages::RotationCoordinator#clear_rotations
|
|
117
168
|
|
|
118
169
|
##
|
|
119
170
|
# :method: on_rotation
|
|
@@ -125,6 +176,9 @@ module ActiveSupport
|
|
|
125
176
|
# For example, this callback could log each time it is called, and thus
|
|
126
177
|
# indicate whether old option sets are still in use or can be removed from
|
|
127
178
|
# rotation.
|
|
179
|
+
#
|
|
180
|
+
#--
|
|
181
|
+
# Implemented by ActiveSupport::Messages::RotationCoordinator#on_rotation
|
|
128
182
|
|
|
129
183
|
##
|
|
130
184
|
private
|
|
@@ -32,6 +32,15 @@ module ActiveSupport
|
|
|
32
32
|
self
|
|
33
33
|
end
|
|
34
34
|
|
|
35
|
+
def prepend(**options, &block)
|
|
36
|
+
raise ArgumentError, "Options cannot be specified when using a block" if block && !options.empty?
|
|
37
|
+
changing_configuration!
|
|
38
|
+
|
|
39
|
+
@rotate_options.unshift(block || options)
|
|
40
|
+
|
|
41
|
+
self
|
|
42
|
+
end
|
|
43
|
+
|
|
35
44
|
def rotate_defaults
|
|
36
45
|
rotate()
|
|
37
46
|
end
|
|
@@ -15,6 +15,11 @@ module ActiveSupport
|
|
|
15
15
|
fall_back_to build_rotation(*args, **options)
|
|
16
16
|
end
|
|
17
17
|
|
|
18
|
+
def on_rotation(&on_rotation)
|
|
19
|
+
@on_rotation = on_rotation
|
|
20
|
+
self
|
|
21
|
+
end
|
|
22
|
+
|
|
18
23
|
def fall_back_to(fallback)
|
|
19
24
|
@rotations << fallback
|
|
20
25
|
self
|
|
@@ -40,6 +45,11 @@ module ActiveSupport
|
|
|
40
45
|
end
|
|
41
46
|
end
|
|
42
47
|
|
|
48
|
+
def initialize_dup(*)
|
|
49
|
+
super
|
|
50
|
+
@rotations = @rotations.dup
|
|
51
|
+
end
|
|
52
|
+
|
|
43
53
|
private
|
|
44
54
|
def build_rotation(*args, **options)
|
|
45
55
|
self.class.new(*args, *@args.drop(args.length), **@options, **options)
|
|
@@ -53,9 +53,19 @@ module ActiveSupport # :nodoc:
|
|
|
53
53
|
delegate :<=>, :=~, :match?, :acts_like_string?, to: :wrapped_string
|
|
54
54
|
|
|
55
55
|
# Creates a new Chars instance by wrapping _string_.
|
|
56
|
-
def initialize(string)
|
|
56
|
+
def initialize(string, deprecation: true)
|
|
57
|
+
if deprecation
|
|
58
|
+
ActiveSupport.deprecator.warn(
|
|
59
|
+
"ActiveSupport::Multibyte::Chars is deprecated and will be removed in Rails 8.2. " \
|
|
60
|
+
"Use normal string methods instead."
|
|
61
|
+
)
|
|
62
|
+
end
|
|
63
|
+
|
|
57
64
|
@wrapped_string = string
|
|
58
|
-
|
|
65
|
+
if string.encoding != Encoding::UTF_8
|
|
66
|
+
@wrapped_string = @wrapped_string.dup
|
|
67
|
+
@wrapped_string.force_encoding(Encoding::UTF_8)
|
|
68
|
+
end
|
|
59
69
|
end
|
|
60
70
|
|
|
61
71
|
# Forward all undefined methods to the wrapped string.
|
|
@@ -12,6 +12,10 @@ module ActiveSupport # :nodoc:
|
|
|
12
12
|
#
|
|
13
13
|
# ActiveSupport::Multibyte.proxy_class = CharsForUTF32
|
|
14
14
|
def self.proxy_class=(klass)
|
|
15
|
+
ActiveSupport.deprecator.warn(
|
|
16
|
+
"ActiveSupport::Multibyte.proxy_class= is deprecated and will be removed in Rails 8.2. " \
|
|
17
|
+
"Use normal string methods instead."
|
|
18
|
+
)
|
|
15
19
|
@proxy_class = klass
|
|
16
20
|
end
|
|
17
21
|
|
|
@@ -17,24 +17,30 @@ module ActiveSupport
|
|
|
17
17
|
|
|
18
18
|
module FanoutIteration # :nodoc:
|
|
19
19
|
private
|
|
20
|
-
def iterate_guarding_exceptions(collection)
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
exceptions
|
|
27
|
-
exceptions << e
|
|
28
|
-
end
|
|
20
|
+
def iterate_guarding_exceptions(collection, &block)
|
|
21
|
+
case collection.size
|
|
22
|
+
when 0
|
|
23
|
+
when 1
|
|
24
|
+
collection.each(&block)
|
|
25
|
+
else
|
|
26
|
+
exceptions = nil
|
|
29
27
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
28
|
+
collection.each do |s|
|
|
29
|
+
yield s
|
|
30
|
+
rescue Exception => e
|
|
31
|
+
exceptions ||= []
|
|
32
|
+
exceptions << e
|
|
33
33
|
end
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
34
|
+
|
|
35
|
+
if exceptions
|
|
36
|
+
exceptions = exceptions.flat_map do |exception|
|
|
37
|
+
exception.is_a?(InstrumentationSubscriberError) ? exception.exceptions : [exception]
|
|
38
|
+
end
|
|
39
|
+
if exceptions.size == 1
|
|
40
|
+
raise exceptions.first
|
|
41
|
+
else
|
|
42
|
+
raise InstrumentationSubscriberError.new(exceptions), cause: exceptions.first
|
|
43
|
+
end
|
|
38
44
|
end
|
|
39
45
|
end
|
|
40
46
|
|
|
@@ -53,7 +59,6 @@ module ActiveSupport
|
|
|
53
59
|
@other_subscribers = []
|
|
54
60
|
@all_listeners_for = Concurrent::Map.new
|
|
55
61
|
@groups_for = Concurrent::Map.new
|
|
56
|
-
@silenceable_groups_for = Concurrent::Map.new
|
|
57
62
|
end
|
|
58
63
|
|
|
59
64
|
def inspect # :nodoc:
|
|
@@ -102,11 +107,9 @@ module ActiveSupport
|
|
|
102
107
|
if key
|
|
103
108
|
@all_listeners_for.delete(key)
|
|
104
109
|
@groups_for.delete(key)
|
|
105
|
-
@silenceable_groups_for.delete(key)
|
|
106
110
|
else
|
|
107
111
|
@all_listeners_for.clear
|
|
108
112
|
@groups_for.clear
|
|
109
|
-
@silenceable_groups_for.clear
|
|
110
113
|
end
|
|
111
114
|
end
|
|
112
115
|
|
|
@@ -184,25 +187,25 @@ module ActiveSupport
|
|
|
184
187
|
end
|
|
185
188
|
end
|
|
186
189
|
|
|
187
|
-
def
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
end
|
|
190
|
+
def group_listeners(listeners) # :nodoc:
|
|
191
|
+
listeners.group_by(&:group_class).transform_values do |s|
|
|
192
|
+
s.map(&:delegate).freeze
|
|
193
|
+
end.freeze
|
|
194
|
+
end
|
|
193
195
|
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
196
|
+
def groups_for(name) # :nodoc:
|
|
197
|
+
silenceable_groups, groups = @groups_for.compute_if_absent(name) do
|
|
198
|
+
listeners = all_listeners_for(name)
|
|
199
|
+
listeners.partition(&:silenceable).map { |l| group_listeners(l) }
|
|
198
200
|
end
|
|
199
201
|
|
|
200
202
|
unless silenceable_groups.empty?
|
|
201
|
-
groups = groups.dup
|
|
202
203
|
silenceable_groups.each do |group_class, subscriptions|
|
|
203
204
|
active_subscriptions = subscriptions.reject { |s| s.silenced?(name) }
|
|
204
205
|
unless active_subscriptions.empty?
|
|
205
|
-
groups
|
|
206
|
+
groups = groups.dup if groups.frozen?
|
|
207
|
+
base_groups = groups[group_class]
|
|
208
|
+
groups[group_class] = base_groups ? base_groups + active_subscriptions : active_subscriptions
|
|
206
209
|
end
|
|
207
210
|
end
|
|
208
211
|
end
|
|
@@ -227,13 +230,11 @@ module ActiveSupport
|
|
|
227
230
|
class Handle
|
|
228
231
|
include FanoutIteration
|
|
229
232
|
|
|
230
|
-
def initialize(notifier, name, id, payload) # :nodoc:
|
|
233
|
+
def initialize(notifier, name, id, groups, payload) # :nodoc:
|
|
231
234
|
@name = name
|
|
232
235
|
@id = id
|
|
233
236
|
@payload = payload
|
|
234
|
-
@groups =
|
|
235
|
-
group_klass.new(grouped_listeners, name, id, payload)
|
|
236
|
-
end
|
|
237
|
+
@groups = groups
|
|
237
238
|
@state = :initialized
|
|
238
239
|
end
|
|
239
240
|
|
|
@@ -267,10 +268,31 @@ module ActiveSupport
|
|
|
267
268
|
end
|
|
268
269
|
end
|
|
269
270
|
|
|
271
|
+
module NullHandle # :nodoc:
|
|
272
|
+
extend self
|
|
273
|
+
|
|
274
|
+
def start
|
|
275
|
+
end
|
|
276
|
+
|
|
277
|
+
def finish
|
|
278
|
+
end
|
|
279
|
+
|
|
280
|
+
def finish_with_values(_name, _id, _payload)
|
|
281
|
+
end
|
|
282
|
+
end
|
|
283
|
+
|
|
270
284
|
include FanoutIteration
|
|
271
285
|
|
|
272
286
|
def build_handle(name, id, payload)
|
|
273
|
-
|
|
287
|
+
groups = groups_for(name).map do |group_klass, grouped_listeners|
|
|
288
|
+
group_klass.new(grouped_listeners, name, id, payload)
|
|
289
|
+
end
|
|
290
|
+
|
|
291
|
+
if groups.empty?
|
|
292
|
+
NullHandle
|
|
293
|
+
else
|
|
294
|
+
Handle.new(self, name, id, groups, payload)
|
|
295
|
+
end
|
|
274
296
|
end
|
|
275
297
|
|
|
276
298
|
def start(name, id, payload)
|
|
@@ -286,8 +308,8 @@ module ActiveSupport
|
|
|
286
308
|
handle.finish_with_values(name, id, payload)
|
|
287
309
|
end
|
|
288
310
|
|
|
289
|
-
def publish(name,
|
|
290
|
-
iterate_guarding_exceptions(listeners_for(name)) { |s| s.publish(name,
|
|
311
|
+
def publish(name, ...)
|
|
312
|
+
iterate_guarding_exceptions(listeners_for(name)) { |s| s.publish(name, ...) }
|
|
291
313
|
end
|
|
292
314
|
|
|
293
315
|
def publish_event(event)
|
|
@@ -387,9 +409,9 @@ module ActiveSupport
|
|
|
387
409
|
EventedGroup
|
|
388
410
|
end
|
|
389
411
|
|
|
390
|
-
def publish(
|
|
412
|
+
def publish(...)
|
|
391
413
|
if @can_publish
|
|
392
|
-
@delegate.publish
|
|
414
|
+
@delegate.publish(...)
|
|
393
415
|
end
|
|
394
416
|
end
|
|
395
417
|
|
|
@@ -419,8 +441,8 @@ module ActiveSupport
|
|
|
419
441
|
TimedGroup
|
|
420
442
|
end
|
|
421
443
|
|
|
422
|
-
def publish(
|
|
423
|
-
@delegate.call
|
|
444
|
+
def publish(...)
|
|
445
|
+
@delegate.call(...)
|
|
424
446
|
end
|
|
425
447
|
end
|
|
426
448
|
|
|
@@ -164,7 +164,7 @@ module ActiveSupport
|
|
|
164
164
|
@cpu_time_finish - @cpu_time_start
|
|
165
165
|
end
|
|
166
166
|
|
|
167
|
-
# Returns the idle time
|
|
167
|
+
# Returns the idle time (in milliseconds) passed between the call to
|
|
168
168
|
# #start! and the call to #finish!.
|
|
169
169
|
def idle_time
|
|
170
170
|
diff = duration - cpu_time
|
|
@@ -15,7 +15,7 @@ module ActiveSupport
|
|
|
15
15
|
|
|
16
16
|
initializer "active_support.isolation_level" do |app|
|
|
17
17
|
config.after_initialize do
|
|
18
|
-
if level = app.config.active_support.
|
|
18
|
+
if level = app.config.active_support.isolation_level
|
|
19
19
|
ActiveSupport::IsolatedExecutionState.isolation_level = level
|
|
20
20
|
end
|
|
21
21
|
end
|
|
@@ -38,19 +38,35 @@ module ActiveSupport
|
|
|
38
38
|
end
|
|
39
39
|
end
|
|
40
40
|
|
|
41
|
-
initializer "active_support.
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
41
|
+
initializer "active_support.set_event_reporter_context_store" do |app|
|
|
42
|
+
config.after_initialize do
|
|
43
|
+
if klass = app.config.active_support.event_reporter_context_store
|
|
44
|
+
ActiveSupport::EventReporter.context_store = klass
|
|
45
|
+
end
|
|
46
|
+
end
|
|
45
47
|
end
|
|
46
48
|
|
|
47
|
-
initializer "active_support.
|
|
48
|
-
app.reloader.before_class_unload
|
|
49
|
-
|
|
50
|
-
|
|
49
|
+
initializer "active_support.reset_execution_context" do |app|
|
|
50
|
+
app.reloader.before_class_unload do
|
|
51
|
+
ActiveSupport::CurrentAttributes.clear_all
|
|
52
|
+
ActiveSupport::ExecutionContext.clear
|
|
53
|
+
ActiveSupport.event_reporter.clear_context
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
app.executor.to_run do
|
|
57
|
+
ActiveSupport::ExecutionContext.push
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
app.executor.to_complete do
|
|
61
|
+
ActiveSupport::CurrentAttributes.clear_all
|
|
62
|
+
ActiveSupport::ExecutionContext.pop
|
|
63
|
+
ActiveSupport.event_reporter.clear_context
|
|
64
|
+
end
|
|
51
65
|
|
|
52
66
|
ActiveSupport.on_load(:active_support_test_case) do
|
|
53
67
|
if app.config.active_support.executor_around_test_case
|
|
68
|
+
ActiveSupport::ExecutionContext.nestable = true
|
|
69
|
+
|
|
54
70
|
require "active_support/executor/test_helper"
|
|
55
71
|
include ActiveSupport::Executor::TestHelper
|
|
56
72
|
else
|
|
@@ -63,6 +79,13 @@ module ActiveSupport
|
|
|
63
79
|
end
|
|
64
80
|
end
|
|
65
81
|
|
|
82
|
+
initializer "active_support.set_filter_parameters" do |app|
|
|
83
|
+
config.after_initialize do
|
|
84
|
+
ActiveSupport.filter_parameters += Rails.application.config.filter_parameters
|
|
85
|
+
ActiveSupport.event_reporter.reload_payload_filter
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
|
|
66
89
|
initializer "active_support.deprecation_behavior" do |app|
|
|
67
90
|
if app.config.active_support.report_deprecations == false
|
|
68
91
|
app.deprecators.silenced = true
|
|
@@ -96,10 +119,6 @@ module ActiveSupport
|
|
|
96
119
|
config.eager_load_namespaces << TZInfo
|
|
97
120
|
end
|
|
98
121
|
|
|
99
|
-
initializer "active_support.to_time_preserves_timezone" do |app|
|
|
100
|
-
ActiveSupport.to_time_preserves_timezone = app.config.active_support.to_time_preserves_timezone
|
|
101
|
-
end
|
|
102
|
-
|
|
103
122
|
# Sets the default week start
|
|
104
123
|
# If assigned value is not a valid day symbol (e.g. :sunday, :monday, ...), an exception will be raised.
|
|
105
124
|
initializer "active_support.initialize_beginning_of_week" do |app|
|