activesupport 6.1.0 → 7.1.5.1
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 +1075 -325
- data/MIT-LICENSE +1 -1
- data/README.rdoc +7 -7
- data/lib/active_support/actionable_error.rb +4 -2
- data/lib/active_support/array_inquirer.rb +2 -2
- data/lib/active_support/backtrace_cleaner.rb +32 -7
- data/lib/active_support/benchmarkable.rb +3 -2
- data/lib/active_support/broadcast_logger.rb +251 -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 +134 -0
- data/lib/active_support/cache/file_store.rb +53 -20
- data/lib/active_support/cache/mem_cache_store.rb +201 -62
- data/lib/active_support/cache/memory_store.rb +86 -24
- data/lib/active_support/cache/null_store.rb +16 -2
- data/lib/active_support/cache/redis_cache_store.rb +186 -193
- data/lib/active_support/cache/serializer_with_fallback.rb +175 -0
- data/lib/active_support/cache/strategy/local_cache.rb +63 -71
- data/lib/active_support/cache.rb +487 -249
- data/lib/active_support/callbacks.rb +227 -105
- data/lib/active_support/code_generator.rb +70 -0
- data/lib/active_support/concern.rb +9 -7
- data/lib/active_support/concurrency/load_interlock_aware_monitor.rb +44 -7
- data/lib/active_support/concurrency/null_lock.rb +13 -0
- data/lib/active_support/concurrency/share_lock.rb +2 -2
- data/lib/active_support/configurable.rb +18 -5
- data/lib/active_support/configuration_file.rb +7 -2
- data/lib/active_support/core_ext/array/access.rb +1 -5
- data/lib/active_support/core_ext/array/conversions.rb +15 -13
- data/lib/active_support/core_ext/array/grouping.rb +6 -6
- data/lib/active_support/core_ext/array/inquiry.rb +2 -2
- data/lib/active_support/core_ext/big_decimal/conversions.rb +1 -1
- data/lib/active_support/core_ext/class/subclasses.rb +37 -26
- data/lib/active_support/core_ext/date/blank.rb +1 -1
- data/lib/active_support/core_ext/date/calculations.rb +24 -9
- data/lib/active_support/core_ext/date/conversions.rb +16 -15
- data/lib/active_support/core_ext/date_and_time/calculations.rb +14 -4
- data/lib/active_support/core_ext/date_and_time/compatibility.rb +1 -1
- data/lib/active_support/core_ext/date_time/blank.rb +1 -1
- data/lib/active_support/core_ext/date_time/calculations.rb +4 -0
- data/lib/active_support/core_ext/date_time/conversions.rb +19 -15
- data/lib/active_support/core_ext/digest/uuid.rb +30 -13
- data/lib/active_support/core_ext/enumerable.rb +85 -83
- data/lib/active_support/core_ext/erb/util.rb +196 -0
- data/lib/active_support/core_ext/file/atomic.rb +3 -1
- data/lib/active_support/core_ext/hash/conversions.rb +1 -2
- data/lib/active_support/core_ext/hash/deep_merge.rb +22 -14
- data/lib/active_support/core_ext/hash/deep_transform_values.rb +3 -3
- data/lib/active_support/core_ext/hash/indifferent_access.rb +3 -3
- data/lib/active_support/core_ext/hash/keys.rb +4 -4
- data/lib/active_support/core_ext/integer/inflections.rb +12 -12
- data/lib/active_support/core_ext/kernel/reporting.rb +4 -4
- data/lib/active_support/core_ext/kernel/singleton_class.rb +1 -1
- data/lib/active_support/core_ext/module/attribute_accessors.rb +8 -0
- data/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb +49 -22
- data/lib/active_support/core_ext/module/concerning.rb +6 -6
- data/lib/active_support/core_ext/module/delegation.rb +81 -43
- 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/name_error.rb +2 -8
- data/lib/active_support/core_ext/numeric/bytes.rb +9 -0
- data/lib/active_support/core_ext/numeric/conversions.rb +82 -77
- data/lib/active_support/core_ext/object/acts_like.rb +29 -5
- data/lib/active_support/core_ext/object/blank.rb +2 -2
- data/lib/active_support/core_ext/object/deep_dup.rb +17 -1
- data/lib/active_support/core_ext/object/duplicable.rb +31 -11
- 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 +49 -27
- data/lib/active_support/core_ext/object/to_query.rb +2 -4
- data/lib/active_support/core_ext/object/try.rb +20 -20
- data/lib/active_support/core_ext/object/with.rb +44 -0
- data/lib/active_support/core_ext/object/with_options.rb +25 -6
- 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 +23 -0
- data/lib/active_support/core_ext/pathname.rb +4 -0
- data/lib/active_support/core_ext/range/compare_range.rb +0 -25
- data/lib/active_support/core_ext/range/conversions.rb +34 -13
- data/lib/active_support/core_ext/range/each.rb +1 -1
- data/lib/active_support/core_ext/range/overlap.rb +40 -0
- data/lib/active_support/core_ext/range.rb +1 -2
- data/lib/active_support/core_ext/securerandom.rb +25 -13
- data/lib/active_support/core_ext/string/conversions.rb +2 -2
- data/lib/active_support/core_ext/string/filters.rb +21 -15
- data/lib/active_support/core_ext/string/indent.rb +1 -1
- data/lib/active_support/core_ext/string/inflections.rb +17 -10
- data/lib/active_support/core_ext/string/inquiry.rb +1 -1
- data/lib/active_support/core_ext/string/output_safety.rb +85 -165
- data/lib/active_support/core_ext/symbol/starts_ends_with.rb +0 -8
- data/lib/active_support/core_ext/thread/backtrace/location.rb +12 -0
- data/lib/active_support/core_ext/time/calculations.rb +30 -8
- data/lib/active_support/core_ext/time/conversions.rb +15 -13
- data/lib/active_support/core_ext/time/zones.rb +12 -28
- data/lib/active_support/core_ext.rb +2 -1
- data/lib/active_support/current_attributes.rb +47 -20
- data/lib/active_support/deep_mergeable.rb +53 -0
- data/lib/active_support/dependencies/autoload.rb +17 -12
- data/lib/active_support/dependencies/interlock.rb +10 -18
- data/lib/active_support/dependencies/require_dependency.rb +28 -0
- data/lib/active_support/dependencies.rb +58 -788
- data/lib/active_support/deprecation/behaviors.rb +66 -40
- 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 +6 -8
- data/lib/active_support/deprecation/instance_delegator.rb +31 -4
- data/lib/active_support/deprecation/method_wrappers.rb +9 -26
- data/lib/active_support/deprecation/proxy_wrappers.rb +38 -23
- data/lib/active_support/deprecation/reporting.rb +43 -26
- data/lib/active_support/deprecation.rb +32 -5
- data/lib/active_support/deprecator.rb +7 -0
- data/lib/active_support/descendants_tracker.rb +150 -72
- data/lib/active_support/digest.rb +5 -3
- data/lib/active_support/duration/iso8601_parser.rb +3 -3
- data/lib/active_support/duration/iso8601_serializer.rb +9 -3
- data/lib/active_support/duration.rb +83 -52
- data/lib/active_support/encrypted_configuration.rb +72 -9
- data/lib/active_support/encrypted_file.rb +29 -13
- data/lib/active_support/environment_inquirer.rb +23 -3
- data/lib/active_support/error_reporter/test_helper.rb +15 -0
- data/lib/active_support/error_reporter.rb +203 -0
- data/lib/active_support/evented_file_update_checker.rb +20 -7
- data/lib/active_support/execution_context/test_helper.rb +13 -0
- data/lib/active_support/execution_context.rb +53 -0
- data/lib/active_support/execution_wrapper.rb +44 -22
- data/lib/active_support/executor/test_helper.rb +7 -0
- data/lib/active_support/file_update_checker.rb +4 -2
- data/lib/active_support/fork_tracker.rb +28 -11
- 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 +44 -19
- data/lib/active_support/html_safe_translation.rb +53 -0
- data/lib/active_support/i18n.rb +2 -1
- data/lib/active_support/i18n_railtie.rb +21 -14
- data/lib/active_support/inflector/inflections.rb +25 -7
- data/lib/active_support/inflector/methods.rb +50 -64
- data/lib/active_support/inflector/transliterate.rb +4 -2
- data/lib/active_support/isolated_execution_state.rb +76 -0
- data/lib/active_support/json/decoding.rb +2 -1
- data/lib/active_support/json/encoding.rb +27 -45
- data/lib/active_support/key_generator.rb +31 -6
- data/lib/active_support/lazy_load_hooks.rb +33 -7
- data/lib/active_support/locale/en.yml +4 -2
- data/lib/active_support/log_subscriber/test_helper.rb +2 -2
- data/lib/active_support/log_subscriber.rb +97 -35
- data/lib/active_support/logger.rb +9 -60
- data/lib/active_support/logger_thread_safe_level.rb +11 -34
- data/lib/active_support/message_encryptor.rb +206 -56
- data/lib/active_support/message_encryptors.rb +141 -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 +235 -84
- data/lib/active_support/message_verifiers.rb +135 -0
- data/lib/active_support/messages/codec.rb +65 -0
- data/lib/active_support/messages/metadata.rb +112 -46
- 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 +12 -11
- data/lib/active_support/multibyte/unicode.rb +9 -49
- data/lib/active_support/multibyte.rb +1 -1
- data/lib/active_support/notifications/fanout.rb +304 -114
- data/lib/active_support/notifications/instrumenter.rb +117 -35
- data/lib/active_support/notifications.rb +25 -25
- data/lib/active_support/number_helper/number_converter.rb +14 -7
- data/lib/active_support/number_helper/number_to_currency_converter.rb +11 -6
- data/lib/active_support/number_helper/number_to_delimited_converter.rb +1 -1
- data/lib/active_support/number_helper/number_to_human_size_converter.rb +4 -4
- data/lib/active_support/number_helper/number_to_phone_converter.rb +2 -1
- data/lib/active_support/number_helper/number_to_rounded_converter.rb +10 -6
- data/lib/active_support/number_helper/rounding_helper.rb +2 -6
- data/lib/active_support/number_helper.rb +379 -319
- data/lib/active_support/option_merger.rb +10 -18
- data/lib/active_support/ordered_hash.rb +4 -4
- data/lib/active_support/ordered_options.rb +15 -1
- data/lib/active_support/parameter_filter.rb +105 -81
- data/lib/active_support/proxy_object.rb +2 -0
- data/lib/active_support/railtie.rb +83 -21
- data/lib/active_support/reloader.rb +13 -5
- data/lib/active_support/rescuable.rb +18 -16
- data/lib/active_support/ruby_features.rb +7 -0
- data/lib/active_support/secure_compare_rotator.rb +18 -11
- data/lib/active_support/security_utils.rb +1 -1
- data/lib/active_support/string_inquirer.rb +3 -3
- data/lib/active_support/subscriber.rb +11 -40
- data/lib/active_support/syntax_error_proxy.rb +60 -0
- data/lib/active_support/tagged_logging.rb +65 -25
- data/lib/active_support/test_case.rb +166 -27
- data/lib/active_support/testing/assertions.rb +61 -15
- 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 +53 -2
- data/lib/active_support/testing/error_reporter_assertions.rb +107 -0
- data/lib/active_support/testing/isolation.rb +30 -29
- data/lib/active_support/testing/method_call_assertions.rb +24 -11
- data/lib/active_support/testing/parallelization/server.rb +4 -0
- data/lib/active_support/testing/parallelization/worker.rb +3 -0
- data/lib/active_support/testing/parallelization.rb +4 -0
- data/lib/active_support/testing/parallelize_executor.rb +81 -0
- data/lib/active_support/testing/setup_and_teardown.rb +2 -0
- data/lib/active_support/testing/stream.rb +4 -6
- data/lib/active_support/testing/strict_warnings.rb +39 -0
- data/lib/active_support/testing/tagged_logging.rb +1 -1
- data/lib/active_support/testing/time_helpers.rb +49 -16
- data/lib/active_support/time_with_zone.rb +39 -28
- data/lib/active_support/values/time_zone.rb +50 -18
- data/lib/active_support/version.rb +1 -1
- data/lib/active_support/xml_mini/jdom.rb +4 -11
- data/lib/active_support/xml_mini/libxml.rb +5 -5
- data/lib/active_support/xml_mini/libxmlsax.rb +1 -1
- data/lib/active_support/xml_mini/nokogiri.rb +5 -5
- data/lib/active_support/xml_mini/nokogirisax.rb +2 -2
- data/lib/active_support/xml_mini/rexml.rb +2 -2
- data/lib/active_support/xml_mini.rb +7 -6
- data/lib/active_support.rb +28 -1
- metadata +150 -18
- data/lib/active_support/core_ext/marshal.rb +0 -26
- data/lib/active_support/core_ext/range/include_time_with_zone.rb +0 -28
- data/lib/active_support/core_ext/range/overlaps.rb +0 -10
- data/lib/active_support/core_ext/uri.rb +0 -29
- data/lib/active_support/dependencies/zeitwerk_integration.rb +0 -117
- data/lib/active_support/per_thread_registry.rb +0 -60
@@ -7,6 +7,43 @@ require "active_support/core_ext/object/try"
|
|
7
7
|
|
8
8
|
module ActiveSupport
|
9
9
|
module Notifications
|
10
|
+
class InstrumentationSubscriberError < RuntimeError
|
11
|
+
attr_reader :exceptions
|
12
|
+
|
13
|
+
def initialize(exceptions)
|
14
|
+
@exceptions = exceptions
|
15
|
+
exception_class_names = exceptions.map { |e| e.class.name }
|
16
|
+
super "Exception(s) occurred within instrumentation subscribers: #{exception_class_names.join(', ')}"
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
module FanoutIteration # :nodoc:
|
21
|
+
private
|
22
|
+
def iterate_guarding_exceptions(collection)
|
23
|
+
exceptions = nil
|
24
|
+
|
25
|
+
collection.each do |s|
|
26
|
+
yield s
|
27
|
+
rescue Exception => e
|
28
|
+
exceptions ||= []
|
29
|
+
exceptions << e
|
30
|
+
end
|
31
|
+
|
32
|
+
if exceptions
|
33
|
+
exceptions = exceptions.flat_map do |exception|
|
34
|
+
exception.is_a?(InstrumentationSubscriberError) ? exception.exceptions : [exception]
|
35
|
+
end
|
36
|
+
if exceptions.size == 1
|
37
|
+
raise exceptions.first
|
38
|
+
else
|
39
|
+
raise InstrumentationSubscriberError.new(exceptions), cause: exceptions.first
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
collection
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
10
47
|
# This is a default queue implementation that ships with Notifications.
|
11
48
|
# It just pushes events to all registered log subscribers.
|
12
49
|
#
|
@@ -15,21 +52,31 @@ module ActiveSupport
|
|
15
52
|
include Mutex_m
|
16
53
|
|
17
54
|
def initialize
|
18
|
-
@string_subscribers =
|
55
|
+
@string_subscribers = Concurrent::Map.new { |h, k| h.compute_if_absent(k) { [] } }
|
19
56
|
@other_subscribers = []
|
20
|
-
@
|
57
|
+
@all_listeners_for = Concurrent::Map.new
|
58
|
+
@groups_for = Concurrent::Map.new
|
59
|
+
@silenceable_groups_for = Concurrent::Map.new
|
21
60
|
super
|
22
61
|
end
|
23
62
|
|
63
|
+
def inspect # :nodoc:
|
64
|
+
total_patterns = @string_subscribers.size + @other_subscribers.size
|
65
|
+
"#<#{self.class} (#{total_patterns} patterns)>"
|
66
|
+
end
|
67
|
+
|
24
68
|
def subscribe(pattern = nil, callable = nil, monotonic: false, &block)
|
25
69
|
subscriber = Subscribers.new(pattern, callable || block, monotonic)
|
26
70
|
synchronize do
|
27
|
-
|
71
|
+
case pattern
|
72
|
+
when String
|
28
73
|
@string_subscribers[pattern] << subscriber
|
29
|
-
|
30
|
-
|
74
|
+
clear_cache(pattern)
|
75
|
+
when NilClass, Regexp
|
31
76
|
@other_subscribers << subscriber
|
32
|
-
|
77
|
+
clear_cache
|
78
|
+
else
|
79
|
+
raise ArgumentError, "pattern must be specified as a String, Regexp or empty"
|
33
80
|
end
|
34
81
|
end
|
35
82
|
subscriber
|
@@ -40,44 +87,232 @@ module ActiveSupport
|
|
40
87
|
case subscriber_or_name
|
41
88
|
when String
|
42
89
|
@string_subscribers[subscriber_or_name].clear
|
43
|
-
|
90
|
+
clear_cache(subscriber_or_name)
|
44
91
|
@other_subscribers.each { |sub| sub.unsubscribe!(subscriber_or_name) }
|
45
92
|
else
|
46
93
|
pattern = subscriber_or_name.try(:pattern)
|
47
94
|
if String === pattern
|
48
95
|
@string_subscribers[pattern].delete(subscriber_or_name)
|
49
|
-
|
96
|
+
clear_cache(pattern)
|
50
97
|
else
|
51
98
|
@other_subscribers.delete(subscriber_or_name)
|
52
|
-
|
99
|
+
clear_cache
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
def clear_cache(key = nil) # :nodoc:
|
106
|
+
if key
|
107
|
+
@all_listeners_for.delete(key)
|
108
|
+
@groups_for.delete(key)
|
109
|
+
@silenceable_groups_for.delete(key)
|
110
|
+
else
|
111
|
+
@all_listeners_for.clear
|
112
|
+
@groups_for.clear
|
113
|
+
@silenceable_groups_for.clear
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
class BaseGroup # :nodoc:
|
118
|
+
include FanoutIteration
|
119
|
+
|
120
|
+
def initialize(listeners, name, id, payload)
|
121
|
+
@listeners = listeners
|
122
|
+
end
|
123
|
+
|
124
|
+
def each(&block)
|
125
|
+
iterate_guarding_exceptions(@listeners, &block)
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
class BaseTimeGroup < BaseGroup # :nodoc:
|
130
|
+
def start(name, id, payload)
|
131
|
+
@start_time = now
|
132
|
+
end
|
133
|
+
|
134
|
+
def finish(name, id, payload)
|
135
|
+
stop_time = now
|
136
|
+
each do |listener|
|
137
|
+
listener.call(name, @start_time, stop_time, id, payload)
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
class MonotonicTimedGroup < BaseTimeGroup # :nodoc:
|
143
|
+
private
|
144
|
+
def now
|
145
|
+
Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
class TimedGroup < BaseTimeGroup # :nodoc:
|
150
|
+
private
|
151
|
+
def now
|
152
|
+
Time.now
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
class EventedGroup < BaseGroup # :nodoc:
|
157
|
+
def start(name, id, payload)
|
158
|
+
each do |s|
|
159
|
+
s.start(name, id, payload)
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
def finish(name, id, payload)
|
164
|
+
each do |s|
|
165
|
+
s.finish(name, id, payload)
|
166
|
+
end
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
170
|
+
class EventObjectGroup < BaseGroup # :nodoc:
|
171
|
+
def start(name, id, payload)
|
172
|
+
@event = build_event(name, id, payload)
|
173
|
+
@event.start!
|
174
|
+
end
|
175
|
+
|
176
|
+
def finish(name, id, payload)
|
177
|
+
@event.payload = payload
|
178
|
+
@event.finish!
|
179
|
+
|
180
|
+
each do |s|
|
181
|
+
s.call(@event)
|
182
|
+
end
|
183
|
+
end
|
184
|
+
|
185
|
+
private
|
186
|
+
def build_event(name, id, payload)
|
187
|
+
ActiveSupport::Notifications::Event.new name, nil, nil, id, payload
|
188
|
+
end
|
189
|
+
end
|
190
|
+
|
191
|
+
def groups_for(name) # :nodoc:
|
192
|
+
groups = @groups_for.compute_if_absent(name) do
|
193
|
+
all_listeners_for(name).reject(&:silenceable).group_by(&:group_class).transform_values do |s|
|
194
|
+
s.map(&:delegate)
|
195
|
+
end
|
196
|
+
end
|
197
|
+
|
198
|
+
silenceable_groups = @silenceable_groups_for.compute_if_absent(name) do
|
199
|
+
all_listeners_for(name).select(&:silenceable).group_by(&:group_class).transform_values do |s|
|
200
|
+
s.map(&:delegate)
|
201
|
+
end
|
202
|
+
end
|
203
|
+
|
204
|
+
unless silenceable_groups.empty?
|
205
|
+
groups = groups.dup
|
206
|
+
silenceable_groups.each do |group_class, subscriptions|
|
207
|
+
active_subscriptions = subscriptions.reject { |s| s.silenced?(name) }
|
208
|
+
unless active_subscriptions.empty?
|
209
|
+
groups[group_class] = (groups[group_class] || []) + active_subscriptions
|
53
210
|
end
|
54
211
|
end
|
55
212
|
end
|
213
|
+
|
214
|
+
groups
|
215
|
+
end
|
216
|
+
|
217
|
+
# A +Handle+ is used to record the start and finish time of event.
|
218
|
+
#
|
219
|
+
# Both #start and #finish must each be called exactly once.
|
220
|
+
#
|
221
|
+
# Where possible, it's best to use the block form: ActiveSupport::Notifications.instrument.
|
222
|
+
# +Handle+ is a low-level API intended for cases where the block form can't be used.
|
223
|
+
#
|
224
|
+
# handle = ActiveSupport::Notifications.instrumenter.build_handle("my.event", {})
|
225
|
+
# begin
|
226
|
+
# handle.start
|
227
|
+
# # work to be instrumented
|
228
|
+
# ensure
|
229
|
+
# handle.finish
|
230
|
+
# end
|
231
|
+
class Handle
|
232
|
+
include FanoutIteration
|
233
|
+
|
234
|
+
def initialize(notifier, name, id, payload) # :nodoc:
|
235
|
+
@name = name
|
236
|
+
@id = id
|
237
|
+
@payload = payload
|
238
|
+
@groups = notifier.groups_for(name).map do |group_klass, grouped_listeners|
|
239
|
+
group_klass.new(grouped_listeners, name, id, payload)
|
240
|
+
end
|
241
|
+
@state = :initialized
|
242
|
+
end
|
243
|
+
|
244
|
+
def start
|
245
|
+
ensure_state! :initialized
|
246
|
+
@state = :started
|
247
|
+
|
248
|
+
iterate_guarding_exceptions(@groups) do |group|
|
249
|
+
group.start(@name, @id, @payload)
|
250
|
+
end
|
251
|
+
end
|
252
|
+
|
253
|
+
def finish
|
254
|
+
finish_with_values(@name, @id, @payload)
|
255
|
+
end
|
256
|
+
|
257
|
+
def finish_with_values(name, id, payload) # :nodoc:
|
258
|
+
ensure_state! :started
|
259
|
+
@state = :finished
|
260
|
+
|
261
|
+
iterate_guarding_exceptions(@groups) do |group|
|
262
|
+
group.finish(name, id, payload)
|
263
|
+
end
|
264
|
+
end
|
265
|
+
|
266
|
+
private
|
267
|
+
def ensure_state!(expected)
|
268
|
+
if @state != expected
|
269
|
+
raise ArgumentError, "expected state to be #{expected.inspect} but was #{@state.inspect}"
|
270
|
+
end
|
271
|
+
end
|
272
|
+
end
|
273
|
+
|
274
|
+
include FanoutIteration
|
275
|
+
|
276
|
+
def build_handle(name, id, payload)
|
277
|
+
Handle.new(self, name, id, payload)
|
56
278
|
end
|
57
279
|
|
58
280
|
def start(name, id, payload)
|
59
|
-
|
281
|
+
handle_stack = (IsolatedExecutionState[:_fanout_handle_stack] ||= [])
|
282
|
+
handle = build_handle(name, id, payload)
|
283
|
+
handle_stack << handle
|
284
|
+
handle.start
|
60
285
|
end
|
61
286
|
|
62
|
-
def finish(name, id, payload, listeners =
|
63
|
-
|
287
|
+
def finish(name, id, payload, listeners = nil)
|
288
|
+
handle_stack = IsolatedExecutionState[:_fanout_handle_stack]
|
289
|
+
handle = handle_stack.pop
|
290
|
+
handle.finish_with_values(name, id, payload)
|
64
291
|
end
|
65
292
|
|
66
293
|
def publish(name, *args)
|
67
|
-
listeners_for(name)
|
294
|
+
iterate_guarding_exceptions(listeners_for(name)) { |s| s.publish(name, *args) }
|
68
295
|
end
|
69
296
|
|
70
|
-
def
|
297
|
+
def publish_event(event)
|
298
|
+
iterate_guarding_exceptions(listeners_for(event.name)) { |s| s.publish_event(event) }
|
299
|
+
end
|
300
|
+
|
301
|
+
def all_listeners_for(name)
|
71
302
|
# this is correctly done double-checked locking (Concurrent::Map's lookups have volatile semantics)
|
72
|
-
@
|
303
|
+
@all_listeners_for[name] || synchronize do
|
73
304
|
# use synchronisation when accessing @subscribers
|
74
|
-
@
|
305
|
+
@all_listeners_for[name] ||=
|
75
306
|
@string_subscribers[name] + @other_subscribers.select { |s| s.subscribed_to?(name) }
|
76
307
|
end
|
77
308
|
end
|
78
309
|
|
310
|
+
def listeners_for(name)
|
311
|
+
all_listeners_for(name).reject { |s| s.silenced?(name) }
|
312
|
+
end
|
313
|
+
|
79
314
|
def listening?(name)
|
80
|
-
|
315
|
+
all_listeners_for(name).any? { |s| !s.silenced?(name) }
|
81
316
|
end
|
82
317
|
|
83
318
|
# This is a sync queue, so there is no waiting.
|
@@ -91,33 +326,30 @@ module ActiveSupport
|
|
91
326
|
if listener.respond_to?(:start) && listener.respond_to?(:finish)
|
92
327
|
subscriber_class = Evented
|
93
328
|
else
|
94
|
-
# Doing
|
95
|
-
# `proc {
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
329
|
+
# Doing this to detect a single argument block or callable
|
330
|
+
# like `proc { |x| }` vs `proc { |*x| }`, `proc { |**x| }`,
|
331
|
+
# or `proc { |x, **y| }`
|
332
|
+
procish = listener.respond_to?(:parameters) ? listener : listener.method(:call)
|
333
|
+
|
334
|
+
if procish.arity == 1 && procish.parameters.length == 1
|
335
|
+
subscriber_class = EventObject
|
101
336
|
end
|
102
337
|
end
|
103
338
|
|
104
|
-
|
105
|
-
end
|
106
|
-
|
107
|
-
def self.wrap_all(pattern, subscriber)
|
108
|
-
unless pattern
|
109
|
-
AllMessages.new(subscriber)
|
110
|
-
else
|
111
|
-
subscriber
|
112
|
-
end
|
339
|
+
subscriber_class.new(pattern, listener)
|
113
340
|
end
|
114
341
|
|
115
|
-
class Matcher
|
342
|
+
class Matcher # :nodoc:
|
116
343
|
attr_reader :pattern, :exclusions
|
117
344
|
|
118
345
|
def self.wrap(pattern)
|
119
|
-
|
120
|
-
|
346
|
+
if String === pattern
|
347
|
+
pattern
|
348
|
+
elsif pattern.nil?
|
349
|
+
AllMessages.new
|
350
|
+
else
|
351
|
+
new(pattern)
|
352
|
+
end
|
121
353
|
end
|
122
354
|
|
123
355
|
def initialize(pattern)
|
@@ -132,15 +364,31 @@ module ActiveSupport
|
|
132
364
|
def ===(name)
|
133
365
|
pattern === name && !exclusions.include?(name)
|
134
366
|
end
|
367
|
+
|
368
|
+
class AllMessages
|
369
|
+
def ===(name)
|
370
|
+
true
|
371
|
+
end
|
372
|
+
|
373
|
+
def unsubscribe!(*)
|
374
|
+
false
|
375
|
+
end
|
376
|
+
end
|
135
377
|
end
|
136
378
|
|
137
|
-
class Evented
|
138
|
-
attr_reader :pattern
|
379
|
+
class Evented # :nodoc:
|
380
|
+
attr_reader :pattern, :delegate, :silenceable
|
139
381
|
|
140
382
|
def initialize(pattern, delegate)
|
141
383
|
@pattern = Matcher.wrap(pattern)
|
142
384
|
@delegate = delegate
|
385
|
+
@silenceable = delegate.respond_to?(:silenced?)
|
143
386
|
@can_publish = delegate.respond_to?(:publish)
|
387
|
+
@can_publish_event = delegate.respond_to?(:publish_event)
|
388
|
+
end
|
389
|
+
|
390
|
+
def group_class
|
391
|
+
EventedGroup
|
144
392
|
end
|
145
393
|
|
146
394
|
def publish(name, *args)
|
@@ -149,109 +397,51 @@ module ActiveSupport
|
|
149
397
|
end
|
150
398
|
end
|
151
399
|
|
152
|
-
def
|
153
|
-
@
|
400
|
+
def publish_event(event)
|
401
|
+
if @can_publish_event
|
402
|
+
@delegate.publish_event event
|
403
|
+
else
|
404
|
+
publish(event.name, event.time, event.end, event.transaction_id, event.payload)
|
405
|
+
end
|
154
406
|
end
|
155
407
|
|
156
|
-
def
|
157
|
-
@delegate.
|
408
|
+
def silenced?(name)
|
409
|
+
@silenceable && @delegate.silenced?(name)
|
158
410
|
end
|
159
411
|
|
160
412
|
def subscribed_to?(name)
|
161
413
|
pattern === name
|
162
414
|
end
|
163
415
|
|
164
|
-
def matches?(name)
|
165
|
-
pattern && pattern === name
|
166
|
-
end
|
167
|
-
|
168
416
|
def unsubscribe!(name)
|
169
417
|
pattern.unsubscribe!(name)
|
170
418
|
end
|
171
419
|
end
|
172
420
|
|
173
421
|
class Timed < Evented # :nodoc:
|
174
|
-
def
|
175
|
-
|
176
|
-
end
|
177
|
-
|
178
|
-
def start(name, id, payload)
|
179
|
-
timestack = Thread.current[:_timestack] ||= []
|
180
|
-
timestack.push Time.now
|
422
|
+
def group_class
|
423
|
+
TimedGroup
|
181
424
|
end
|
182
425
|
|
183
|
-
def finish(name, id, payload)
|
184
|
-
timestack = Thread.current[:_timestack]
|
185
|
-
started = timestack.pop
|
186
|
-
@delegate.call(name, started, Time.now, id, payload)
|
187
|
-
end
|
188
|
-
end
|
189
|
-
|
190
|
-
class MonotonicTimed < Evented # :nodoc:
|
191
426
|
def publish(name, *args)
|
192
427
|
@delegate.call name, *args
|
193
428
|
end
|
194
|
-
|
195
|
-
def start(name, id, payload)
|
196
|
-
timestack = Thread.current[:_timestack_monotonic] ||= []
|
197
|
-
timestack.push Concurrent.monotonic_time
|
198
|
-
end
|
199
|
-
|
200
|
-
def finish(name, id, payload)
|
201
|
-
timestack = Thread.current[:_timestack_monotonic]
|
202
|
-
started = timestack.pop
|
203
|
-
@delegate.call(name, started, Concurrent.monotonic_time, id, payload)
|
204
|
-
end
|
205
429
|
end
|
206
430
|
|
207
|
-
class
|
208
|
-
def
|
209
|
-
|
210
|
-
event = build_event name, id, payload
|
211
|
-
event.start!
|
212
|
-
stack.push event
|
213
|
-
end
|
214
|
-
|
215
|
-
def finish(name, id, payload)
|
216
|
-
stack = Thread.current[:_event_stack]
|
217
|
-
event = stack.pop
|
218
|
-
event.payload = payload
|
219
|
-
event.finish!
|
220
|
-
@delegate.call event
|
431
|
+
class MonotonicTimed < Timed # :nodoc:
|
432
|
+
def group_class
|
433
|
+
MonotonicTimedGroup
|
221
434
|
end
|
222
|
-
|
223
|
-
private
|
224
|
-
def build_event(name, id, payload)
|
225
|
-
ActiveSupport::Notifications::Event.new name, nil, nil, id, payload
|
226
|
-
end
|
227
435
|
end
|
228
436
|
|
229
|
-
class
|
230
|
-
def
|
231
|
-
|
232
|
-
end
|
233
|
-
|
234
|
-
def start(name, id, payload)
|
235
|
-
@delegate.start name, id, payload
|
236
|
-
end
|
237
|
-
|
238
|
-
def finish(name, id, payload)
|
239
|
-
@delegate.finish name, id, payload
|
240
|
-
end
|
241
|
-
|
242
|
-
def publish(name, *args)
|
243
|
-
@delegate.publish name, *args
|
244
|
-
end
|
245
|
-
|
246
|
-
def subscribed_to?(name)
|
247
|
-
true
|
437
|
+
class EventObject < Evented
|
438
|
+
def group_class
|
439
|
+
EventObjectGroup
|
248
440
|
end
|
249
441
|
|
250
|
-
def
|
251
|
-
|
442
|
+
def publish_event(event)
|
443
|
+
@delegate.call event
|
252
444
|
end
|
253
|
-
|
254
|
-
alias :matches? :===
|
255
445
|
end
|
256
446
|
end
|
257
447
|
end
|