mirror of https://github.com/rails/rails
Fix exception guards on multiple subscriber types
Previously in https://github.com/rails/rails/pull/43282, which shipped with Rails 7.0, we added the guarantee that if an exception occurred within an ActiveSupport::Notificaitons subscriber that the remaining subscribers would still be run. This was broken in https://github.com/rails/rails/pull/44469, where the different types of subscribers were broken into groups by type for performance. Although we would guard exceptions and allways run all (or none) of the same group, that didn't work cross-group with different types of subscriber.
This commit is contained in:
parent
a4751751bc
commit
7beaacce51
|
@ -17,10 +17,11 @@ module ActiveSupport
|
|||
end
|
||||
|
||||
module FanoutIteration # :nodoc:
|
||||
def iterate_guarding_exceptions(listeners)
|
||||
private
|
||||
def iterate_guarding_exceptions(collection)
|
||||
exceptions = nil
|
||||
|
||||
listeners.each do |s|
|
||||
collection.each do |s|
|
||||
yield s
|
||||
rescue Exception => e
|
||||
exceptions ||= []
|
||||
|
@ -28,6 +29,9 @@ module ActiveSupport
|
|||
end
|
||||
|
||||
if exceptions
|
||||
exceptions = exceptions.flat_map do |exception|
|
||||
exception.is_a?(InstrumentationSubscriberError) ? exception.exceptions : [exception]
|
||||
end
|
||||
if exceptions.size == 1
|
||||
raise exceptions.first
|
||||
else
|
||||
|
@ -35,7 +39,7 @@ module ActiveSupport
|
|||
end
|
||||
end
|
||||
|
||||
listeners
|
||||
collection
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -222,6 +226,8 @@ module ActiveSupport
|
|||
# handle.finish
|
||||
# end
|
||||
class Handle
|
||||
include FanoutIteration
|
||||
|
||||
def initialize(notifier, name, id, payload) # :nodoc:
|
||||
@name = name
|
||||
@id = id
|
||||
|
@ -236,7 +242,7 @@ module ActiveSupport
|
|||
ensure_state! :initialized
|
||||
@state = :started
|
||||
|
||||
@groups.each do |group|
|
||||
iterate_guarding_exceptions(@groups) do |group|
|
||||
group.start(@name, @id, @payload)
|
||||
end
|
||||
end
|
||||
|
@ -249,7 +255,7 @@ module ActiveSupport
|
|||
ensure_state! :started
|
||||
@state = :finished
|
||||
|
||||
@groups.each do |group|
|
||||
iterate_guarding_exceptions(@groups) do |group|
|
||||
group.finish(name, id, payload)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -126,6 +126,9 @@ module ActiveSupport
|
|||
listener = Listener.new
|
||||
notifier.subscribe nil, BadFinishListener.new
|
||||
notifier.subscribe nil, BadFinishListener.new
|
||||
notifier.subscribe(nil) { |*args| raise "foo" }
|
||||
notifier.subscribe(nil) { |obj| raise "foo" }
|
||||
notifier.subscribe(nil, monotonic: true) { |obj| raise "foo" }
|
||||
notifier.subscribe nil, listener
|
||||
|
||||
notifier.start "hello", 1, {}
|
||||
|
@ -133,11 +136,13 @@ module ActiveSupport
|
|||
error = assert_raises InstrumentationSubscriberError do
|
||||
notifier.finish "world", 1, {}
|
||||
end
|
||||
assert_equal 5, error.exceptions.count
|
||||
assert_instance_of BadListenerException, error.cause
|
||||
|
||||
error = assert_raises InstrumentationSubscriberError do
|
||||
notifier.finish "hello", 1, {}
|
||||
end
|
||||
assert_equal 5, error.exceptions.count
|
||||
assert_instance_of BadListenerException, error.cause
|
||||
|
||||
assert_equal 4, listener.events.length
|
||||
|
|
Loading…
Reference in New Issue