-
Notifications
You must be signed in to change notification settings - Fork 29.6k
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
async generators do not capture async context #42237
Comments
@devsnek is this v8 not firing the right promise hooks or on our side (or you haven't had a chance to investigate yet)? |
I'm not sure. |
Should async generators capture the async context? |
i dunno... its technically an abstraction that's outside of promises, but in terms of the usage of apis like AsyncLocalStorage, i think i would expect hooks to apply to them. |
If the generator would capture the id where it was created everything after |
Are you missing the yield keyword, I can't find it Your using a generator |
User expectation would probably be "yes" |
Using inspiration from open-telemetry/opentelemetry-js#2951 (comment), I was able to build a generic wrapper to work around this issue in the mean time. export function bindAsyncGenerator<T = unknown, TReturn = any, TNext = unknown>(
store: AsyncLocalStorage<unknown>,
generator: AsyncGenerator<T, TReturn, TNext>,
): AsyncGenerator<T, TReturn, TNext> {
const ctx = store.getStore();
return {
next: () => store.run(ctx, generator.next.bind(generator)),
return: (args) => store.run(ctx, generator.return.bind(generator), args),
throw: (args) => store.run(ctx, generator.throw.bind(generator), args),
[Symbol.asyncIterator]() {
return this;
},
};
} |
cc @nodejs/tsc who would have the most information to resolve this bug? |
I think @bengl can coordinate this. |
FWIW there is an ongoing discussion in scope of TC39 AsyncContext proposal regarding the same topic. |
Got this problem when I was writing logging middleware for nice-grpc server. Middleware: export default function loggingMiddleware(logger: ILogger) {
return async function* <Request, Response>(
call: ServerMiddlewareCall<Request, Response>,
context: CallContext,
) {
const someId = context.metadata.get("some-id");
return yield* withContext({ someId }, async function* () {
try {
return yield* call.next(call.request, context);
} catch (err) {
// ...
throw err;
}
});
};
} In import store from "path/to/AsyncLocalStorage/instance";
type TStoreData = {
someId: string;
}
export function withContext<T>(storeData: TStoreData, callback: () => T): T {
store.enterWith(storeData);
return store.run(storeData, callback);
} Now, I have access to data in storage in my Let me know if there is a better way. |
tested on v17 but i don't suspect that matters much.
output:
/cc @nodejs/async_hooks
i'm assuming this probably will need some sort of effort on the v8 side?
The text was updated successfully, but these errors were encountered: