Search code examples
javascriptdenoasync-hooks

Does Deno have a Way to Track Async Contexts?


Speaking broadly, in NodeJS a program creates "an async context" whenever code runs that creates a callback-to-be-run-later via the Event Loop or the microtask queue. Network requests, setTimeout callbacks, Promises, etc.

In modern versions of NodeJs you have the (still experimental) async_hooks module to track the lifecycle of these asynchronous resources.

Previous versions of NodeJS had the now deprecated process.addAsyncListener -- kept alive by the async-listener polyfill package.

Does Deno have any built-in or third party functionality that allows userland code to track the creation of these asynchronous contexts? Or is there something about how Deno works that makes this an irrelevant concept?


Solution

  • I don't think such functionality is publicly available at this moment or through 3rd party modules.

    Briefly looked into the functionality async_hooks provide (might miss something important, please correct me), it seems that init and promiseResolve are more like the interesting ones in Deno (Deno hardly uses callbacks in its APIs).

    The way Deno does privileged operations is by sending serialized text message (mostly JSON) and zero-copy buffers to the Rust side, and it receives messages from Rust side when Rust side invokes a callback with response messages. It would be interesting if we can intercept some of them by adding a small wrapping listener to some of the core message channel methods, e.g. Deno.core.dispatchByName (this one is used by almost all Deno privileged operations, async or sync. There are a lot of interesting other things available on Deno.core, see core/core.js in source. Somehow handleAsyncMsgFromRust which receives async messages from Rust is not exposed though).

    Unfortunately Deno.core is currently frozen (actually I was the one responsible for this change) to avoid overwrite (such can cause hard crashes on upgrade as Deno.core hosts critical yet volatile internal API). Probably you could open an issue in the Deno repo to ask if others would like to implement some interface to allow user inject message-capturing callbacks to conceptual send and recv methods. (I am currently unable to contribute)