You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
That false says to not re-raise it. So the task exits and says there "might have been" an exception and gives the backtrace - all of which is helpful - but not enough. Ideally I would like it to treat StandardErrors the same way as Exceptions. At the least I want some way to get at the swallowed exceptions so I can re-raise them myself.
I'm happy to code a solution - including passing a parameter to Async do -- Async(error_handling: :reraise) do, or something like that.
Super helpful - thanks. I was doing something wrong, and I'm still not super happy with what I have to do.
My mistake:
Async do
Fiber.schedule do
...
end
Fiber.schedule do
...
end
end
Because I was using Fiber.schedule directly I had no access to the exceptions. That's my mistake and it happened because I was migrating to async and failed to convert the schedule calls.
What I have to do:
tasks = []
Async do
tasks << Async do
...
end
tasks << Async do
...
end
end
tasks.each(&:wait)
This is sufficient. But I would still prefer something more streamlined:
Async(raise_errors: true) do
Async do
...
end
Async do
...
end
end
Or perhaps (if the outer can keep track of the internal fibers)
Async do
Async do
...
end
Async do
...
end
end.reraise_errors
Having to gather and call wait to re-raise isn't at all intuitive. If I were coming to the code as a new user, I would probably assume the wait was needed to get the fibers to execute - not that it was being used to handle errors!
I use a barrier for this, since it collects the tasks in a "bucket" I can call wait on, but, yeah, dealing with exceptions is a bit more verbose. I suppose I don't think about it much anymore, once I got accustomed to it, tbh.
A task may outlive it's parent so the parent can't naturally be a scope for exception handling.
I think ideally, tasks don't raise exceptions as a matter of normal behaviour ("exceptional" cases).
Either you are waiting on a task to complete (fan out) or you are "fire and forget". You need to think about what situation you are in and what is the appropriate error handling for your situation.
Activity
trevorturk commentedon Apr 28, 2023
This is definitely easy to get tripped up on, and it's one of the more confusing aspects of Async, IMO, but I think it all makes sense eventually!
There's a bit of documentation around exceptions worth reading, you can check this out to get started: https://socketry.github.io/async/guides/asynchronous-tasks/index.html#exception-handling
Let me know what you think, and if you have more questions I can try to help, or I'm sure someone else can chime in as well!
kwerle commentedon Apr 28, 2023
Super helpful - thanks. I was doing something wrong, and I'm still not super happy with what I have to do.
My mistake:
Because I was using Fiber.schedule directly I had no access to the exceptions. That's my mistake and it happened because I was migrating to async and failed to convert the schedule calls.
What I have to do:
This is sufficient. But I would still prefer something more streamlined:
Or perhaps (if the outer can keep track of the internal fibers)
Having to gather and call wait to re-raise isn't at all intuitive. If I were coming to the code as a new user, I would probably assume the wait was needed to get the fibers to execute - not that it was being used to handle errors!
trevorturk commentedon Apr 28, 2023
I use a barrier for this, since it collects the tasks in a "bucket" I can call
waiton, but, yeah, dealing with exceptions is a bit more verbose. I suppose I don't think about it much anymore, once I got accustomed to it, tbh.ioquatix commentedon Apr 28, 2023
A task may outlive it's parent so the parent can't naturally be a scope for exception handling.
I think ideally, tasks don't raise exceptions as a matter of normal behaviour ("exceptional" cases).
Either you are waiting on a task to complete (fan out) or you are "fire and forget". You need to think about what situation you are in and what is the appropriate error handling for your situation.
As @trevorturk suggested, using an
Async::Barrieris a good option for fan-out. https://socketry.github.io/async/source/Async/Barrier/index.html