-
Notifications
You must be signed in to change notification settings - Fork 30k
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
[Feature Request]: want to get parent promise from PromiseHookInit through async_hooks #13302
Comments
Ping @trevnorris @addaleax |
@jasnell , thank you ! I need this Also ping @AndreasMadsen, @matthewloring ! from the PromiseHook Sample https://docs.google.com/document/d/1rda3yKGHimKIhg5YeoAmCOtyURgsbTH_qaYR79FELlk/edit# there is code like this. const async_wrap = process.binding('async_wrap');
const chain = new Map();
const startTimes = new Map();
const endTimes = new Map();
let root;
function init(id, parentId) {
if (parentId !== undefined) {
chain.set(parentId, id);
} else {
root = id;
}
}
function before(id) { startTimes.set(id, Date.now()); }
function after(id) { endTimes.set(id, Date.now()); }
async_wrap.setupHooks({init, before, after});
async_wrap.enable();
doSomeAsyncOp()
.then(() => { .. })
.then(() => { .. })
async_wrap.disable();
let totalTime = 0;
while(root = chain.get(root)) {
totalTime += (endTimes.get(root) - startTimes.get(root));
}
console.log(totalTime);
const p = new Promise ( resolve => resolve(1) );
const p1 = p.then(val => { console.log(val == 1); return 2; });
const p2 = p.then(val => console.log(val == 1));
the call order will like
This is the expected result, but current nodejs 8 nightly build, the code is const async_hooks = require('async_hooks');
function init(id, provider, parentId, parentHandle) {
process._rawDebug('init ', id, provider, parentId, parentHandle);
}
function before(id) {
process._rawDebug('before', id);
}
function after(id) {
process._rawDebug('after', id);
}
function destroy(id) {
process._rawDebug('destroy', id);
}
async_hooks.createHook({init, before, after, destroy}).enable();
const p = new Promise ( resolve => {
process._rawDebug('execute p');
resolve(1);} );
const p1 = p.then(val => { process._rawDebug('p1 then', val); return 2; });
const p2 = p1.then(val => process._rawDebug('p2', val)); and the output is
The parentId are all edit (AndreasMadsen): added syntax highlighting |
I need confirmation that I understand the question/feature request correctly. Consider this code: const async_hooks = require('async_hooks');
async_hooks.createHook({
init(id, type, triggerId, resource) {
process._rawDebug('init', {id, type, triggerId, resource});
},
before(id) {
process._rawDebug('before', {id});
},
after(id) {
process._rawDebug('after', {id});
},
destroy(id) {
process._rawDebug('destroy', {id});
}
}).enable();
const p2 = new Promise(function (resolve) {
resolve(1);
});
const p3 = p2.then(function (val) {
return 2;
}); This results in the following output:
You would like the I think that is fair, it shouldn't be difficult implement. Honestly, the trigger id stuff is a little confusing to me, I would like to see a clear line when we set the |
@AndreasMadsen , thank you for the reply.
Yes, that will help. And If the implementation become like this, I have another question is
Can I say that |
Not always, If we implement as suggested, you can check if |
@AndreasMadsen , Thank you! Got it! |
@AndreasMadsen , should we add this issue to nodejs/diagnostics#29 as a feature request? Thank you! |
I want to close nodejs/diagnostics#29 as soon as documentation, N-API, and NAN is fixed. From a management perspective, we are moving from a project management to maintenance management, thus I see no need to create roadmaps etc.. If there are issues in nodejs/diagnostics#29 that have not been fixed by then I will create matching issues in nodejs/node so we can just filter by the |
@AndreasMadsen , thank you, so I will just leave this issue open here. |
Exactly! |
@AndreasMadsen , I tried to understand how to implement this one, I read the source in static void PromiseHook(PromiseHookType type, Local<Promise> promise,
Local<Value> parent, void* arg) {
Local<Context> context = promise->CreationContext();
Environment* env = Environment::GetCurrent(context);
PromiseWrap* wrap = Unwrap<PromiseWrap>(promise);
if (type == PromiseHookType::kInit || wrap == nullptr) {
bool silent = type != PromiseHookType::kInit;
wrap = new PromiseWrap(env, promise, silent);
wrap->MakeWeak(wrap);
} else if (type == PromiseHookType::kResolve) {
// TODO(matthewloring): need to expose this through the async hooks api.
}
CHECK_NE(wrap, nullptr);
if (type == PromiseHookType::kBefore) {
PreCallbackExecution(wrap, false);
} else if (type == PromiseHookType::kAfter) {
PostCallbackExecution(wrap, false);
}
} When I am very new to c++,sorry for the basic questions. Also ping @matthewloring , thank you so much for the great work to add PromiseHook into async_hooks, please help to look into this when you have time. I want to add this into Thank you very much! |
@JiaLiPassion I think you can get the id of the parent promise with Of course |
@AndreasMadsen , Thank you very much!
the code here,
and the spec here, https://docs.google.com/document/d/1rda3yKGHimKIhg5YeoAmCOtyURgsbTH_qaYR79FELlk/edit#
I think |
Yes |
@AndreasMadsen , sorry for so many basic questions, I don't know how to write C++ code at all, basically the updated logic will look like static void PromiseHook(PromiseHookType type, Local<Promise> promise,
Local<Value> parent, void* arg) {
Local<Context> context = promise->CreationContext();
Environment* env = Environment::GetCurrent(context);
PromiseWrap* wrap = Unwrap<PromiseWrap>(promise);
if (type == PromiseHookType::kInit || wrap == nullptr) {
bool silent = type != PromiseHookType::kInit;
// set parent promise's async Id as this promise's triggerId
if (!parent->IsUndefined()) {
// parent promise exists, current promise
// if a chained promise
double trigger_id = Unwrap<PromiseWrap>(parent)->get_id();
env->set_init_trigger_id(trigger_id);
wrap = new PromiseWrap(env, promise, silent);
} else {
wrap = new PromiseWrap(env, promise, silent);
}
wrap->MakeWeak(wrap);
} else if (type == PromiseHookType::kResolve) {
.... Is that correct? And when I compile, it seems
cause compile error with
And if we call
When should we clear this trigger_id? Thank you for your time! |
I think you need to cast the edit: okay, I guess
That is done automatically when you call |
I haven’t read the full thread here, but it seems the idea is to make the I agree that exposing it seems like a good idea, but I think the creation context id needs to remain accessible in some way; So we might need an API change, either in the style of (For example, I think for use cases like continuation-local storage the current code actually makes more sense.) |
@AndreasMadsen , Thank you very much! I will try it. |
@addaleax , Thank you for reply.
Yes, I want to know the newly created promise is a
So, you suggest we
or
is that correct? |
@addaleax We have that, it is |
async_hooks init callback will be triggered when promise newly created, in previous version, the parent promise which pass from chrome V8 PromiseHook is ignored, so we can't tell the promise is a pure new promise or a chained promise. In this commit, we use the parent promise's id as triggerId to trigger the init callback. Fixes: nodejs#13302
async_hooks init callback will be triggered when promise newly created, in previous version, the parent promise which pass from chrome V8 PromiseHook is ignored, so we can't tell the promise is a pure new promise or a chained promise. In this commit, we use the parent promise's id as triggerId to trigger the init callback. Fixes: #13302 PR-URL: #13367 Reviewed-By: Andreas Madsen <amwebdk@gmail.com> Reviewed-By: Anna Henningsen <anna@addaleax.net>
Version:
v8.0.0-nightly20170527f84666f923
Platform:
Subsystem:
Chrome V8 PromiseHook
init
hook's signature isPromiseHookInit(promise,parentPromise)
,current
async_hooks
seems not support to get theparentPromise
, is that possible to get thethe parentPromise from
async_hooks init
callback?Thank you very much!
The text was updated successfully, but these errors were encountered: