-
Notifications
You must be signed in to change notification settings - Fork 30.1k
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
docs: documenting async hooks features #12953
Conversation
doc/api/async_hooks.md
Outdated
|
||
### Overview | ||
|
||
Here is a simple overview of the public API. All of this API is explained in |
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.
s/Here/Following
``` | ||
|
||
#### `async_hooks.createHook(callbacks)` | ||
|
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.
args listing? e.g.
* `callbacks` ...
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.
Also, yaml block?
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.
Including args listing for consistency. The entire block below elaborates on what the callbacks
are.
Not sure what you mean by yaml block could you give an example?
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.
Not sure what you mean by yaml block could you give an example?
<!-- YAML
added: REPLACEME
-->
you can add those directly below headings :) (oh, and edit: the REPLACEME
is literal, it will be replaced during releasing)
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.
OK added, thanks
doc/api/async_hooks.md
Outdated
emulate the lifetime of handles and requests that do not fit this model. For | ||
example, `HTTPParser` instances are recycled to improve performance. Therefore the | ||
`destroy()` callback is called manually after a connection is done using | ||
it, just before it's placed back into the unused resource pool. |
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.
s/it's/it is
doc/api/async_hooks.md
Outdated
specifics of all functions that can be passed to `callbacks` is in the section | ||
`Hook Callbacks`. | ||
|
||
**Error Handling**: If any `AsyncHook` callbacks throw, the application will |
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.
This would be better as a heading... e.g.
##### Error Handling
doc/api/async_hooks.md
Outdated
Some examples include `TCP`, `GetAddrInfo` and `HTTPParser`. Users will be able | ||
to define their own `type` when using the public embedder API. | ||
|
||
**Note:** It is possible to have type name collisions. Embedders are recommended |
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.
s/**Note:**
/*Note*:
doc/api/async_hooks.md
Outdated
|
||
**Note:** Some resources depend on GC for cleanup. So if a reference is made to | ||
the `resource` object passed to `init()` it's possible that `destroy()` is | ||
never called. Causing a memory leak in the application. Of course if you know |
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.
Please avoid the use of you
doc/api/async_hooks.md
Outdated
placed in an unused resource pool to be used later. For these `destroy()` will | ||
be called just before the resource is placed on the unused resource pool. | ||
|
||
**Note:** Some resources depend on GC for cleanup. So if a reference is made to |
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.
s/**Note:**
/*Note*:
doc/api/async_hooks.md
Outdated
@@ -0,0 +1,670 @@ | |||
# Async Hooks | |||
|
|||
|
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.
No need for the extra blank lines in here
doc/api/async_hooks.md
Outdated
|
||
The `async-hooks` module provides an API to register callbacks tracking the | ||
lifetime of asynchronous resources created inside a Node.js application. | ||
|
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.
Please include something like:
It can be accessed using `require('async-hooks')`
doc/api/async_hooks.md
Outdated
|
||
## Terminology | ||
|
||
An async resource represents either a "handle" or a "request". |
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.
rather than the quotes, make these italic. e.g. handle or a request
repeating my comment from #12892 (comment):
What effect does that have for
--- a/lib/async_hooks.js
+++ b/lib/async_hooks.js
@@ -222,6 +222,13 @@ class AsyncEvent {
processing_hook = false;
}
+ makeCallback(cb, ...args) {
+ emitBeforeS(this[async_id_symbol], this[trigger_id_symbol]);
+ cb(...args);
+ emitAfterS(this[async_id_symbol]);
+ return this;
+ }
+ In response to @Fishrock123 (#12892 (comment)) ...
What made the In #11883 (comment) I explained the problems with the Can you elaborate on the domains problem you allude to? |
doc/api/async_hooks.md
Outdated
|
||
// Return the id of the handle responsible for triggering the callback of the | ||
// current execution scope to fire. | ||
const tid = aysnc_hooks.triggerId(); |
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.
s/aysnc/async
doc/api/async_hooks.md
Outdated
```js | ||
const async_hooks = require('async_hooks'); | ||
|
||
asyns_hooks.createHook({ |
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.
s/asyns/async
doc/api/async_hooks.md
Outdated
TTYWRAP(6) -> Timeout(4) -> TIMERWRAP(5) -> TickObject(3) -> root(1) | ||
``` | ||
|
||
The `TCPWRAP` isn't part of this graph; evne though it was the reason for |
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.
s/evne/even
doc/api/async_hooks.md
Outdated
|
||
### `class AsyncEvent()` | ||
|
||
The class `AsyncEvent` was designed to be extended from for embedder's async |
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.
Maybe replace from for
by by the
?
doc/api/async_hooks.md
Outdated
#### `AsyncEvent(type[, triggerId])` | ||
|
||
* arguments | ||
* `type` {String} the type of ascycn event |
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.
s/ascycn/async
doc/api/async_hooks.md
Outdated
|
||
```js | ||
class DBQuery extends AsyncEvent { | ||
construtor(db) { |
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.
s/construtor/constructor
doc/api/async_hooks.md
Outdated
* `id` {number} Generated by `newId()` | ||
* Returns {Undefined} | ||
|
||
Notify hooks that a resource is being destroyed (or being moved to the free'd |
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.
s/free'd/freed
doc/api/async_hooks.md
Outdated
``` | ||
|
||
It is important to note that the id returned fom `currentId()` is related to | ||
execution timing. Not causality (which is covered by `triggerId()`). For |
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.
Nit: s/ /
doc/api/async_hooks.md
Outdated
example: | ||
|
||
```js | ||
const server = net.createServer(function onconnection(conn) { |
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.
Nit: s/onconnection/onConnection
doc/api/async_hooks.md
Outdated
// MakeCallback(). | ||
async_hooks.currentId(); | ||
|
||
}).listen(port, function onlistening() { |
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.
Nit: s/onlistening/onListening
doc/api/async_hooks.md
Outdated
|
||
* `triggerId` {number} | ||
* `callback` {Function} | ||
* Returns {Undefined} |
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.
All types should be lower cased. I saw Undefined, String, Object and 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.
All types? Getting mixed info here. I was told elsewhere only primitive types.
For now I lowercased Undefined
and String
as requested above.
Going to wait for clarification here until I lower case more.
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.
A nit. This also needs a summary at the top, as it's a long document.
`${type}(${id}): trigger: ${triggerId} scope: ${cId}`); | ||
}, | ||
before (id) { | ||
process._rawDebug(' '.repeat(ws) + 'before: ', id); |
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.
it's not explained why we need to use _rawDebug
here.
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.
It's also not explained how to get the data out of the app process in general. If I want to send it across network or push to a database, all I can do is disable hooks and enable them back, but that has a potential of dropping a lot of information in meantime, so _rawDebug seems the only option to get any information out of async hooks.
Could this be addressed head-on in the docs?
If not, we should document practical use cases for this. All synchronous APIs can be used, but there's not a lot of them left.
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.
There is the option of not allowing any async hooks to execute while one of its own hooks is running. That should be the most straight forward approach, but we'd also loose information about what's happening during hook execution. If that's a fine trade then I can whip up the patch.
FYI: Reason process._rawDebug()
needs to be used is because it writes directly to stderr
. A similar effect would be to do fs.writeSync(2, 'foo');
. Otherwise init
will be called and cause a circular call to the hooks. Causing the application to crash.
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.
We all know why rawDebug is required, but the doc should mention that.
I'm not sure if disabling hooks while one is running is a good idea because you probably can't guarantee other parts of the app won't get executed between async calls of hook callback.
But without that we need to educate everyone they can only use sync writes (and make their hooks slow down other stuff).
Would it be possible to expose an API to push items to a queue that would then be offloaded somewhere on a background thread? I expect people will want to send hook results out live as means of debugging their code.
Pushing custom trave events from hooks might also be a thing.
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.
Oh, unless you mean not running hooks if a hook callback is one of the parents in callstack, which seems like a good solution to all the issues with sending out data.
Hooks code can be diagnosed with profiling and flamegraphs still, so that's not much of an issue.
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.
@trevnorris would that just be in the current tick or for the full context?
async_hooks.createHooks({
init() {
setImmediate(() => setImmediate(() => /* does this fire hooks */));
}
})
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.
What @AndreasMadsen asked ^^
It looks ok, but we'd need to be clear about what happens in the setImmediate()
case.
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.
I think an fs.writeSync(1, ...)
can be used in place of _rawDebug()
. People will want to play around with hooks and print things while gainining an understanding, so since console.log()
messes this up, perhaps an intro section is needed on this topic, describing the problem and a solution. It could show a safe "print" function using fs.writeSync as an example, and then that function could be used consistently throughout the other examples in the docs
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.
Sorry for the delay.
@AndreasMadsen @jasnell
would that just be in the current tick or for the full context?
That puts a swift end to my suggestion. I lapsed back to the previous implementation where all resources were tracked individually so each resource could omit firing its hooks.
I might suggest we add an API like async_hooks.log()
. Telling the user to fs.writeSync(1)
seems like something that enough people will need to do that we might as well codify it in the API.
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.
That puts a swift end to my suggestion. I lapsed back to the previous implementation where all resources were tracked individually so each resource could omit firing its hooks.
I had my suspicions :D
Something I have been thinking about is if two separate AsyncHook
instances both call an async operation. Sure they can know about their own and prevent an internal recursion, but I don't think they can prevent a recursion jumping between each other.
doc/api/async_hooks.md
Outdated
##### `init(id, type, triggerId, resource)` | ||
|
||
* `id` {number} a unique id for the async resource | ||
* `type` {String} the type of the async resource |
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.
String
, Undefined
should also be lowercase ;)
Thanks for all the feedback .. tied up mostly this week, but will get to it next week and try to fix all problems that were pointed out. |
The state is checked when unwinding, and the application will crash if it isn't called in the correct order. It will also crash if the user forgets to run
To clarify, do you mean In regards to As for the "Sensitive Embedder API", I'm not too attached at keeping it around but it will make it much easier for users to incorporate into existing code; rather than needing to inherit from In short, if the "Sensitive Embedder API" is left intact then I would be alright removing |
This makes sense. I am a little worried about if we got this right, but assuming so, replacing
I think there are plenty of cases where an experimental API couldn't be changed later. But more importantly, I think we will get much better feedback if we are lacking a feature, than if we have too many features. Nobody complains about too many features. For example, let's say that nobody uses the "Standalone JS API" (I think this is quite likely), then we will get no feedback and thus assume it is perfect. When we mark I would much rather have a clear indication that every part of the
I don't know what "Sensitive Embedder API" is, can we use the terminology from the EPS? There are two APIs:
I want to keep the "Standalone JS API" private for now. I don't think the "Standalone JS API" makes things easier, using: resource = new AsyncEvent();
resource.emitBefore(); is at least as easy as: id = async_hooks.newId();
async_hooks.emitInit(id);
async_hooks.emitBefore(id); |
Addressed all obvious nits, asked for clarification on others. If anyone has a fix for either of those (i.e. @trevnorris) please just provide me with a commit and I'll cherry-pick it onto here. Alternatively anyone who wants to help LMK and I'll add them as a collab to the repo with this branch. |
3108512
to
6cce6d2
Compare
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.
Mostly looks good to me, with a few grammar nits and suggestions.
|
||
The `async-hooks` module provides an API to register callbacks tracking the | ||
lifetime of asynchronous resources created inside a Node.js application. | ||
It can be accessed using `require('async-hooks')`. |
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.
These should be underscores (i.e. `async_hooks`
)
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.
Also, please move the require statement to it's own line for consistency with other docs. e.g.
It can be accessed using:
```js
const async_hooks = require('async_hooks');
Handles are a reference to a system resource. Some resources are a simple | ||
identifier. For example, file system handles are represented by a file | ||
descriptor. Other handles are represented by libuv as a platform abstracted | ||
struct, e.g. `uv_tcp_t`. Each handle can be continually reused to access and |
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.
Is anything described in the Some resources … uv_tcp_t
bit actually visible to users? I don’t think so, so I’d just drop it.
operate on the referenced resource. | ||
|
||
Requests are short lived data structures created to accomplish one task. The | ||
callback for a request should always and only ever fire one time. Which is when |
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.
one time. Which is
→ one time, which is
Registers functions to be called for different lifetime events of each async | ||
operation. | ||
The callbacks `init()`/`before()`/`after()`/`destroy()` are registered via an | ||
`AsyncHooks` instance and fire during the respective asynchronous events in the |
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.
AsyncHooks
→ AsyncHook
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.
fire -> "are called"?
--> | ||
|
||
* `callbacks` {Object} the callbacks to register | ||
|
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.
Can you add * Returns: {AsyncHook}
?
|
||
*Note:* Some resources depend on GC for cleanup. So if a reference is made to | ||
the `resource` object passed to `init()` it's possible that `destroy()` is | ||
never called. Causing a memory leak in the application. Of course if |
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.
never called. Causing a memory leak
→ never called, causing a memory leak
``` | ||
|
||
It is important to note that the id returned fom `currentId()` is related to | ||
execution timing. Not causality (which is covered by `triggerId()`). For |
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.
execution timing. Not causality
→ execution timing, not causality
|
||
```js | ||
const server = net.createServer(function onConnection(conn) { | ||
// Returns the id of the server, not of the new connection. Because the |
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.
the new connection. Because the
→ the new connection, because the
```js | ||
const server = net.createServer(function onConnection(conn) { | ||
// Returns the id of the server, not of the new connection. Because the | ||
// on connection callback runs in the execution scope of the server's |
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.
I’d drop on
, or spell it as onConnection
to match the code
If the user's callback throws an exception then `emitAfter()` will | ||
automatically be called for all `id`'s on the stack if the error is handled by | ||
a domain or `'uncaughtException'` handler. So there is no need to guard against | ||
this. |
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.
I’d drop this last sentence fragment, but if you keep it, please join it with a comma
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.
If this addresses my question about lack of try/catch above, it probably needs a bit more text, not less, to describe what will happen.
|
||
## Terminology | ||
|
||
An async resource represents either a _handle_ or a _request_. |
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.
s/_handle_
/*handle*
s/_request_
/*request*
the assigned task has either completed or encountered an error. Requests are | ||
used by handles to perform tasks such as accepting a new connection or | ||
writing data to disk. | ||
|
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.
Something should be described around here about how the async_hooks
API specifically relates to handles and requests
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.
It doesn't relate, in fact, it abstracts the two cases into the resource concept.
### Overview | ||
|
||
Following is a simple overview of the public API. All of this API is explained in | ||
more detail further down. |
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.
Just strike the second sentence here.
destroy: 5 | ||
``` | ||
|
||
First notice that `scope` and the value returned by `currentId()` are always |
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.
*Note*: As illustrated in the example, `currentId()` and `scope` each specify the value
of the current execution context; which is delineated by calls to `before()` and `after()`.
the same. That's because `currentId()` simply returns the value of the | ||
current execution context; which is defined by `before()` and `after()` calls. | ||
|
||
Now only using `scope` to graph resource allocation results in the following: |
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.
Remove the word Now
Can we keep it exposed but undocumented? Could even attach the functions to |
Yes, that is all I want. I have quite a lot of concerns about abuse, recently I got some new about setting the |
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.
Lots of great info here on a very large and subtle API, good work.
```js | ||
const async_hooks = require('async_hooks'); | ||
|
||
// Return the id of the current execution context. |
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.
"ID"?
function init(id, type, triggerId, resource) { } | ||
|
||
// before() is called just before the resource's callback is called. It can be | ||
// called 0-N times for handles (e.g. TCPWrap), and should be called exactly 1 |
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.
"should" -> "will", should implies a goal that may not always be achieved, I don't think that is the case here.
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.
Reason I said "should be" was to communicate at the time that since it's an experimental API there's a possibility that it may not be called, and if it isn't then there's a bug.
function before(id) { } | ||
|
||
// after() is called just after the resource's callback has finished. | ||
// This hook will not be called if an uncaught exception occurred. |
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.
occured where? in the async_hook callback? In the user's callback 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.
Also: Is this actually true? I have tried to reproduce this, but it’s all a bit tricky to see through. If it is true that after
won’t be called, I’d call that a bug? How would the hooks know that the execution context is exited in that case? @nodejs/diagnostics
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.
@addaleax that is left over documentation from a previous implementation. The after
callbacks should always be called.
|
||
// destroy() is called when an AsyncWrap instance is destroyed. In cases like | ||
// HTTPParser where the resource is reused, or timers where the handle is only | ||
// a JS object, destroy() will be triggered manually soon after after() has |
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.
JS->Javascript
|
||
// destroy() is called when an AsyncWrap instance is destroyed. In cases like | ||
// HTTPParser where the resource is reused, or timers where the handle is only | ||
// a JS object, destroy() will be triggered manually soon after after() has |
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.
"manually", this sounds like an imp detail, that you are saying that the core C++ won't call destroy(), but it will be arranged to be called by node's javascript code, but is that relevant to the user?
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.
I think with HTTPParser, the handle might be gone before destroy()
is actually invoked, so accessing the handle would cause problems. (So as to not call JS during a GC operation.)
If the user's callback throws an exception then `emitAfter()` will | ||
automatically be called for all `id`'s on the stack if the error is handled by | ||
a domain or `'uncaughtException'` handler. So there is no need to guard against | ||
this. |
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.
If this addresses my question about lack of try/catch above, it probably needs a bit more text, not less, to describe what will happen.
* Returns {undefined} | ||
|
||
Call all `destroy()` hooks. This should only ever be called once. An error will | ||
be thrown if it is called more than once. This **must** be manually called. If |
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.
as opposed to automatically called? What callbacks are called automatically?
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.
Some of our resource objects are destroyed automatically by the gc. Since they are implemented in C++ they actually call the destroy
callbacks appropriately.
|
||
* Returns {number} the unique `id` assigned to the resource. | ||
|
||
Useful when used with `triggerIdScope()`. |
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.
what is triggerIdScope()? should this be a link to something? is that a method on something? what?
|
||
#### `asyncEvent.triggerId()` | ||
|
||
* Returns {number} the same `triggerId` that is passed to `init()` hooks. |
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.
maybe "triggerId that was passed in the AsyncEvent constructor"?
The following API can be used as an alternative to using `AsyncEvent()`, but it | ||
is left to the embedder to manually track values needed for all emitted events | ||
(e.g. `id` and `triggerId`). It mainly exists for use in Node.js core itself and | ||
it is highly recommended that embedders instead use `AsyncEvent`. |
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 do we doc it? does it have a use-case? is there some rare thing it can be used for that the AsyncEvent API cannot be used for? Why don't we use the AsyncEvent API in node core? If its for efficiency, it seems worrying that we are suggesting user-land use an API that we won't use in node core.
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.
The low-level Embedder API is no longer included in the documentation.
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.
As requested here is the commit resolving the "Standalone JS Embedder API" discussion. Agreement with @trevnorris was that we will keep the API but not document it. Hopefully, we can get a better idea of what is needed from userland.
- [squash] remove standalone JS Embedder API docs: 2a79a9b735f79bd1f7eef98073ce88e5c014e134
As a bonus, we renamed AsyncEvent
to AsyncResource
, here is a commit that updates the documentation:
- [squash] AsyncEvent is renamed to AsyncResource: 482fccf30dd57ff2a0fa9dd4ba32cc7ba20cf56e
PS: do we plan to add documentation for the C++ Embedder API in this PR?
I would say “no”, at least for the Just as a data point, we don’t document the current |
I'm going through all the reviews. I'm adding a ❤️ to everything I have seen, I will make an updated PR shortly. |
The new PR is in #13287, please review. |
Thanks @AndreasMadsen should I close this one then? |
Sure, we can reopen if I suddenly don't respond. |
Continuation of ongoing PR to add documentation for the async hooks feature which was merged recently.
The existing commits in the previous PR have been cherry-picked onto latest master.
I suggest to work out all nits and finally squash this into one proper commit.
Checklist
Affected core subsystem(s)