async_hooks: add hook to stop propagation

Add hook to AsyncLocalStorage to allow user to stop propagation.
This is needed to avoid leaking a store if e.g. the store indicates
that its operations are finished or it reached its time to live.

PR-URL: https://github.com/nodejs/node/pull/45386
Reviewed-By: Stephen Belanger <admin@stephenbelanger.com>
Reviewed-By: Minwoo Jung <nodecorelab@gmail.com>
Reviewed-By: Chengzhong Wu <legendecas@gmail.com>
This commit is contained in:
Gerhard Stöbich 2022-11-15 13:27:03 +01:00 committed by GitHub
parent 0a592e48a0
commit 67d1831e9b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 89 additions and 5 deletions

View file

@ -18,6 +18,7 @@ const {
const {
ERR_ASYNC_CALLBACK,
ERR_ASYNC_TYPE,
ERR_INVALID_ARG_TYPE,
ERR_INVALID_ASYNC_ID
} = require('internal/errors').codes;
const { kEmptyObject } = require('internal/util');
@ -268,15 +269,27 @@ const storageHook = createHook({
const currentResource = executionAsyncResource();
// Value of currentResource is always a non null object
for (let i = 0; i < storageList.length; ++i) {
storageList[i]._propagate(resource, currentResource);
storageList[i]._propagate(resource, currentResource, type);
}
}
});
class AsyncLocalStorage {
constructor() {
constructor(options = kEmptyObject) {
if (typeof options !== 'object' || options === null) {
throw new ERR_INVALID_ARG_TYPE('options', 'Object', options);
}
const { onPropagate = null } = options;
if (onPropagate !== null && typeof onPropagate !== 'function') {
throw new ERR_INVALID_ARG_TYPE('options.onPropagate',
'function',
onPropagate);
}
this.kResourceStore = Symbol('kResourceStore');
this.enabled = false;
this._onPropagate = onPropagate;
}
disable() {
@ -300,10 +313,12 @@ class AsyncLocalStorage {
}
// Propagate the context from a parent resource to a child one
_propagate(resource, triggerResource) {
_propagate(resource, triggerResource, type) {
const store = triggerResource[this.kResourceStore];
if (this.enabled) {
resource[this.kResourceStore] = store;
if (this._onPropagate === null || this._onPropagate(type, store)) {
resource[this.kResourceStore] = store;
}
}
}