async_hooks: multi-tenant promise hook api#39283
Conversation
2e7497f to
e60e621
Compare
|
@nodejs/async_hooks |
AndreasMadsen
left a comment
There was a problem hiding this comment.
I like this direction. In my opinion tracking promises should not be a part of async_hooks. except for .then() because that is the only async operation.
However, this seems to be some wired middle ground. Where promise_hooks lives as its own documentation entry but is still merged with async_hooks, while also having a different API than AsyncHook when it doesn't need to.
I would like to either separate the modules or keep the API similar and the documentation together.
lib/internal/promise_hook.js
Outdated
| if (after) ArrayPrototypePush(hooks, onAfter(after)); | ||
| if (resolve) ArrayPrototypePush(hooks, onResolve(resolve)); | ||
|
|
||
| return () => { |
There was a problem hiding this comment.
I see it as API fragmentation to deviate from the enable and disable methods in async_hooks.
There was a problem hiding this comment.
What do you think of createHook returning an object with enable/disable while the on* functions continue to just return stop functions?
To me, the API of async_hooks is more complicated than it needs to be, especially here where a lot of users are likely only going to care about the init event. I'm not a fan of explicitly needing to call enable at the start--why even create the hooks if you aren't ready to enable them yet? Personally I'd rather just supply a function again if I want to attach it again rather that wrapping it in an unnecessary tracking object that does nothing else except attach and detach it. But then I also tend to prefer more functional code in general. π€·
There was a problem hiding this comment.
Sometimes it is useful to be able to have a state in its own scope, like a WeekMap for the promises, while also delaying tracking until an event, for example server.on('listen').
I don't think I had a strong opinion on what the default was (enabled or disabled), but there is a real benefit in being able to enable hooks again after they have been disabled.
There was a problem hiding this comment.
Sure, but I don't see why it needs an object to manage enabling it again when you could just pass the function in again. π€·ββοΈ
There was a problem hiding this comment.
The scope where you enable again may not be the scope of the WeekMap. In general, I don't think hooks should be functional. Hooks don't return anything and inherently depend on mutating a state to do something, so they will never truly be functional.
There was a problem hiding this comment.
Not sure what you are referring to about a WeakMap. As for if it's functional or not, I don't think that matters here. I just find it simpler to use functions rather than objects. It's also safer as internals canβt be tampered with. If people feel strongly that it should be object-based though, I'm happy to reconsider.
There was a problem hiding this comment.
Thinking about it more, I would say making it look more like async_hooks would actually be very confusing. More than just the specific intent being different, the actual functionality is different enough that it would just be a source of confusion, especially if we opt to move the API back into the async_hooks module. The set of lifecycle events does not match what async_hooks produces as there's no destroy event, and the hook functions all receive the promise object, there is no ID mechanism like async_hooks has, so the hook functions are different enough the making the API look too similar to async_hooks would most likely just confuse people that would expect functionality to be identical when it's not.
There was a problem hiding this comment.
I'm torn on the enable/disable question. I prefer the function return but, with the enable/disable pattern, I can create the hook but more precisely control when it is enabled. I like having that ability to separate the creation of the hook from the enabling of it. I can live with this API design tho.
There was a problem hiding this comment.
I've dealt with all the firm feedback. Would you like me to change the form of this API to mirror that enable/disable functionality? I'm okay with it either way, I just went for this design because it was simpler.
|
I'm happy to make this top-level if people prefer. I just chose to put it under async_hooks because we've historically done that with some other hooks-related things like |
e60e621 to
e6d77f3
Compare
Well, I also found that a wired choice. I'm fine with it being in |
|
My latest change makes it a top-level module of its own. Still need to do some stuff around error handling, but I'll be on vacation for the next week so I'll have to get back to this later. Thanks for the feedback so far! π |
e6d77f3 to
54b9ce1
Compare
|
I've added a test which verifies proper handling of exceptions within hooks. The JS code doesn't actually do anything with exceptions, the exception routing is entirely within the original PromiseHook changes I made in V8, this test just confirms that they get routed to the |
This comment has been minimized.
This comment has been minimized.
4efda13 to
80855c5
Compare
This comment has been minimized.
This comment has been minimized.
|
Changed from semver-major to semver-minor as this no longer adds a new top level module. |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
|
Rebased. Hopefully that will help with the CI failures. |
This comment has been minimized.
This comment has been minimized.
|
Test failures all seem to be unrelated but consistent. They appear to be causing failures in many other PRs too, according to the CI reliability reports. Not sure how to proceed other than just waiting for those tests to get fixed. |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
|
@Qard Finally CI is green. Do you want to adapt the commit message during landing as component is no longer async_hooks? |
|
Does our tooling support the new subsystem? Not sure if our commit linting would blow up on that. |
|
It's part of v8 now which is not that new. |
|
Oh, you mean change to "V8" as the subsystem? I'm good with that. Is that how we express changes to the V8 module? Not sure if that's confusing with the distinction between V8 itself and our module for it. Whatever matches what we're doing currently is good with me though. π |
|
To my understanding that's how it's done usually. |
PR-URL: nodejs#39283 Reviewed-By: Gerhard StΓΆbich <deb2001-github@yahoo.de> Reviewed-By: Vladimir de Turckheim <vlad2t@hotmail.com> Reviewed-By: Joyee Cheung <joyeec9h3@gmail.com> Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com>
|
Landed in da82844 |
I've introduced a new
promise_hookmodule which exposes thePromiseHookAPI in V8 more directly to userland. I've also updatedasync_hooksto consume this new API for its own promise lifecycle events. This is part of my ongoing effort to break downasync_hooksinto more purpose-specific components that can be used directly rather than usingasync_hooksitself which conflates many different data sources and can be awkward to use at times. Feedback is welcome. πΈ