-
Notifications
You must be signed in to change notification settings - Fork 29.8k
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
AsyncWrap external API improvements #3461
Conversation
env->set_async_hooks_pre_function(args[1].As<Function>()); | ||
env->set_async_hooks_post_function(args[2].As<Function>()); | ||
if (args[0]->IsFunction()) | ||
env->set_async_hooks_init_function(args[0].As<Function>()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since the init callback is always necessary, will change this to fail if init callback is not passed.
semver-minor or major? |
env->set_async_hooks_init_function(args[0].As<Function>()); | ||
env->set_async_hooks_pre_function(args[1].As<Function>()); | ||
env->set_async_hooks_post_function(args[2].As<Function>()); | ||
if (args[0]->IsFunction()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Earlier if the arguments are not functions, it will throw. This change will ignore the values if they are not functions. Is that okay?
Edit: Ah, I see it now. This is the first point in the PR description.
Why do we need the unique ids? |
re semver—so far we've been treating AsyncWrap changes as neither major nor minor but getting all changes in to patch releases because it's sort of in "unofficial" land, undocumented anyway at some point we have to grow out of that though! @trevnorris do you have a feel for maturity of AsyncWrap? We can't leave it in limbo, it needs to be an official API at some point. |
@thefourtheye For the new destructed callback. We can't return the instance like we do in the others, so instead we give the id of the instance being destroyed. @rvagg My recent flurry of PRs regarding async wrap is to address this. I feel like it's almost ready to be made publicly experimental API, but there is still some cleanup that needs to be done. e.g. it can't simply abort if something goes wrong. like right now if any of the callbacks throw the program will simply crash. I did that b/c I honestly have no idea what will happen to the application if execution proceeds after an exception. There's also the case of timers. Currently none of these are being tracked. While this could be delayed until after making the API public, I have a couple implementation ideas to try out first. |
20c95fd
to
c11d56f
Compare
Added test and rebased. |
c11d56f
to
f8a3b16
Compare
needs someone more qualified than me to review, @nodejs/tracing, @bnoordhuis or @thlorenz perhaps? |
@@ -103,6 +103,9 @@ RetainedObjectInfo* WrapperInfo(uint16_t class_id, Local<Value> wrapper) { | |||
|
|||
static void EnableHooksJS(const FunctionCallbackInfo<Value>& args) { | |||
Environment* env = Environment::GetCurrent(args); | |||
Local<Function> init_fn = env->async_hooks_init_function(); | |||
if (init_fn.IsEmpty() || !init_fn->IsFunction()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why is the function check required? In the reset of the code only init_fn.IsEmpty()
is used to check of async-wrap is enabled. The SetupHooks
function also checks that init_fn
is a function.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Currently in AsyncWrap::AsyncWrap
we check if the init
hook is set. If not then it returns early. If this is the case then bits_
will never be set and no additional callback will ever be called for that object as a result. I can probably rethink the logic, but this seemed the most straight forward for this PR.
Very awesome with the destructor hook. But how does this fit into the tick/turn logic, does it follow immediately after the |
Doesn't have a specific timing. Sometimes the handle is cleaned up on a |
f8a3b16
to
1144ed2
Compare
LGTM, if CI is green |
1144ed2
to
325cb95
Compare
One final CI after rebase: https://ci.nodejs.org/job/node-test-pull-request/681/ |
325cb95
to
8983ab4
Compare
Only enforce that the init callback is passed to setupHooks(). The remaining hooks can be optionally passed. Throw if async_wrap.enable() runs before setting the init callback or if setupHooks() is called while async wrap is enabled. Add test to verify calls throw appropriately. PR-URL: nodejs#3461 Reviewed-By: Fedor Indutny <fedor@indutny.com>
New instances of AsyncWrap are automatically assigned a unique id. The value will be used in future commits to communicate additional information via the async hooks. While the largest value we can reliably communicate to JS is 2^53, even if a new AsyncWrap is created every 100ns the uid won't reach its end for 28.5 years. PR-URL: nodejs#3461 Reviewed-By: Fedor Indutny <fedor@indutny.com>
Call a user's callback to notify that the handle has been destroyed. Only pass the id of the AsyncWrap instance since the object no longer exists. The object that's being destructed should never be inspected within the callback or any time afterward. This commit make a breaking change. The init callback will now be passed arguments in the order of provider, id, parent. PR-URL: nodejs#3461 Reviewed-By: Fedor Indutny <fedor@indutny.com>
8983ab4
to
bb1bd76
Compare
@jasnell Thoughts on LTS worthy? Since this is technically internal API still, no API breakage. |
Only enforce that the init callback is passed to setupHooks(). The remaining hooks can be optionally passed. Throw if async_wrap.enable() runs before setting the init callback or if setupHooks() is called while async wrap is enabled. Add test to verify calls throw appropriately. PR-URL: #3461 Reviewed-By: Fedor Indutny <fedor@indutny.com>
New instances of AsyncWrap are automatically assigned a unique id. The value will be used in future commits to communicate additional information via the async hooks. While the largest value we can reliably communicate to JS is 2^53, even if a new AsyncWrap is created every 100ns the uid won't reach its end for 28.5 years. PR-URL: #3461 Reviewed-By: Fedor Indutny <fedor@indutny.com>
Call a user's callback to notify that the handle has been destroyed. Only pass the id of the AsyncWrap instance since the object no longer exists. The object that's being destructed should never be inspected within the callback or any time afterward. This commit make a breaking change. The init callback will now be passed arguments in the order of provider, id, parent. PR-URL: #3461 Reviewed-By: Fedor Indutny <fedor@indutny.com>
I'm a tentative +1 on getting the asyncwrap improvements into v4.x but I think this might be worth discussing in either a CTC or LTS WG meeting because the API is getting close to being finalised and documented, how far do we go in keeping it updated in LTS? It's useful but mostly a background feature for everyone but those in the know. |
@rvagg @trevnorris was a decision reached regarding landing this on 4.x? |
I can't recall exactly but I'm pretty sure we agreed to land AsyncWrap functionality on to v4 but to stop short of announcing it as a major addition—we really just want to get parity where it gets to before it's announced as public in v5/v6 so we don't risk shipping a 1/2 baked version that's not compatible with anything else and is simply technical debt in v4. |
Only enforce that the init callback is passed to setupHooks(). The remaining hooks can be optionally passed. Throw if async_wrap.enable() runs before setting the init callback or if setupHooks() is called while async wrap is enabled. Add test to verify calls throw appropriately. PR-URL: #3461 Reviewed-By: Fedor Indutny <fedor@indutny.com>
New instances of AsyncWrap are automatically assigned a unique id. The value will be used in future commits to communicate additional information via the async hooks. While the largest value we can reliably communicate to JS is 2^53, even if a new AsyncWrap is created every 100ns the uid won't reach its end for 28.5 years. PR-URL: #3461 Reviewed-By: Fedor Indutny <fedor@indutny.com>
Call a user's callback to notify that the handle has been destroyed. Only pass the id of the AsyncWrap instance since the object no longer exists. The object that's being destructed should never be inspected within the callback or any time afterward. This commit make a breaking change. The init callback will now be passed arguments in the order of provider, id, parent. PR-URL: #3461 Reviewed-By: Fedor Indutny <fedor@indutny.com>
landed in v4.x-staging as ae46a23...dab862f If there are any concerns about this being in LTS please let me know and I'll back the commits out. |
@thealphanerd This was discussed in nodejs/Release#59 (comment)
|
Only enforce that the init callback is passed to setupHooks(). The remaining hooks can be optionally passed. Throw if async_wrap.enable() runs before setting the init callback or if setupHooks() is called while async wrap is enabled. Add test to verify calls throw appropriately. PR-URL: #3461 Reviewed-By: Fedor Indutny <fedor@indutny.com>
New instances of AsyncWrap are automatically assigned a unique id. The value will be used in future commits to communicate additional information via the async hooks. While the largest value we can reliably communicate to JS is 2^53, even if a new AsyncWrap is created every 100ns the uid won't reach its end for 28.5 years. PR-URL: #3461 Reviewed-By: Fedor Indutny <fedor@indutny.com>
Call a user's callback to notify that the handle has been destroyed. Only pass the id of the AsyncWrap instance since the object no longer exists. The object that's being destructed should never be inspected within the callback or any time afterward. This commit make a breaking change. The init callback will now be passed arguments in the order of provider, id, parent. PR-URL: #3461 Reviewed-By: Fedor Indutny <fedor@indutny.com>
Few improvements to make the
AsyncWrap
external API more usable. These include:AsyncWrap
instances receive a unique id.AsyncWrap
destructor.R=@bnoordhuis
CI: https://ci.nodejs.org/job/node-test-pull-request/548/