@midwayjs/async-hooks-context-manager 3.4.0-beta.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +9 -0
- package/dist/asyncHooksContextManager.d.ts +49 -0
- package/dist/asyncHooksContextManager.js +140 -0
- package/dist/asyncLocalStorageContextManager.d.ts +17 -0
- package/dist/asyncLocalStorageContextManager.js +70 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +23 -0
- package/dist/util.d.ts +5 -0
- package/dist/util.js +36 -0
- package/package.json +34 -0
package/README.md
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { AsyncContext, AsyncContextManager } from '@midwayjs/core';
|
|
2
|
+
export declare class AsyncHooksContextManager implements AsyncContextManager {
|
|
3
|
+
private _asyncHook;
|
|
4
|
+
private _contexts;
|
|
5
|
+
private _stack;
|
|
6
|
+
constructor();
|
|
7
|
+
active(): AsyncContext;
|
|
8
|
+
with<A extends unknown[], F extends (...args: A) => ReturnType<F>>(context: AsyncContext, fn: F, thisArg?: ThisParameterType<F>, ...args: A): ReturnType<F>;
|
|
9
|
+
enable(): this;
|
|
10
|
+
disable(): this;
|
|
11
|
+
/**
|
|
12
|
+
* Init hook will be called when userland create a async context, setting the
|
|
13
|
+
* context as the current one if it exist.
|
|
14
|
+
* @param uid id of the async context
|
|
15
|
+
* @param type the resource type
|
|
16
|
+
*/
|
|
17
|
+
private _init;
|
|
18
|
+
/**
|
|
19
|
+
* Destroy hook will be called when a given context is no longer used so we can
|
|
20
|
+
* remove its attached context.
|
|
21
|
+
* @param uid uid of the async context
|
|
22
|
+
*/
|
|
23
|
+
private _destroy;
|
|
24
|
+
/**
|
|
25
|
+
* Before hook is called just before executing a async context.
|
|
26
|
+
* @param uid uid of the async context
|
|
27
|
+
*/
|
|
28
|
+
private _before;
|
|
29
|
+
/**
|
|
30
|
+
* After hook is called just after completing the execution of a async context.
|
|
31
|
+
*/
|
|
32
|
+
private _after;
|
|
33
|
+
/**
|
|
34
|
+
* Set the given context as active
|
|
35
|
+
*/
|
|
36
|
+
private _enterContext;
|
|
37
|
+
/**
|
|
38
|
+
* Remove the context at the root of the stack
|
|
39
|
+
*/
|
|
40
|
+
private _exitContext;
|
|
41
|
+
/**
|
|
42
|
+
* Binds a the certain context or the active one to the target function and then returns the target
|
|
43
|
+
* @param context A context (span) to be bind to target
|
|
44
|
+
* @param target a function. When target or one of its callbacks is called,
|
|
45
|
+
* the provided context will be used as the active context for the duration of the call.
|
|
46
|
+
*/
|
|
47
|
+
bind<T>(context: AsyncContext, target: T): T;
|
|
48
|
+
}
|
|
49
|
+
//# sourceMappingURL=asyncHooksContextManager.d.ts.map
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/*
|
|
3
|
+
* Copyright The OpenTelemetry Authors
|
|
4
|
+
*
|
|
5
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
* you may not use this file except in compliance with the License.
|
|
7
|
+
* You may obtain a copy of the License at
|
|
8
|
+
*
|
|
9
|
+
* https://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
*
|
|
11
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
* See the License for the specific language governing permissions and
|
|
15
|
+
* limitations under the License.
|
|
16
|
+
*/
|
|
17
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18
|
+
exports.AsyncHooksContextManager = void 0;
|
|
19
|
+
const core_1 = require("@midwayjs/core");
|
|
20
|
+
const asyncHooks = require("async_hooks");
|
|
21
|
+
class AsyncHooksContextManager {
|
|
22
|
+
constructor() {
|
|
23
|
+
this._contexts = new Map();
|
|
24
|
+
this._stack = [];
|
|
25
|
+
this._asyncHook = asyncHooks.createHook({
|
|
26
|
+
init: this._init.bind(this),
|
|
27
|
+
before: this._before.bind(this),
|
|
28
|
+
after: this._after.bind(this),
|
|
29
|
+
destroy: this._destroy.bind(this),
|
|
30
|
+
promiseResolve: this._destroy.bind(this),
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
active() {
|
|
34
|
+
var _a;
|
|
35
|
+
return (_a = this._stack[this._stack.length - 1]) !== null && _a !== void 0 ? _a : core_1.ASYNC_ROOT_CONTEXT;
|
|
36
|
+
}
|
|
37
|
+
with(context, fn, thisArg, ...args) {
|
|
38
|
+
this._enterContext(context);
|
|
39
|
+
try {
|
|
40
|
+
return fn.call(thisArg, ...args);
|
|
41
|
+
}
|
|
42
|
+
finally {
|
|
43
|
+
this._exitContext();
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
enable() {
|
|
47
|
+
this._asyncHook.enable();
|
|
48
|
+
return this;
|
|
49
|
+
}
|
|
50
|
+
disable() {
|
|
51
|
+
this._asyncHook.disable();
|
|
52
|
+
this._contexts.clear();
|
|
53
|
+
this._stack = [];
|
|
54
|
+
return this;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Init hook will be called when userland create a async context, setting the
|
|
58
|
+
* context as the current one if it exist.
|
|
59
|
+
* @param uid id of the async context
|
|
60
|
+
* @param type the resource type
|
|
61
|
+
*/
|
|
62
|
+
_init(uid, type) {
|
|
63
|
+
// ignore TIMERWRAP as they combine timers with same timeout which can lead to
|
|
64
|
+
// false context propagation. TIMERWRAP has been removed in node 11
|
|
65
|
+
// every timer has it's own `Timeout` resource anyway which is used to propagete
|
|
66
|
+
// context.
|
|
67
|
+
if (type === 'TIMERWRAP')
|
|
68
|
+
return;
|
|
69
|
+
const context = this._stack[this._stack.length - 1];
|
|
70
|
+
if (context !== undefined) {
|
|
71
|
+
this._contexts.set(uid, context);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Destroy hook will be called when a given context is no longer used so we can
|
|
76
|
+
* remove its attached context.
|
|
77
|
+
* @param uid uid of the async context
|
|
78
|
+
*/
|
|
79
|
+
_destroy(uid) {
|
|
80
|
+
this._contexts.delete(uid);
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Before hook is called just before executing a async context.
|
|
84
|
+
* @param uid uid of the async context
|
|
85
|
+
*/
|
|
86
|
+
_before(uid) {
|
|
87
|
+
const context = this._contexts.get(uid);
|
|
88
|
+
if (context !== undefined) {
|
|
89
|
+
this._enterContext(context);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* After hook is called just after completing the execution of a async context.
|
|
94
|
+
*/
|
|
95
|
+
_after() {
|
|
96
|
+
this._exitContext();
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Set the given context as active
|
|
100
|
+
*/
|
|
101
|
+
_enterContext(context) {
|
|
102
|
+
this._stack.push(context);
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Remove the context at the root of the stack
|
|
106
|
+
*/
|
|
107
|
+
_exitContext() {
|
|
108
|
+
this._stack.pop();
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Binds a the certain context or the active one to the target function and then returns the target
|
|
112
|
+
* @param context A context (span) to be bind to target
|
|
113
|
+
* @param target a function. When target or one of its callbacks is called,
|
|
114
|
+
* the provided context will be used as the active context for the duration of the call.
|
|
115
|
+
*/
|
|
116
|
+
bind(context, target) {
|
|
117
|
+
if (typeof target === 'function') {
|
|
118
|
+
// eslint-disable-next-line @typescript-eslint/no-this-alias
|
|
119
|
+
const manager = this;
|
|
120
|
+
const contextWrapper = function (...args) {
|
|
121
|
+
return manager.with(context, () => target.apply(this, args));
|
|
122
|
+
};
|
|
123
|
+
Object.defineProperty(contextWrapper, 'length', {
|
|
124
|
+
enumerable: false,
|
|
125
|
+
configurable: true,
|
|
126
|
+
writable: false,
|
|
127
|
+
value: target.length,
|
|
128
|
+
});
|
|
129
|
+
/**
|
|
130
|
+
* It isn't possible to tell Typescript that contextWrapper is the same as T
|
|
131
|
+
* so we forced to cast as any here.
|
|
132
|
+
*/
|
|
133
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
134
|
+
return contextWrapper;
|
|
135
|
+
}
|
|
136
|
+
return target;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
exports.AsyncHooksContextManager = AsyncHooksContextManager;
|
|
140
|
+
//# sourceMappingURL=asyncHooksContextManager.js.map
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { AsyncContext, AsyncContextManager } from '@midwayjs/core';
|
|
2
|
+
export declare class AsyncLocalStorageContextManager implements AsyncContextManager {
|
|
3
|
+
private _asyncLocalStorage;
|
|
4
|
+
constructor();
|
|
5
|
+
active(): AsyncContext;
|
|
6
|
+
with<A extends unknown[], F extends (...args: A) => ReturnType<F>>(context: AsyncContext, fn: F, thisArg?: ThisParameterType<F>, ...args: A): ReturnType<F>;
|
|
7
|
+
enable(): this;
|
|
8
|
+
disable(): this;
|
|
9
|
+
/**
|
|
10
|
+
* Binds a the certain context or the active one to the target function and then returns the target
|
|
11
|
+
* @param context A context (span) to be bind to target
|
|
12
|
+
* @param target a function. When target or one of its callbacks is called,
|
|
13
|
+
* the provided context will be used as the active context for the duration of the call.
|
|
14
|
+
*/
|
|
15
|
+
bind<T>(context: AsyncContext, target: T): T;
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=asyncLocalStorageContextManager.d.ts.map
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/*
|
|
3
|
+
* Copyright The OpenTelemetry Authors
|
|
4
|
+
*
|
|
5
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
* you may not use this file except in compliance with the License.
|
|
7
|
+
* You may obtain a copy of the License at
|
|
8
|
+
*
|
|
9
|
+
* https://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
*
|
|
11
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
* See the License for the specific language governing permissions and
|
|
15
|
+
* limitations under the License.
|
|
16
|
+
*/
|
|
17
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18
|
+
exports.AsyncLocalStorageContextManager = void 0;
|
|
19
|
+
const core_1 = require("@midwayjs/core");
|
|
20
|
+
const async_hooks_1 = require("async_hooks");
|
|
21
|
+
class AsyncLocalStorageContextManager {
|
|
22
|
+
constructor() {
|
|
23
|
+
this._asyncLocalStorage = new async_hooks_1.AsyncLocalStorage();
|
|
24
|
+
}
|
|
25
|
+
active() {
|
|
26
|
+
var _a;
|
|
27
|
+
return (_a = this._asyncLocalStorage.getStore()) !== null && _a !== void 0 ? _a : core_1.ASYNC_ROOT_CONTEXT;
|
|
28
|
+
}
|
|
29
|
+
with(context, fn, thisArg, ...args) {
|
|
30
|
+
const cb = thisArg == null ? fn : fn.bind(thisArg);
|
|
31
|
+
return this._asyncLocalStorage.run(context, cb, ...args);
|
|
32
|
+
}
|
|
33
|
+
enable() {
|
|
34
|
+
return this;
|
|
35
|
+
}
|
|
36
|
+
disable() {
|
|
37
|
+
this._asyncLocalStorage.disable();
|
|
38
|
+
return this;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Binds a the certain context or the active one to the target function and then returns the target
|
|
42
|
+
* @param context A context (span) to be bind to target
|
|
43
|
+
* @param target a function. When target or one of its callbacks is called,
|
|
44
|
+
* the provided context will be used as the active context for the duration of the call.
|
|
45
|
+
*/
|
|
46
|
+
bind(context, target) {
|
|
47
|
+
if (typeof target === 'function') {
|
|
48
|
+
// eslint-disable-next-line @typescript-eslint/no-this-alias
|
|
49
|
+
const manager = this;
|
|
50
|
+
const contextWrapper = function (...args) {
|
|
51
|
+
return manager.with(context, () => target.apply(this, args));
|
|
52
|
+
};
|
|
53
|
+
Object.defineProperty(contextWrapper, 'length', {
|
|
54
|
+
enumerable: false,
|
|
55
|
+
configurable: true,
|
|
56
|
+
writable: false,
|
|
57
|
+
value: target.length,
|
|
58
|
+
});
|
|
59
|
+
/**
|
|
60
|
+
* It isn't possible to tell Typescript that contextWrapper is the same as T
|
|
61
|
+
* so we forced to cast as any here.
|
|
62
|
+
*/
|
|
63
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
64
|
+
return contextWrapper;
|
|
65
|
+
}
|
|
66
|
+
return target;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
exports.AsyncLocalStorageContextManager = AsyncLocalStorageContextManager;
|
|
70
|
+
//# sourceMappingURL=asyncLocalStorageContextManager.js.map
|
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
exports.createContextManager = exports.isSemverGreaterThanOrEqualTo = void 0;
|
|
18
|
+
__exportStar(require("./asyncHooksContextManager"), exports);
|
|
19
|
+
__exportStar(require("./asyncLocalStorageContextManager"), exports);
|
|
20
|
+
var util_1 = require("./util");
|
|
21
|
+
Object.defineProperty(exports, "isSemverGreaterThanOrEqualTo", { enumerable: true, get: function () { return util_1.isSemverGreaterThanOrEqualTo; } });
|
|
22
|
+
Object.defineProperty(exports, "createContextManager", { enumerable: true, get: function () { return util_1.createContextManager; } });
|
|
23
|
+
//# sourceMappingURL=index.js.map
|
package/dist/util.d.ts
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { AsyncLocalStorageContextManager } from './asyncLocalStorageContextManager';
|
|
2
|
+
import { AsyncHooksContextManager } from './asyncHooksContextManager';
|
|
3
|
+
export declare function isSemverGreaterThanOrEqualTo(currentVersion: string, targetVersion: string): boolean;
|
|
4
|
+
export declare function createContextManager(): AsyncHooksContextManager | AsyncLocalStorageContextManager;
|
|
5
|
+
//# sourceMappingURL=util.d.ts.map
|
package/dist/util.js
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createContextManager = exports.isSemverGreaterThanOrEqualTo = void 0;
|
|
4
|
+
const asyncLocalStorageContextManager_1 = require("./asyncLocalStorageContextManager");
|
|
5
|
+
const asyncHooksContextManager_1 = require("./asyncHooksContextManager");
|
|
6
|
+
const semver = /^[v^~<>=]*?(\d+)(?:\.([x*]|\d+)(?:\.([x*]|\d+)(?:\.([x*]|\d+))?(?:-([\da-z-]+(?:\.[\da-z-]+)*))?(?:\+[\da-z-]+(?:\.[\da-z-]+)*)?)?)?$/i;
|
|
7
|
+
// 判断 semver 大于等于 v14.8.0
|
|
8
|
+
function isSemverGreaterThanOrEqualTo(currentVersion, targetVersion) {
|
|
9
|
+
const v = semver.exec(currentVersion);
|
|
10
|
+
const t = semver.exec(targetVersion);
|
|
11
|
+
if (v && t) {
|
|
12
|
+
if (v[1] === t[1] && v[2] === t[2] && v[3] === t[3] && v[4] === t[4]) {
|
|
13
|
+
return true;
|
|
14
|
+
}
|
|
15
|
+
return (gteString(v[1], t[1]) ||
|
|
16
|
+
(v[1] === t[1] && gteString(v[2], t[2])) ||
|
|
17
|
+
(v[1] === t[1] && v[2] === t[2] && gteString(v[3], t[3])) ||
|
|
18
|
+
(v[1] === t[1] && v[2] === t[2] && v[3] === t[3] && gteString(v[4], t[4])));
|
|
19
|
+
}
|
|
20
|
+
return false;
|
|
21
|
+
}
|
|
22
|
+
exports.isSemverGreaterThanOrEqualTo = isSemverGreaterThanOrEqualTo;
|
|
23
|
+
function gteString(v1, v2) {
|
|
24
|
+
// compare string with parseInt
|
|
25
|
+
const v1Int = parseInt(v1, 10);
|
|
26
|
+
const v2Int = parseInt(v2, 10);
|
|
27
|
+
return v1Int > v2Int;
|
|
28
|
+
}
|
|
29
|
+
function createContextManager() {
|
|
30
|
+
const ContextManager = isSemverGreaterThanOrEqualTo(process.version, '14.8.0')
|
|
31
|
+
? asyncLocalStorageContextManager_1.AsyncLocalStorageContextManager
|
|
32
|
+
: asyncHooksContextManager_1.AsyncHooksContextManager;
|
|
33
|
+
return new ContextManager();
|
|
34
|
+
}
|
|
35
|
+
exports.createContextManager = createContextManager;
|
|
36
|
+
//# sourceMappingURL=util.js.map
|
package/package.json
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@midwayjs/async-hooks-context-manager",
|
|
3
|
+
"version": "3.4.0-beta.8",
|
|
4
|
+
"description": "midway async hooks context manager",
|
|
5
|
+
"main": "dist/index",
|
|
6
|
+
"typings": "dist/index.d.ts",
|
|
7
|
+
"scripts": {
|
|
8
|
+
"build": "tsc",
|
|
9
|
+
"test": "node --require=ts-node/register ../../node_modules/.bin/jest --runInBand",
|
|
10
|
+
"cov": "node --require=ts-node/register ../../node_modules/.bin/jest --runInBand --coverage --forceExit"
|
|
11
|
+
},
|
|
12
|
+
"keywords": [
|
|
13
|
+
"midway",
|
|
14
|
+
"async",
|
|
15
|
+
"context manager"
|
|
16
|
+
],
|
|
17
|
+
"files": [
|
|
18
|
+
"dist/**/*.js",
|
|
19
|
+
"dist/**/*.d.ts"
|
|
20
|
+
],
|
|
21
|
+
"license": "MIT",
|
|
22
|
+
"devDependencies": {
|
|
23
|
+
"@midwayjs/core": "^3.4.0-beta.8"
|
|
24
|
+
},
|
|
25
|
+
"author": "Harry Chen <czy88840616@gmail.com>",
|
|
26
|
+
"repository": {
|
|
27
|
+
"type": "git",
|
|
28
|
+
"url": "http://github.com/midwayjs/midway.git"
|
|
29
|
+
},
|
|
30
|
+
"engines": {
|
|
31
|
+
"node": ">=12.17.0"
|
|
32
|
+
},
|
|
33
|
+
"gitHead": "a603d2348d6141f8f723901498f03a162a037708"
|
|
34
|
+
}
|