-
-
Notifications
You must be signed in to change notification settings - Fork 34.9k
Description
Affected URL(s)
https://nodejs.org/api/async_hooks.html#async-hooks
Description of the problem
We're building an emulation tool for workerd's event loop / async resource isolation that aims to be similar in intention. In workerd (or Cloudflare Workers) they track both the event loop for each incoming request and resources it creates.
If the work per request cannot complete workerd issues as "Will never generate a response" error, see: https://developers.cloudflare.com/workers/observability/errors/#the-script-will-never-generate-a-response-errors
The cause of this is a bit abstract and separate from the intention;
- Possible causes: For example, two requests share a
new Promise, one request is cancelled, hence, the other can never resolve - General intention: Each request is isolated and shouldn't share async resources with another to guarantee that requests cannot stall (and presumably so requests can eventually more strongly be isolated; this does in theory prevent future bugs)
- Implementation detail: As far as I'm aware, this is tracked by checking the event loop. If any request runs out of pending async tasks/resources, it has created/owns, and hasn't resolved, then this error is thrown
This creates a developer experience problem. Not only is it hard to emulate this exact check accurately (as far as I'm aware), it's hard to track why this error is thrown. In development for Expo, we'd instead like to track async resources and proactively create rules that emulate this behaviour while delivering more information on where or why the violation of a rule has occurred.
Long story short: The proof of concept code for this uses async_hooks's createHook with a small graph that attempts to keep track of where async resources are created and resolved: https://github.com/kitten/fiber-dev
The tests show which rules we'd like to enforce:
- async resources created outside an isolated function shouldn't be used within
- async resources created in one isolated function shouldn't be used within another
- stalling async resources (e.g. unresolved promises) should lead to an error
While this slows things down marginally, it's useful to deliver more useful errors in development, before users take their server-side code to workerd in production.