-
Notifications
You must be signed in to change notification settings - Fork 21.9k
Revert "Guard against subscriber exceptions in ActiveSupport::Notifications" #43561
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Revert "Guard against subscriber exceptions in ActiveSupport::Notifications" #43561
Conversation
Do you have an example of these cases? I'd think raising to interrupt an action should still work even if the exception is wrapped. |
Yeah, we have some test helpers like: def assert_no_redis_commands(&block)
callback = -> (_name, _start, _finnish, _message_id, values) do
raise(Minitest::Assertion, "Unexpected call to a Redis method: \n #{values[:commands]}")
end
ActiveSupport::Notifications.subscribed(callback, "command.shopify_metrics_redis", &block)
end This is just an example, but the exception class changing break various things. |
Yeah, I've incidentally encountered this exception-wrapping and found it made things more difficult to reason about. Calling all subscribers, then re-raising the first exception, seems like it might be the least-bad option to me. We'll go from aborting iteration immediately to at least giving each subscriber a chance to handle it... but would swallow any exceptions arising from the calls we historically would've skipped. The only alternative that comes to mind would be to re-raise a single exception untouched, but raise a new MultipleErrors exception (with |
As a quick fix yes, but I think ultimately the proper behavior would be to |
What about Shopify@e053a86 ? It's simple, solve the immediate problem. |
While that ensures we internally keep completions balanced, I think it still leaves subscribers potentially seeing a To me it makes sense that we'd stop processing immediately if a |
I think I like this one. Any rescues or similar not matching seems like a feature if there are multiple exceptions (because otherwise it's arbitrary). Side-note: I'd love to see us move away from the |
What is the difference between |
They're similar, but |
Should we remove |
I guess some subscribers might leak state of things like that if their
I suppose the multiple exception scenario is rare enough that we can indeed "optimize" it out. I'll open a PR for that. |
Closing in favor of #43581 |
Ref: rails#43282 Ref: rails#43561 It can be legitimate for subscriber to want to bubble up some exception to the caller, so wrapping it change the exception class which might break the calling code expecting a specific error. We can minimize this by only using InstrumentationSubscriberError when more than one subscriber raised.
Reverts #43282
@theojulienne @matthewd @rafaelfranca @jhawthorn I'm afraid this PR breaks a tons of code and more importantly breaks the legitimate use case of raising from a subscriber to interrupt an action.
Could we somehow split the
finish
in two, so that we first complete all the events, and then call all the subscribers?Alternatively as a short term solution I suppose we can re-raise the first exception we got? It's a bit dirty, but would work as a stopgap?