Skip to content
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_hooks: add sync enterWith to async storage #31945

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
42 changes: 42 additions & 0 deletions doc/api/async_hooks.md
Expand Up @@ -950,6 +950,48 @@ If this method is called outside of an asynchronous context initialized by
calling `asyncLocalStorage.run` or `asyncLocalStorage.runAndReturn`, it will
return `undefined`.

### `asyncLocalStorage.enterWith(store)`
<!-- YAML
added: REPLACEME
-->

* `store` {any}

Calling `asyncLocalStorage.enterWith(store)` will transition into the context
for the remainder of the current synchronous execution and will persist
through any following asynchronous calls.

Example:

```js
const store = { id: 1 };
asyncLocalStorage.enterWith(store);
asyncLocalStorage.getStore(); // Returns the store object
someAsyncOperation(() => {
asyncLocalStorage.getStore(); // Returns the same object
});
```

This transition will continue for the _entire_ synchronous execution.
Qard marked this conversation as resolved.
Show resolved Hide resolved
This means that if, for example, the context is entered within an event
handler subsequent event handlers will also run within that context unless
Qard marked this conversation as resolved.
Show resolved Hide resolved
specifically bound to another context with an `AsyncResource`.

vdeturckheim marked this conversation as resolved.
Show resolved Hide resolved
```js
const store = { id: 1 };

emitter.on('my-event', () => {
asyncLocalStorage.enterWith(store);
});
emitter.on('my-event', () => {
asyncLocalStorage.getStore(); // Returns the same object
});

asyncLocalStorage.getStore(); // Returns undefined
emitter.emit('my-event');
asyncLocalStorage.getStore(); // Returns the same object
vdeturckheim marked this conversation as resolved.
Show resolved Hide resolved
```

### `asyncLocalStorage.run(store, callback[, ...args])`
<!-- YAML
added: v13.10.0
Expand Down
6 changes: 3 additions & 3 deletions lib/async_hooks.js
Expand Up @@ -245,7 +245,7 @@ class AsyncLocalStorage {
}
}

_enter(store) {
enterWith(store) {
if (!this.enabled) {
this.enabled = true;
storageList.push(this);
Expand All @@ -258,7 +258,7 @@ class AsyncLocalStorage {
runSyncAndReturn(store, callback, ...args) {
const resource = executionAsyncResource();
const outerStore = resource[this.kResourceStore];
this._enter(store);
this.enterWith(store);
try {
return callback(...args);
} finally {
Expand Down Expand Up @@ -288,7 +288,7 @@ class AsyncLocalStorage {
run(store, callback, ...args) {
const resource = executionAsyncResource();
const outerStore = resource[this.kResourceStore];
this._enter(store);
this.enterWith(store);
process.nextTick(callback, ...args);
resource[this.kResourceStore] = outerStore;
}
Expand Down
20 changes: 20 additions & 0 deletions test/async-hooks/test-async-local-storage-enter-with.js
@@ -0,0 +1,20 @@
'use strict';
require('../common');
const assert = require('assert');
const { AsyncLocalStorage } = require('async_hooks');

const asyncLocalStorage = new AsyncLocalStorage();

setImmediate(() => {
const store = { foo: 'bar' };
asyncLocalStorage.enterWith(store);

assert.strictEqual(asyncLocalStorage.getStore(), store);
setTimeout(() => {
assert.strictEqual(asyncLocalStorage.getStore(), store);
}, 10);
});

setTimeout(() => {
assert.strictEqual(asyncLocalStorage.getStore(), undefined);
}, 10);