Context lost when awaiting on custom thenable
vkarpov15 opened this issue · comments
Not sure if this is an issue or expected behavior, but figured I'd ask. I've been tracking down a bug with mongoose and express-http-context, and found that if you use await
with a custom then()
function, context goes away. Here's an example:
const clsHooked = require('cls-hooked');
const session = clsHooked.createNamespace('mytest');
session.run(() => {
run().catch(err => console.log(err));
});
async function run() {
session.set('test', '42');
const thenable = {
then: (resolve, reject) => {
console.log('Session', session.get('test')); // undefined
return Promise.resolve('').then(resolve, reject);
}
};
await thenable; // This is the problem, context gets lost in `then()`
// This works fine
await new Promise((resolve, reject) => {
console.log('Session2', session.get('test')); // 42
});
}
Any ideas as to what might be going on here?
@vkarpov15 ! Sorry I haven't gotten to this. I'm a little fuzzy on what mongoose's exec()
does under the hood but my first thought is that a custom then()
would need to be wrapped similar to how cls-bluebird does it.
This is caused by an issue in Node where the context is restored by the Promise class and not the await
language construct which is handled within v8.
@Jeff-Lewis I've been looking more into this issue and found something you might find interesting: this issue only happens with run()
. It works fine as long as you wrap your async function with runPromise()
as shown below.
const clsHooked = require('cls-hooked');
const session = clsHooked.createNamespace('mytest');
session.runPromise(run);
async function run() {
session.set('test', '42');
const thenable = {
then: (resolve, reject) => {
console.log('Session', session.get('test')); // undefined
return Promise.resolve('').then(resolve, reject);
}
};
await thenable; // This is the problem, context gets lost in `then()`
// This works fine
await new Promise((resolve, reject) => {
console.log('Session2', session.get('test')); // 42
});
}
It seems like this only happens if you start using async functions inside of run()
rather than runPromise()
.
@vkarpov15 If your issue is caused by the bug in Node, it should be fixed by this PR in ^12.19.0 || >=14.5.0
.