Jeff-Lewis / cls-hooked

cls-hooked : CLS using AsynWrap or async_hooks instead of async-listener for node 4.7+

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

session lost when call promise-like function

myfjdthink opened this issue · comments

Hi there,

I found that cls session was lost when execute promise-like(not really promise object, just have a then property) function ,see the below code example。

var createNamespace = require('cls-hooked').createNamespace;
var session = createNamespace('my session');
var async_hooks = require('async_hooks');

async function main () {
  const fake = new Fake()
  const result = await fake.query(233)    // not work, function end  session.get('user') is undefined
  // const result = await util.promisify(fake.query)(233) // work, session.get('user') is 'flag'
  // const result = await fake.query(233).then()  // work

  console.log('result ', result, '\n')
}

function Fake () {
  // empty
}

Fake.prototype.query = function (ct) {
  this.ct = ct
  console.log('session user :', session.get('user'))
  console.log('query asyncId :', async_hooks.executionAsyncId(), async_hooks.triggerAsyncId())
  console.log('set query ct', ct, '\n')
  return this
}

Fake.prototype.end = function (callback) {
  const self = this
  setTimeout(function () {
    console.log('session user :', session.get('user'))
    console.log('end asyncId :', async_hooks.executionAsyncId(), async_hooks.triggerAsyncId())
    console.log('do query ', self.ct, '\n')
    callback(self.ct)
  })
}

Fake.prototype.then = function then (resolve, reject) {
  const self = this
  let promise = new Promise(function (innerResolve) {
    self.end(innerResolve)
  })
  return promise.then(resolve, reject)
}

session.run(function () {
  session.set('user', 'flag')
  console.log('main asyncId :', async_hooks.executionAsyncId(), async_hooks.triggerAsyncId(), '\n')
  main().then()
})

change await fake.query(233) to await fake.query(233).then() seems can solve the problem,but I don't want to modify in all places, Is there other way to solve the problem?

superagent was support promise like the above code example, so when I try to trace seesion in superagent's http-client, I got this problem.
see https://github.com/visionmedia/superagent/blob/c2f65c665cf1738c5ed8f31c9d255f0a0afa70b2/lib/request-base.js#L231

From looking at your mongoose tracer bug, it appears you've seen how user-land queueing can still break any cls. See my request for Mongoose to implement async_hook's Async Hooks Embedder API.

OK, I got it, Thanks a lot.