Skip to content

AsyncLocalStorage stub silently drops async context — emit shim diagnostic on async_hooks import #775

@proggeramlug

Description

@proggeramlug

Background

PR #754 added a structural stub for node:async_hooks (crates/perry-jsruntime/src/modules.rs) so @nestjs/core's context-bind path could compile. The stub provides AsyncResource, AsyncLocalStorage, executionAsyncId, and createHook shapes — enough that NestJS's bootstrap doesn't crash — but with no real async-context tracking. From the fixture's WALLS.md:

The bind/runInAsyncScope shape is enough for the NestJS code path; no real async-context tracking yet.

This is the same silent-failure shape that PR #754's review item 2a was solving for reflect-metadata: a polyfill the user import-ed turns out not to be the polyfill they expected. Anything that relies on AsyncLocalStorage for context propagation will compile, run, and silently lose context:

  • Sentry's request-scoped error context
  • OpenTelemetry's distributed-trace propagation
  • NestJS request-scoped providers (@Injectable({ scope: Scope.REQUEST })) once the rest of the stack lights up
  • pino-style child loggers bound to a request

Suggested fix

Mirror the 2a solution — emit a one-shot [perry] note: to stderr at compile time when async_hooks (or node:async_hooks) is imported, listing the implemented surface and explicitly stating that AsyncLocalStorage.run() does not propagate context across await/setImmediate/process.nextTick boundaries. That way users get the warning at compile time rather than discovering missing trace context in production.

Same AtomicBool::swap one-shot pattern as emit_reflect_metadata_shim_note() in crates/perry-hir/src/lower.rs.

Longer-term

Real async-context tracking via tokio task_local! (or equivalent through Perry's promise/microtask scheduler) is the proper fix, but it's a substantial piece of work. The compile-time note is the minimum-viable mitigation that keeps the silent-failure surface from growing.

Related

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions