-
-
Notifications
You must be signed in to change notification settings - Fork 1.5k
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
Async exception tracking #24582
Async exception tracking #24582
Conversation
2c0cebd
to
e648b93
Compare
3f4b553
to
1ed9ea6
Compare
I'm almost certain this cannot be done in a backward compatible way. A lot of (non-async) procs in asyncdispatch.nim create and return a Maybe making I do realize this is throwing the baby out with the bathwater. The user could handle the asyncdispatch |
chronos went this way indeed to allow a more gradual transition from non-raises to raises - and to have better compatibility between libraries that use and don't use raises lists - the syntax has changed slightly since the linked pr, the annotation now looks like this: Per our pre-raises porting guide, this usually is relatively pain-free, ie we can combine raises and non-raises-annotated libraries usually by doing work only on the raises-annotated side which ends up being pretty natural (that's where you're changing the code anyway). The biggest problem arises when code uses async Finally, one of the biggest sources of bugs in asyncdispatch itself is uncaught exceptions that leak out of the event loop - before introducing raises in futures, we had to harden the core against those. The hardening of the core is what led to raises tracking being easier to introduce - code using chronos was already a little bit more exception-aware because of that. |
The main issue I found with the chronos approach is it makes error tracking annotations viral. There is no inference. In a previous approach I tried rewriting the return type to FutureEx + doing raises inference in a later stage (typed macro), but the raises list is not available for async generic procs at that point. I also ran into issues of the type I agree callbacks need to not raise; For this PR latest approach, if we had an async keyword, I'd be able to detect the proc is async and not a closure that happens to return a future, but can raise anything because the future result is "user controlled"; that way we could rely on the error tracking inference for the async proc. |
we started playing with that here: status-im/nim-chronos#327 - this is a little bit what I meant by adding language for raises computations - those would also include a |
Somewhat inspired in chronos.
Goal:
How:
read
call. If raises cannot be retrieved, then nothing is set, and the current behavior is kept (raises: [Exception]
).toFutureEx
macro takes an async function call, and it returns the error typed futureFutureEx[T, E]
for passing it around.addCallback
callbacks must not raise for this to work. It's possible to make this backward compatible, I think. Just deprecate the proc that takes a cb without raises: [], and cast it to untrack raises.newFuture()
usage in user code usually leads to inferredException
at some point becauseread(Future)
can raise anything. If the user wants granular raises, they must useFutureEx
.Todo:
all, and, or
FutureEx versionsfail
FutureEx version; can it be done so it only accepts the typed exceptions?Status: main blocker to move this forward is I cannot detect if a type is an async proc, or a closure that returns a Future (they are both the same type right now). See this test if we pass an async proc, the raises get inferred as [Exception] as well, since we cannot check if the callback is an async proc or a closure returning Future that can eventually fail with any exception. I suspect it may not be possible to get the raises lists for async generic callbacks.