activesupport 7.0.8.7 → 7.1.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 +722 -314
- data/MIT-LICENSE +1 -1
- data/README.rdoc +4 -4
- data/lib/active_support/actionable_error.rb +3 -1
- data/lib/active_support/array_inquirer.rb +2 -0
- data/lib/active_support/backtrace_cleaner.rb +25 -5
- data/lib/active_support/benchmarkable.rb +1 -0
- data/lib/active_support/builder.rb +1 -1
- data/lib/active_support/cache/coder.rb +153 -0
- data/lib/active_support/cache/entry.rb +128 -0
- data/lib/active_support/cache/file_store.rb +36 -9
- data/lib/active_support/cache/mem_cache_store.rb +84 -68
- data/lib/active_support/cache/memory_store.rb +76 -24
- data/lib/active_support/cache/null_store.rb +6 -0
- data/lib/active_support/cache/redis_cache_store.rb +126 -131
- data/lib/active_support/cache/serializer_with_fallback.rb +175 -0
- data/lib/active_support/cache/strategy/local_cache.rb +20 -8
- data/lib/active_support/cache.rb +304 -246
- data/lib/active_support/callbacks.rb +38 -18
- data/lib/active_support/concern.rb +4 -2
- data/lib/active_support/concurrency/load_interlock_aware_monitor.rb +42 -3
- data/lib/active_support/concurrency/null_lock.rb +13 -0
- data/lib/active_support/configurable.rb +10 -0
- data/lib/active_support/core_ext/array/conversions.rb +2 -1
- data/lib/active_support/core_ext/array.rb +0 -1
- data/lib/active_support/core_ext/class/subclasses.rb +13 -10
- data/lib/active_support/core_ext/date/conversions.rb +1 -0
- data/lib/active_support/core_ext/date.rb +0 -1
- data/lib/active_support/core_ext/date_and_time/calculations.rb +10 -0
- data/lib/active_support/core_ext/date_time/conversions.rb +6 -2
- data/lib/active_support/core_ext/date_time.rb +0 -1
- data/lib/active_support/core_ext/digest/uuid.rb +1 -10
- data/lib/active_support/core_ext/enumerable.rb +3 -75
- data/lib/active_support/core_ext/erb/util.rb +196 -0
- data/lib/active_support/core_ext/hash/conversions.rb +1 -1
- data/lib/active_support/core_ext/module/attribute_accessors.rb +6 -0
- data/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb +34 -16
- data/lib/active_support/core_ext/module/delegation.rb +40 -11
- data/lib/active_support/core_ext/module/deprecation.rb +15 -12
- data/lib/active_support/core_ext/module/introspection.rb +0 -1
- data/lib/active_support/core_ext/numeric/bytes.rb +9 -0
- data/lib/active_support/core_ext/numeric/conversions.rb +2 -0
- data/lib/active_support/core_ext/numeric.rb +0 -1
- data/lib/active_support/core_ext/object/deep_dup.rb +16 -0
- data/lib/active_support/core_ext/object/duplicable.rb +15 -24
- data/lib/active_support/core_ext/object/inclusion.rb +13 -5
- data/lib/active_support/core_ext/object/instance_variables.rb +22 -12
- data/lib/active_support/core_ext/object/json.rb +10 -2
- data/lib/active_support/core_ext/object/with.rb +44 -0
- data/lib/active_support/core_ext/object/with_options.rb +3 -3
- data/lib/active_support/core_ext/object.rb +1 -0
- data/lib/active_support/core_ext/pathname/blank.rb +16 -0
- data/lib/active_support/core_ext/pathname/existence.rb +2 -0
- data/lib/active_support/core_ext/pathname.rb +1 -0
- data/lib/active_support/core_ext/range/conversions.rb +28 -7
- data/lib/active_support/core_ext/range/{overlaps.rb → overlap.rb} +5 -3
- data/lib/active_support/core_ext/range.rb +1 -2
- data/lib/active_support/core_ext/securerandom.rb +24 -12
- data/lib/active_support/core_ext/string/filters.rb +20 -14
- data/lib/active_support/core_ext/string/inflections.rb +16 -5
- data/lib/active_support/core_ext/string/output_safety.rb +38 -174
- data/lib/active_support/core_ext/thread/backtrace/location.rb +12 -0
- data/lib/active_support/core_ext/time/calculations.rb +18 -2
- data/lib/active_support/core_ext/time/conversions.rb +2 -2
- data/lib/active_support/core_ext/time/zones.rb +4 -4
- data/lib/active_support/core_ext/time.rb +0 -1
- data/lib/active_support/current_attributes.rb +15 -6
- data/lib/active_support/dependencies/autoload.rb +17 -12
- data/lib/active_support/deprecation/behaviors.rb +53 -32
- data/lib/active_support/deprecation/constant_accessor.rb +5 -4
- data/lib/active_support/deprecation/deprecators.rb +104 -0
- data/lib/active_support/deprecation/disallowed.rb +3 -5
- data/lib/active_support/deprecation/instance_delegator.rb +31 -4
- data/lib/active_support/deprecation/method_wrappers.rb +6 -23
- data/lib/active_support/deprecation/proxy_wrappers.rb +37 -22
- data/lib/active_support/deprecation/reporting.rb +35 -21
- data/lib/active_support/deprecation.rb +32 -5
- data/lib/active_support/deprecator.rb +7 -0
- data/lib/active_support/descendants_tracker.rb +104 -132
- data/lib/active_support/duration/iso8601_serializer.rb +0 -2
- data/lib/active_support/duration.rb +2 -1
- data/lib/active_support/encrypted_configuration.rb +30 -9
- data/lib/active_support/encrypted_file.rb +8 -3
- data/lib/active_support/environment_inquirer.rb +22 -2
- data/lib/active_support/error_reporter/test_helper.rb +15 -0
- data/lib/active_support/error_reporter.rb +121 -35
- data/lib/active_support/execution_wrapper.rb +4 -4
- data/lib/active_support/file_update_checker.rb +4 -2
- data/lib/active_support/fork_tracker.rb +10 -2
- data/lib/active_support/gem_version.rb +4 -4
- data/lib/active_support/gzip.rb +2 -0
- data/lib/active_support/hash_with_indifferent_access.rb +35 -17
- data/lib/active_support/i18n.rb +1 -1
- data/lib/active_support/i18n_railtie.rb +20 -13
- data/lib/active_support/inflector/inflections.rb +2 -0
- data/lib/active_support/inflector/methods.rb +22 -10
- data/lib/active_support/inflector/transliterate.rb +3 -1
- data/lib/active_support/isolated_execution_state.rb +26 -22
- data/lib/active_support/json/decoding.rb +2 -1
- data/lib/active_support/json/encoding.rb +25 -43
- data/lib/active_support/key_generator.rb +9 -1
- data/lib/active_support/lazy_load_hooks.rb +6 -4
- data/lib/active_support/locale/en.yml +2 -0
- data/lib/active_support/log_subscriber.rb +78 -33
- data/lib/active_support/logger.rb +1 -1
- data/lib/active_support/logger_thread_safe_level.rb +9 -21
- data/lib/active_support/message_encryptor.rb +197 -53
- data/lib/active_support/message_encryptors.rb +140 -0
- data/lib/active_support/message_pack/cache_serializer.rb +23 -0
- data/lib/active_support/message_pack/extensions.rb +292 -0
- data/lib/active_support/message_pack/serializer.rb +63 -0
- data/lib/active_support/message_pack.rb +50 -0
- data/lib/active_support/message_verifier.rb +212 -93
- data/lib/active_support/message_verifiers.rb +134 -0
- data/lib/active_support/messages/codec.rb +65 -0
- data/lib/active_support/messages/metadata.rb +111 -45
- data/lib/active_support/messages/rotation_coordinator.rb +93 -0
- data/lib/active_support/messages/rotator.rb +34 -32
- data/lib/active_support/messages/serializer_with_fallback.rb +158 -0
- data/lib/active_support/multibyte/chars.rb +2 -0
- data/lib/active_support/multibyte/unicode.rb +9 -37
- data/lib/active_support/notifications/fanout.rb +239 -81
- data/lib/active_support/notifications/instrumenter.rb +71 -14
- data/lib/active_support/notifications.rb +1 -1
- data/lib/active_support/number_helper/number_converter.rb +2 -2
- data/lib/active_support/number_helper/number_to_human_size_converter.rb +1 -1
- data/lib/active_support/number_helper/number_to_phone_converter.rb +1 -0
- data/lib/active_support/ordered_hash.rb +3 -3
- data/lib/active_support/ordered_options.rb +14 -0
- data/lib/active_support/parameter_filter.rb +84 -69
- data/lib/active_support/proxy_object.rb +2 -0
- data/lib/active_support/railtie.rb +33 -21
- data/lib/active_support/reloader.rb +12 -4
- data/lib/active_support/rescuable.rb +2 -0
- data/lib/active_support/secure_compare_rotator.rb +16 -9
- data/lib/active_support/string_inquirer.rb +3 -1
- data/lib/active_support/subscriber.rb +9 -27
- data/lib/active_support/syntax_error_proxy.rb +49 -0
- data/lib/active_support/tagged_logging.rb +60 -24
- data/lib/active_support/test_case.rb +153 -6
- data/lib/active_support/testing/assertions.rb +25 -9
- data/lib/active_support/testing/autorun.rb +0 -2
- data/lib/active_support/testing/constant_stubbing.rb +32 -0
- data/lib/active_support/testing/deprecation.rb +25 -25
- data/lib/active_support/testing/error_reporter_assertions.rb +108 -0
- data/lib/active_support/testing/isolation.rb +1 -1
- data/lib/active_support/testing/method_call_assertions.rb +21 -8
- data/lib/active_support/testing/parallelize_executor.rb +8 -3
- data/lib/active_support/testing/stream.rb +1 -1
- data/lib/active_support/testing/strict_warnings.rb +38 -0
- data/lib/active_support/testing/time_helpers.rb +32 -14
- data/lib/active_support/time_with_zone.rb +4 -14
- data/lib/active_support/values/time_zone.rb +9 -7
- data/lib/active_support/version.rb +1 -1
- data/lib/active_support/xml_mini/jdom.rb +3 -10
- data/lib/active_support/xml_mini/nokogiri.rb +1 -1
- data/lib/active_support/xml_mini/nokogirisax.rb +1 -1
- data/lib/active_support/xml_mini/rexml.rb +1 -1
- data/lib/active_support/xml_mini.rb +2 -2
- data/lib/active_support.rb +13 -3
- metadata +106 -21
- data/lib/active_support/core_ext/array/deprecated_conversions.rb +0 -25
- data/lib/active_support/core_ext/date/deprecated_conversions.rb +0 -40
- data/lib/active_support/core_ext/date_time/deprecated_conversions.rb +0 -36
- data/lib/active_support/core_ext/numeric/deprecated_conversions.rb +0 -60
- data/lib/active_support/core_ext/range/deprecated_conversions.rb +0 -36
- data/lib/active_support/core_ext/range/include_time_with_zone.rb +0 -5
- data/lib/active_support/core_ext/time/deprecated_conversions.rb +0 -73
- data/lib/active_support/core_ext/uri.rb +0 -5
- data/lib/active_support/per_thread_registry.rb +0 -65
@@ -17,6 +17,29 @@ module ActiveSupport
|
|
17
17
|
end
|
18
18
|
end
|
19
19
|
|
20
|
+
module FanoutIteration # :nodoc:
|
21
|
+
def iterate_guarding_exceptions(listeners)
|
22
|
+
exceptions = nil
|
23
|
+
|
24
|
+
listeners.each do |s|
|
25
|
+
yield s
|
26
|
+
rescue Exception => e
|
27
|
+
exceptions ||= []
|
28
|
+
exceptions << e
|
29
|
+
end
|
30
|
+
|
31
|
+
if exceptions
|
32
|
+
if exceptions.size == 1
|
33
|
+
raise exceptions.first
|
34
|
+
else
|
35
|
+
raise InstrumentationSubscriberError.new(exceptions), cause: exceptions.first
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
listeners
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
20
43
|
# This is a default queue implementation that ships with Notifications.
|
21
44
|
# It just pushes events to all registered log subscribers.
|
22
45
|
#
|
@@ -25,22 +48,29 @@ module ActiveSupport
|
|
25
48
|
include Mutex_m
|
26
49
|
|
27
50
|
def initialize
|
28
|
-
@string_subscribers =
|
51
|
+
@string_subscribers = Concurrent::Map.new { |h, k| h.compute_if_absent(k) { [] } }
|
29
52
|
@other_subscribers = []
|
30
|
-
@
|
53
|
+
@all_listeners_for = Concurrent::Map.new
|
54
|
+
@groups_for = Concurrent::Map.new
|
55
|
+
@silenceable_groups_for = Concurrent::Map.new
|
31
56
|
super
|
32
57
|
end
|
33
58
|
|
59
|
+
def inspect # :nodoc:
|
60
|
+
total_patterns = @string_subscribers.size + @other_subscribers.size
|
61
|
+
"#<#{self.class} (#{total_patterns} patterns)>"
|
62
|
+
end
|
63
|
+
|
34
64
|
def subscribe(pattern = nil, callable = nil, monotonic: false, &block)
|
35
65
|
subscriber = Subscribers.new(pattern, callable || block, monotonic)
|
36
66
|
synchronize do
|
37
67
|
case pattern
|
38
68
|
when String
|
39
69
|
@string_subscribers[pattern] << subscriber
|
40
|
-
|
70
|
+
clear_cache(pattern)
|
41
71
|
when NilClass, Regexp
|
42
72
|
@other_subscribers << subscriber
|
43
|
-
|
73
|
+
clear_cache
|
44
74
|
else
|
45
75
|
raise ArgumentError, "pattern must be specified as a String, Regexp or empty"
|
46
76
|
end
|
@@ -53,69 +83,230 @@ module ActiveSupport
|
|
53
83
|
case subscriber_or_name
|
54
84
|
when String
|
55
85
|
@string_subscribers[subscriber_or_name].clear
|
56
|
-
|
86
|
+
clear_cache(subscriber_or_name)
|
57
87
|
@other_subscribers.each { |sub| sub.unsubscribe!(subscriber_or_name) }
|
58
88
|
else
|
59
89
|
pattern = subscriber_or_name.try(:pattern)
|
60
90
|
if String === pattern
|
61
91
|
@string_subscribers[pattern].delete(subscriber_or_name)
|
62
|
-
|
92
|
+
clear_cache(pattern)
|
63
93
|
else
|
64
94
|
@other_subscribers.delete(subscriber_or_name)
|
65
|
-
|
95
|
+
clear_cache
|
66
96
|
end
|
67
97
|
end
|
68
98
|
end
|
69
99
|
end
|
70
100
|
|
71
|
-
def
|
72
|
-
|
101
|
+
def clear_cache(key = nil) # :nodoc:
|
102
|
+
if key
|
103
|
+
@all_listeners_for.delete(key)
|
104
|
+
@groups_for.delete(key)
|
105
|
+
@silenceable_groups_for.delete(key)
|
106
|
+
else
|
107
|
+
@all_listeners_for.clear
|
108
|
+
@groups_for.clear
|
109
|
+
@silenceable_groups_for.clear
|
110
|
+
end
|
73
111
|
end
|
74
112
|
|
75
|
-
|
76
|
-
|
113
|
+
class BaseGroup # :nodoc:
|
114
|
+
include FanoutIteration
|
115
|
+
|
116
|
+
def initialize(listeners, name, id, payload)
|
117
|
+
@listeners = listeners
|
118
|
+
end
|
119
|
+
|
120
|
+
def each(&block)
|
121
|
+
iterate_guarding_exceptions(@listeners, &block)
|
122
|
+
end
|
77
123
|
end
|
78
124
|
|
79
|
-
|
80
|
-
|
125
|
+
class BaseTimeGroup < BaseGroup # :nodoc:
|
126
|
+
def start(name, id, payload)
|
127
|
+
@start_time = now
|
128
|
+
end
|
129
|
+
|
130
|
+
def finish(name, id, payload)
|
131
|
+
stop_time = now
|
132
|
+
each do |listener|
|
133
|
+
listener.call(name, @start_time, stop_time, id, payload)
|
134
|
+
end
|
135
|
+
end
|
81
136
|
end
|
82
137
|
|
83
|
-
|
84
|
-
|
138
|
+
class MonotonicTimedGroup < BaseTimeGroup # :nodoc:
|
139
|
+
private
|
140
|
+
def now
|
141
|
+
Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
142
|
+
end
|
85
143
|
end
|
86
144
|
|
87
|
-
|
88
|
-
|
145
|
+
class TimedGroup < BaseTimeGroup # :nodoc:
|
146
|
+
private
|
147
|
+
def now
|
148
|
+
Time.now
|
149
|
+
end
|
150
|
+
end
|
89
151
|
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
152
|
+
class EventedGroup < BaseGroup # :nodoc:
|
153
|
+
def start(name, id, payload)
|
154
|
+
each do |s|
|
155
|
+
s.start(name, id, payload)
|
156
|
+
end
|
95
157
|
end
|
96
158
|
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
else
|
101
|
-
raise InstrumentationSubscriberError.new(exceptions), cause: exceptions.first
|
159
|
+
def finish(name, id, payload)
|
160
|
+
each do |s|
|
161
|
+
s.finish(name, id, payload)
|
102
162
|
end
|
103
163
|
end
|
164
|
+
end
|
104
165
|
|
105
|
-
|
166
|
+
class EventObjectGroup < BaseGroup # :nodoc:
|
167
|
+
def start(name, id, payload)
|
168
|
+
@event = build_event(name, id, payload)
|
169
|
+
@event.start!
|
170
|
+
end
|
171
|
+
|
172
|
+
def finish(name, id, payload)
|
173
|
+
@event.payload = payload
|
174
|
+
@event.finish!
|
175
|
+
|
176
|
+
each do |s|
|
177
|
+
s.call(@event)
|
178
|
+
end
|
179
|
+
end
|
180
|
+
|
181
|
+
private
|
182
|
+
def build_event(name, id, payload)
|
183
|
+
ActiveSupport::Notifications::Event.new name, nil, nil, id, payload
|
184
|
+
end
|
106
185
|
end
|
107
186
|
|
108
|
-
def
|
187
|
+
def groups_for(name) # :nodoc:
|
188
|
+
groups = @groups_for.compute_if_absent(name) do
|
189
|
+
all_listeners_for(name).reject(&:silenceable).group_by(&:group_class).transform_values do |s|
|
190
|
+
s.map(&:delegate)
|
191
|
+
end
|
192
|
+
end
|
193
|
+
|
194
|
+
silenceable_groups = @silenceable_groups_for.compute_if_absent(name) do
|
195
|
+
all_listeners_for(name).select(&:silenceable).group_by(&:group_class).transform_values do |s|
|
196
|
+
s.map(&:delegate)
|
197
|
+
end
|
198
|
+
end
|
199
|
+
|
200
|
+
unless silenceable_groups.empty?
|
201
|
+
groups = groups.dup
|
202
|
+
silenceable_groups.each do |group_class, subscriptions|
|
203
|
+
active_subscriptions = subscriptions.reject { |s| s.silenced?(name) }
|
204
|
+
unless active_subscriptions.empty?
|
205
|
+
groups[group_class] = (groups[group_class] || []) + active_subscriptions
|
206
|
+
end
|
207
|
+
end
|
208
|
+
end
|
209
|
+
|
210
|
+
groups
|
211
|
+
end
|
212
|
+
|
213
|
+
# A +Handle+ is used to record the start and finish time of event.
|
214
|
+
#
|
215
|
+
# Both #start and #finish must each be called exactly once.
|
216
|
+
#
|
217
|
+
# Where possible, it's best to use the block form: ActiveSupport::Notifications.instrument.
|
218
|
+
# +Handle+ is a low-level API intended for cases where the block form can't be used.
|
219
|
+
#
|
220
|
+
# handle = ActiveSupport::Notifications.instrumenter.build_handle("my.event", {})
|
221
|
+
# begin
|
222
|
+
# handle.start
|
223
|
+
# # work to be instrumented
|
224
|
+
# ensure
|
225
|
+
# handle.finish
|
226
|
+
# end
|
227
|
+
class Handle
|
228
|
+
def initialize(notifier, name, id, payload) # :nodoc:
|
229
|
+
@name = name
|
230
|
+
@id = id
|
231
|
+
@payload = payload
|
232
|
+
@groups = notifier.groups_for(name).map do |group_klass, grouped_listeners|
|
233
|
+
group_klass.new(grouped_listeners, name, id, payload)
|
234
|
+
end
|
235
|
+
@state = :initialized
|
236
|
+
end
|
237
|
+
|
238
|
+
def start
|
239
|
+
ensure_state! :initialized
|
240
|
+
@state = :started
|
241
|
+
|
242
|
+
@groups.each do |group|
|
243
|
+
group.start(@name, @id, @payload)
|
244
|
+
end
|
245
|
+
end
|
246
|
+
|
247
|
+
def finish
|
248
|
+
finish_with_values(@name, @id, @payload)
|
249
|
+
end
|
250
|
+
|
251
|
+
def finish_with_values(name, id, payload) # :nodoc:
|
252
|
+
ensure_state! :started
|
253
|
+
@state = :finished
|
254
|
+
|
255
|
+
@groups.each do |group|
|
256
|
+
group.finish(name, id, payload)
|
257
|
+
end
|
258
|
+
end
|
259
|
+
|
260
|
+
private
|
261
|
+
def ensure_state!(expected)
|
262
|
+
if @state != expected
|
263
|
+
raise ArgumentError, "expected state to be #{expected.inspect} but was #{@state.inspect}"
|
264
|
+
end
|
265
|
+
end
|
266
|
+
end
|
267
|
+
|
268
|
+
include FanoutIteration
|
269
|
+
|
270
|
+
def build_handle(name, id, payload)
|
271
|
+
Handle.new(self, name, id, payload)
|
272
|
+
end
|
273
|
+
|
274
|
+
def start(name, id, payload)
|
275
|
+
handle_stack = (IsolatedExecutionState[:_fanout_handle_stack] ||= [])
|
276
|
+
handle = build_handle(name, id, payload)
|
277
|
+
handle_stack << handle
|
278
|
+
handle.start
|
279
|
+
end
|
280
|
+
|
281
|
+
def finish(name, id, payload, listeners = nil)
|
282
|
+
handle_stack = IsolatedExecutionState[:_fanout_handle_stack]
|
283
|
+
handle = handle_stack.pop
|
284
|
+
handle.finish_with_values(name, id, payload)
|
285
|
+
end
|
286
|
+
|
287
|
+
def publish(name, *args)
|
288
|
+
iterate_guarding_exceptions(listeners_for(name)) { |s| s.publish(name, *args) }
|
289
|
+
end
|
290
|
+
|
291
|
+
def publish_event(event)
|
292
|
+
iterate_guarding_exceptions(listeners_for(event.name)) { |s| s.publish_event(event) }
|
293
|
+
end
|
294
|
+
|
295
|
+
def all_listeners_for(name)
|
109
296
|
# this is correctly done double-checked locking (Concurrent::Map's lookups have volatile semantics)
|
110
|
-
@
|
297
|
+
@all_listeners_for[name] || synchronize do
|
111
298
|
# use synchronisation when accessing @subscribers
|
112
|
-
@
|
299
|
+
@all_listeners_for[name] ||=
|
113
300
|
@string_subscribers[name] + @other_subscribers.select { |s| s.subscribed_to?(name) }
|
114
301
|
end
|
115
302
|
end
|
116
303
|
|
304
|
+
def listeners_for(name)
|
305
|
+
all_listeners_for(name).reject { |s| s.silenced?(name) }
|
306
|
+
end
|
307
|
+
|
117
308
|
def listening?(name)
|
118
|
-
|
309
|
+
all_listeners_for(name).any? { |s| !s.silenced?(name) }
|
119
310
|
end
|
120
311
|
|
121
312
|
# This is a sync queue, so there is no waiting.
|
@@ -180,15 +371,20 @@ module ActiveSupport
|
|
180
371
|
end
|
181
372
|
|
182
373
|
class Evented # :nodoc:
|
183
|
-
attr_reader :pattern
|
374
|
+
attr_reader :pattern, :delegate, :silenceable
|
184
375
|
|
185
376
|
def initialize(pattern, delegate)
|
186
377
|
@pattern = Matcher.wrap(pattern)
|
187
378
|
@delegate = delegate
|
379
|
+
@silenceable = delegate.respond_to?(:silenced?)
|
188
380
|
@can_publish = delegate.respond_to?(:publish)
|
189
381
|
@can_publish_event = delegate.respond_to?(:publish_event)
|
190
382
|
end
|
191
383
|
|
384
|
+
def group_class
|
385
|
+
EventedGroup
|
386
|
+
end
|
387
|
+
|
192
388
|
def publish(name, *args)
|
193
389
|
if @can_publish
|
194
390
|
@delegate.publish name, *args
|
@@ -203,12 +399,8 @@ module ActiveSupport
|
|
203
399
|
end
|
204
400
|
end
|
205
401
|
|
206
|
-
def
|
207
|
-
@delegate.
|
208
|
-
end
|
209
|
-
|
210
|
-
def finish(name, id, payload)
|
211
|
-
@delegate.finish name, id, payload
|
402
|
+
def silenced?(name)
|
403
|
+
@silenceable && @delegate.silenced?(name)
|
212
404
|
end
|
213
405
|
|
214
406
|
def subscribed_to?(name)
|
@@ -221,63 +413,29 @@ module ActiveSupport
|
|
221
413
|
end
|
222
414
|
|
223
415
|
class Timed < Evented # :nodoc:
|
224
|
-
def
|
225
|
-
|
226
|
-
end
|
227
|
-
|
228
|
-
def start(name, id, payload)
|
229
|
-
timestack = IsolatedExecutionState[:_timestack] ||= []
|
230
|
-
timestack.push Time.now
|
231
|
-
end
|
232
|
-
|
233
|
-
def finish(name, id, payload)
|
234
|
-
timestack = IsolatedExecutionState[:_timestack]
|
235
|
-
started = timestack.pop
|
236
|
-
@delegate.call(name, started, Time.now, id, payload)
|
416
|
+
def group_class
|
417
|
+
TimedGroup
|
237
418
|
end
|
238
|
-
end
|
239
419
|
|
240
|
-
class MonotonicTimed < Evented # :nodoc:
|
241
420
|
def publish(name, *args)
|
242
421
|
@delegate.call name, *args
|
243
422
|
end
|
423
|
+
end
|
244
424
|
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
end
|
249
|
-
|
250
|
-
def finish(name, id, payload)
|
251
|
-
timestack = IsolatedExecutionState[:_timestack_monotonic]
|
252
|
-
started = timestack.pop
|
253
|
-
@delegate.call(name, started, Process.clock_gettime(Process::CLOCK_MONOTONIC), id, payload)
|
425
|
+
class MonotonicTimed < Timed # :nodoc:
|
426
|
+
def group_class
|
427
|
+
MonotonicTimedGroup
|
254
428
|
end
|
255
429
|
end
|
256
430
|
|
257
431
|
class EventObject < Evented
|
258
|
-
def
|
259
|
-
|
260
|
-
event = build_event name, id, payload
|
261
|
-
event.start!
|
262
|
-
stack.push event
|
263
|
-
end
|
264
|
-
|
265
|
-
def finish(name, id, payload)
|
266
|
-
stack = IsolatedExecutionState[:_event_stack]
|
267
|
-
event = stack.pop
|
268
|
-
event.payload = payload
|
269
|
-
event.finish!
|
270
|
-
@delegate.call event
|
432
|
+
def group_class
|
433
|
+
EventObjectGroup
|
271
434
|
end
|
272
435
|
|
273
436
|
def publish_event(event)
|
274
437
|
@delegate.call event
|
275
438
|
end
|
276
|
-
|
277
|
-
private
|
278
|
-
def build_event(name, id, payload)
|
279
|
-
ActiveSupport::Notifications::Event.new name, nil, nil, id, payload
|
280
|
-
end
|
281
439
|
end
|
282
440
|
end
|
283
441
|
end
|
@@ -1,5 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require "active_support/core_ext/module/delegation"
|
3
4
|
require "securerandom"
|
4
5
|
|
5
6
|
module ActiveSupport
|
@@ -9,17 +10,50 @@ module ActiveSupport
|
|
9
10
|
attr_reader :id
|
10
11
|
|
11
12
|
def initialize(notifier)
|
13
|
+
unless notifier.respond_to?(:build_handle)
|
14
|
+
notifier = LegacyHandle::Wrapper.new(notifier)
|
15
|
+
end
|
16
|
+
|
12
17
|
@id = unique_id
|
13
18
|
@notifier = notifier
|
14
19
|
end
|
15
20
|
|
21
|
+
class LegacyHandle # :nodoc:
|
22
|
+
class Wrapper # :nodoc:
|
23
|
+
def initialize(notifier)
|
24
|
+
@notifier = notifier
|
25
|
+
end
|
26
|
+
|
27
|
+
def build_handle(name, id, payload)
|
28
|
+
LegacyHandle.new(@notifier, name, id, payload)
|
29
|
+
end
|
30
|
+
|
31
|
+
delegate :start, :finish, to: :@notifier
|
32
|
+
end
|
33
|
+
|
34
|
+
def initialize(notifier, name, id, payload)
|
35
|
+
@notifier = notifier
|
36
|
+
@name = name
|
37
|
+
@id = id
|
38
|
+
@payload = payload
|
39
|
+
end
|
40
|
+
|
41
|
+
def start
|
42
|
+
@listener_state = @notifier.start @name, @id, @payload
|
43
|
+
end
|
44
|
+
|
45
|
+
def finish
|
46
|
+
@notifier.finish(@name, @id, @payload, @listener_state)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
16
50
|
# Given a block, instrument it by measuring the time taken to execute
|
17
51
|
# and publish it. Without a block, simply send a message via the
|
18
52
|
# notifier. Notice that events get sent even if an error occurs in the
|
19
53
|
# passed-in block.
|
20
54
|
def instrument(name, payload = {})
|
21
|
-
|
22
|
-
|
55
|
+
handle = build_handle(name, payload)
|
56
|
+
handle.start
|
23
57
|
begin
|
24
58
|
yield payload if block_given?
|
25
59
|
rescue Exception => e
|
@@ -27,10 +61,24 @@ module ActiveSupport
|
|
27
61
|
payload[:exception_object] = e
|
28
62
|
raise e
|
29
63
|
ensure
|
30
|
-
|
64
|
+
handle.finish
|
31
65
|
end
|
32
66
|
end
|
33
67
|
|
68
|
+
# Returns a "handle" for an event with the given +name+ and +payload+
|
69
|
+
#
|
70
|
+
# +#start+ and +#finish+ must each be called exactly once on the returned object.
|
71
|
+
#
|
72
|
+
# Where possible, it's best to use +#instrument+, which will record the
|
73
|
+
# start and finish of the event and correctly handle any exceptions.
|
74
|
+
# +build_handle+ is a low-level API intended for cases where using
|
75
|
+
# +#instrument+ isn't possible.
|
76
|
+
#
|
77
|
+
# See ActiveSupport::Notifications::Fanout::Handle
|
78
|
+
def build_handle(name, payload)
|
79
|
+
@notifier.build_handle(name, @id, payload)
|
80
|
+
end
|
81
|
+
|
34
82
|
def new_event(name, payload = {}) # :nodoc:
|
35
83
|
Event.new(name, nil, nil, @id, payload)
|
36
84
|
end
|
@@ -56,7 +104,7 @@ module ActiveSupport
|
|
56
104
|
end
|
57
105
|
|
58
106
|
class Event
|
59
|
-
attr_reader :name, :time, :end, :transaction_id
|
107
|
+
attr_reader :name, :time, :end, :transaction_id
|
60
108
|
attr_accessor :payload
|
61
109
|
|
62
110
|
def initialize(name, start, ending, transaction_id, payload)
|
@@ -65,7 +113,6 @@ module ActiveSupport
|
|
65
113
|
@time = start ? start.to_f * 1_000.0 : start
|
66
114
|
@transaction_id = transaction_id
|
67
115
|
@end = ending ? ending.to_f * 1_000.0 : ending
|
68
|
-
@children = []
|
69
116
|
@cpu_time_start = 0.0
|
70
117
|
@cpu_time_finish = 0.0
|
71
118
|
@allocation_count_start = 0
|
@@ -108,7 +155,8 @@ module ActiveSupport
|
|
108
155
|
# Returns the idle time time (in milliseconds) passed since the call to
|
109
156
|
# +start!+ and the call to +finish!+
|
110
157
|
def idle_time
|
111
|
-
duration - cpu_time
|
158
|
+
diff = duration - cpu_time
|
159
|
+
diff > 0.0 ? diff : 0.0
|
112
160
|
end
|
113
161
|
|
114
162
|
# Returns the number of allocations made since the call to +start!+ and
|
@@ -117,6 +165,23 @@ module ActiveSupport
|
|
117
165
|
@allocation_count_finish - @allocation_count_start
|
118
166
|
end
|
119
167
|
|
168
|
+
def children # :nodoc:
|
169
|
+
ActiveSupport.deprecator.warn <<~EOM
|
170
|
+
ActiveSupport::Notifications::Event#children is deprecated and will
|
171
|
+
be removed in Rails 7.2.
|
172
|
+
EOM
|
173
|
+
[]
|
174
|
+
end
|
175
|
+
|
176
|
+
def parent_of?(event) # :nodoc:
|
177
|
+
ActiveSupport.deprecator.warn <<~EOM
|
178
|
+
ActiveSupport::Notifications::Event#parent_of? is deprecated and will
|
179
|
+
be removed in Rails 7.2.
|
180
|
+
EOM
|
181
|
+
start = (time - event.time) * 1000
|
182
|
+
start <= 0 && (start + duration >= event.duration)
|
183
|
+
end
|
184
|
+
|
120
185
|
# Returns the difference in milliseconds between when the execution of the
|
121
186
|
# event started and when it ended.
|
122
187
|
#
|
@@ -133,14 +198,6 @@ module ActiveSupport
|
|
133
198
|
self.end - time
|
134
199
|
end
|
135
200
|
|
136
|
-
def <<(event)
|
137
|
-
@children << event
|
138
|
-
end
|
139
|
-
|
140
|
-
def parent_of?(event)
|
141
|
-
@children.include? event
|
142
|
-
end
|
143
|
-
|
144
201
|
private
|
145
202
|
def now
|
146
203
|
Process.clock_gettime(Process::CLOCK_MONOTONIC, :float_millisecond)
|
@@ -6,7 +6,7 @@ require "active_support/notifications/fanout"
|
|
6
6
|
module ActiveSupport
|
7
7
|
# = \Notifications
|
8
8
|
#
|
9
|
-
#
|
9
|
+
# +ActiveSupport::Notifications+ provides an instrumentation API for
|
10
10
|
# Ruby.
|
11
11
|
#
|
12
12
|
# == Instrumenters
|
@@ -1,7 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require "active_support/core_ext/big_decimal/conversions"
|
4
|
-
require "active_support/core_ext/object/blank"
|
5
4
|
require "active_support/core_ext/hash/keys"
|
6
5
|
require "active_support/i18n"
|
7
6
|
require "active_support/core_ext/class/attribute"
|
@@ -122,7 +121,8 @@ module ActiveSupport
|
|
122
121
|
|
123
122
|
def initialize(number, options)
|
124
123
|
@number = number
|
125
|
-
@opts
|
124
|
+
@opts = options.symbolize_keys
|
125
|
+
@options = nil
|
126
126
|
end
|
127
127
|
|
128
128
|
def execute
|
@@ -5,7 +5,7 @@ require "active_support/number_helper/number_converter"
|
|
5
5
|
module ActiveSupport
|
6
6
|
module NumberHelper
|
7
7
|
class NumberToHumanSizeConverter < NumberConverter # :nodoc:
|
8
|
-
STORAGE_UNITS = [:byte, :kb, :mb, :gb, :tb, :pb, :eb]
|
8
|
+
STORAGE_UNITS = [:byte, :kb, :mb, :gb, :tb, :pb, :eb, :zb]
|
9
9
|
|
10
10
|
self.namespace = :human
|
11
11
|
self.validate_float = true
|
@@ -7,7 +7,7 @@ YAML.add_builtin_type("omap") do |type, val|
|
|
7
7
|
end
|
8
8
|
|
9
9
|
module ActiveSupport
|
10
|
-
# DEPRECATED:
|
10
|
+
# DEPRECATED: +ActiveSupport::OrderedHash+ implements a hash that preserves
|
11
11
|
# insertion order.
|
12
12
|
#
|
13
13
|
# oh = ActiveSupport::OrderedHash.new
|
@@ -17,9 +17,9 @@ module ActiveSupport
|
|
17
17
|
#
|
18
18
|
# Also, maps the +omap+ feature for YAML files
|
19
19
|
# (See https://yaml.org/type/omap.html) to support ordered items
|
20
|
-
# when loading from
|
20
|
+
# when loading from YAML.
|
21
21
|
#
|
22
|
-
#
|
22
|
+
# +ActiveSupport::OrderedHash+ is namespaced to prevent conflicts
|
23
23
|
# with other implementations.
|
24
24
|
class OrderedHash < ::Hash # :nodoc:
|
25
25
|
def to_yaml_type
|
@@ -3,6 +3,8 @@
|
|
3
3
|
require "active_support/core_ext/object/blank"
|
4
4
|
|
5
5
|
module ActiveSupport
|
6
|
+
# = Ordered Options
|
7
|
+
#
|
6
8
|
# +OrderedOptions+ inherits from +Hash+ and provides dynamic accessor methods.
|
7
9
|
#
|
8
10
|
# With a +Hash+, key-value pairs are typically managed like this:
|
@@ -40,6 +42,10 @@ module ActiveSupport
|
|
40
42
|
super(key.to_sym)
|
41
43
|
end
|
42
44
|
|
45
|
+
def dig(*keys)
|
46
|
+
super(*keys.flatten.map(&:to_sym))
|
47
|
+
end
|
48
|
+
|
43
49
|
def method_missing(name, *args)
|
44
50
|
name_string = +name.to_s
|
45
51
|
if name_string.chomp!("=")
|
@@ -68,6 +74,8 @@ module ActiveSupport
|
|
68
74
|
end
|
69
75
|
end
|
70
76
|
|
77
|
+
# = Inheritable Options
|
78
|
+
#
|
71
79
|
# +InheritableOptions+ provides a constructor to build an OrderedOptions
|
72
80
|
# hash inherited from another hash.
|
73
81
|
#
|
@@ -76,6 +84,12 @@ module ActiveSupport
|
|
76
84
|
# h = ActiveSupport::InheritableOptions.new({ girl: 'Mary', boy: 'John' })
|
77
85
|
# h.girl # => 'Mary'
|
78
86
|
# h.boy # => 'John'
|
87
|
+
#
|
88
|
+
# If the existing hash has string keys, call Hash#symbolize_keys on it.
|
89
|
+
#
|
90
|
+
# h = ActiveSupport::InheritableOptions.new({ 'girl' => 'Mary', 'boy' => 'John' }.symbolize_keys)
|
91
|
+
# h.girl # => 'Mary'
|
92
|
+
# h.boy # => 'John'
|
79
93
|
class InheritableOptions < OrderedOptions
|
80
94
|
def initialize(parent = nil)
|
81
95
|
if parent.kind_of?(OrderedOptions)
|