Skip to content

The store when using enterWith/exitWith in asyncLocalStorage is not "stacked" #36683

@giltayar

Description

@giltayar
  • Version: 15.5.0
  • Platform: MacOS
  • Subsystem: async_hooks

What steps will reproduce the bug?

I expected the following program to work:

import {AsyncLocalStorage} from 'async_hooks'
import assert from 'assert'

const asyncLocalStorage = new AsyncLocalStorage()

// This section works nicely: the store is "stacked"
asyncLocalStorage.run({depth: 1}, () => {
  assert.deepStrictEqual(asyncLocalStorage.getStore(), {depth: 1})

  asyncLocalStorage.run({depth: 2}, () => {
    assert.deepStrictEqual(asyncLocalStorage.getStore(), {depth: 2})
  })

  assert.deepStrictEqual(asyncLocalStorage.getStore(), {depth: 1})
})

// This section how when using enterWith/exit the store is not stacked
asyncLocalStorage.enterWith({depth: 1})
assert.deepStrictEqual(asyncLocalStorage.getStore(), {depth: 1})

asyncLocalStorage.enterWith({depth: 2})
assert.deepStrictEqual(asyncLocalStorage.getStore(), {depth: 2})

asyncLocalStorage.exit(() => {
  // **** this fails because the store returns undefined
  assert.deepStrictEqual(asyncLocalStorage.getStore(), {depth: 1})

  asyncLocalStorage.exit(() => {
    assert.deepStrictEqual(asyncLocalStorage.getStore(), undefined)
  })
})

assert.deepStrictEqual(asyncLocalStorage.getStore(), {depth: 2})

But it fails in the line after the marked ****. The reason I expected it to work is because I assumed that enter/exit has the same "stacked" semantics as run, in that entering twice and exiting once will give me the store of the first enter. Unfortunately, the store I get after the first exit is undefined.

How often does it reproduce? Is there a required condition?

Consistent. Always.

What is the expected behavior?

The program should pass without error. See above for why.

What do you see instead?

A failure of the code:

node:internal/process/esm_loader:74
    internalBinding('errors').triggerUncaughtException(
                              ^

AssertionError [ERR_ASSERTION]: Expected values to be strictly deep-equal:
+ actual - expected

+ undefined
- {
-   depth: 1
- }
    at file:///Users/giltayar/code/mono/packages/request-id-logger-fastify-plugin/src/foo.js:26:10
    at AsyncLocalStorage.exit (node:async_hooks:323:14)
    at file:///Users/giltayar/code/mono/packages/request-id-logger-fastify-plugin/src/foo.js:24:19
    at ModuleJob.run (node:internal/modules/esm/module_job:152:23)
    at async Loader.import (node:internal/modules/esm/loader:166:24)
    at async Object.loadESM (node:internal/process/esm_loader:68:5) {
  generatedMessage: true,
  code: 'ERR_ASSERTION',
  actual: undefined,
  expected: { depth: 1 },
  operator: 'deepStrictEqual'
}

Additional information

This also fails in v14.15.1

Metadata

Metadata

Assignees

No one assigned

    Labels

    async_hooksIssues and PRs related to the async hooks subsystem.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions