faastjs
Version:
Serverless batch computing made simple.
139 lines • 14.6 kB
JavaScript
Object.defineProperty(exports, "__esModule", { value: true });
exports.clearLeakDetector = exports.onAsyncHook = exports.stopAsyncTracing = exports.printHooks = exports.detectAsyncLeaks = exports.printAsyncStack = exports.trace = exports.startAsyncTracing = void 0;
const tslib_1 = require("tslib");
const async_hooks_1 = tslib_1.__importDefault(require("async_hooks"));
const util_1 = require("util");
let hook;
const asyncObjects = new Map();
const objectMapping = new Map();
function startAsyncTracing(stackTraces = false) {
hook = onAsyncHook(stackTraces);
}
exports.startAsyncTracing = startAsyncTracing;
function trace(obj) {
let res = objectMapping.get(obj);
if (!res) {
// console.log(`trace: object not found: ${util.inspect(obj)}`);
return;
}
let asyncTrace = `== Tracing leaked object ${res.asyncId} ==`;
while (res) {
const { stack, ...rest } = res;
asyncTrace += `${(0, util_1.inspect)(rest)}\n${stack}`;
res = asyncObjects.get(res.triggerId);
}
console.log(asyncTrace);
return { obj, trace: asyncTrace };
}
exports.trace = trace;
function printAsyncStack() {
console.log(`Async stack:`);
let res = asyncObjects.get(async_hooks_1.default.executionAsyncId());
while (res) {
const { stack, ...rest } = res;
console.log(`%O\n${stack}`, rest);
res = asyncObjects.get(res.triggerId);
}
}
exports.printAsyncStack = printAsyncStack;
function detectAsyncLeaks() {
const leaks = [];
process._getActiveHandles().forEach((h) => {
if (h !== process.stdout && h !== process.stderr) {
const leak = trace(h);
leak && leaks.push(leak);
}
});
process._getActiveRequests().forEach((h) => {
const leak = trace(h);
leak && leaks.push(leak);
});
return leaks;
}
exports.detectAsyncLeaks = detectAsyncLeaks;
function printHooks() {
for (const obj of asyncObjects) {
console.log(`%O`, obj);
}
}
exports.printHooks = printHooks;
function stopAsyncTracing() {
hook?.();
}
exports.stopAsyncTracing = stopAsyncTracing;
function onAsyncHook(stackTraces) {
const hooks = {
init,
before,
after,
destroy,
promiseResolve
};
const asyncHook = async_hooks_1.default.createHook(hooks);
asyncHook.enable();
return () => {
asyncHook.disable();
};
function init(asyncId, type, triggerId, resource) {
const obj = {
asyncId,
type,
triggerId,
resource,
state: "init",
startedCount: 0,
finishedCount: 0,
stack: stackTraces
? new Error("stack:").stack.replace(/Error:/, "")
: undefined
};
asyncObjects.set(asyncId, obj);
objectMapping.set(resource, obj);
}
function destroy(asyncId) {
const obj = asyncObjects.get(asyncId);
if (obj) {
obj.state = "destroyed";
}
else {
// console.log(`destroyed: No obj ${asyncId}`);
}
}
function before(asyncId) {
const obj = asyncObjects.get(asyncId);
if (obj) {
obj.state = "before";
obj.startedCount++;
}
else {
// console.log(`before: No obj ${asyncId}`);
}
}
function after(asyncId) {
const obj = asyncObjects.get(asyncId);
if (obj) {
obj.state = "after";
obj.finishedCount++;
}
else {
// console.log(`after: No obj ${asyncId}`);
}
}
function promiseResolve(asyncId) {
const obj = asyncObjects.get(asyncId);
if (obj) {
obj.state = "resolved";
}
else {
// console.log(`resolved: No obj ${asyncId}`);
}
}
}
exports.onAsyncHook = onAsyncHook;
function clearLeakDetector() {
asyncObjects.clear();
objectMapping.clear();
}
exports.clearLeakDetector = clearLeakDetector;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHJhY2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvdHJhY2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7OztBQUFBLHNFQUFxQztBQUNyQywrQkFBK0I7QUFFL0IsSUFBSSxJQUE0QixDQUFDO0FBZWpDLE1BQU0sWUFBWSxHQUE2QixJQUFJLEdBQUcsRUFBRSxDQUFDO0FBQ3pELE1BQU0sYUFBYSxHQUE2QixJQUFJLEdBQUcsRUFBRSxDQUFDO0FBRTFELFNBQWdCLGlCQUFpQixDQUFDLGNBQXVCLEtBQUs7SUFDMUQsSUFBSSxHQUFHLFdBQVcsQ0FBQyxXQUFXLENBQUMsQ0FBQztBQUNwQyxDQUFDO0FBRkQsOENBRUM7QUFPRCxTQUFnQixLQUFLLENBQUMsR0FBVztJQUM3QixJQUFJLEdBQUcsR0FBRyxhQUFhLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxDQUFDO0lBQ2pDLElBQUksQ0FBQyxHQUFHLEVBQUUsQ0FBQztRQUNQLGdFQUFnRTtRQUNoRSxPQUFPO0lBQ1gsQ0FBQztJQUNELElBQUksVUFBVSxHQUFHLDRCQUE0QixHQUFHLENBQUMsT0FBTyxLQUFLLENBQUM7SUFDOUQsT0FBTyxHQUFHLEVBQUUsQ0FBQztRQUNULE1BQU0sRUFBRSxLQUFLLEVBQUUsR0FBRyxJQUFJLEVBQUUsR0FBRyxHQUFHLENBQUM7UUFDL0IsVUFBVSxJQUFJLEdBQUcsSUFBQSxjQUFPLEVBQUMsSUFBSSxDQUFDLEtBQUssS0FBSyxFQUFFLENBQUM7UUFDM0MsR0FBRyxHQUFHLFlBQVksQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLFNBQVMsQ0FBQyxDQUFDO0lBQzFDLENBQUM7SUFDRCxPQUFPLENBQUMsR0FBRyxDQUFDLFVBQVUsQ0FBQyxDQUFDO0lBQ3hCLE9BQU8sRUFBRSxHQUFHLEVBQUUsS0FBSyxFQUFFLFVBQVUsRUFBRSxDQUFDO0FBQ3RDLENBQUM7QUFkRCxzQkFjQztBQUVELFNBQWdCLGVBQWU7SUFDM0IsT0FBTyxDQUFDLEdB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LENBQUMsS0FBSyxFQUFFLENBQUM7QUFDMUIsQ0FBQztBQUhELDhDQUdDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IGFzeW5jSG9va3MgZnJvbSBcImFzeW5jX2hvb2tzXCI7XG5pbXBvcnQgeyBpbnNwZWN0IH0gZnJvbSBcInV0aWxcIjtcblxubGV0IGhvb2s6ICgpID0+IHZvaWQgfCB1bmRlZmluZWQ7XG5cbnR5cGUgQXN5bmNTdGF0ZSA9IFwiaW5pdFwiIHwgXCJiZWZvcmVcIiB8IFwiYWZ0ZXJcIiB8IFwiZGVzdHJveWVkXCIgfCBcInJlc29sdmVkXCI7XG5cbmludGVyZmFjZSBBc3luY09iamVjdCB7XG4gICAgYXN5bmNJZDogbnVtYmVyO1xuICAgIHR5cGU6IHN0cmluZztcbiAgICB0cmlnZ2VySWQ6IG51bWJlcjtcbiAgICByZXNvdXJjZTogYW55O1xuICAgIHN0YXRlOiBBc3luY1N0YXRlO1xuICAgIHN0YXJ0ZWRDb3VudDogbnVtYmVyO1xuICAgIGZpbmlzaGVkQ291bnQ6IG51bWJlcjtcbiAgICBzdGFjaz86IHN0cmluZztcbn1cblxuY29uc3QgYXN5bmNPYmplY3RzOiBNYXA8bnVtYmVyLCBBc3luY09iamVjdD4gPSBuZXcgTWFwKCk7XG5jb25zdCBvYmplY3RNYXBwaW5nOiBNYXA8b2JqZWN0LCBBc3luY09iamVjdD4gPSBuZXcgTWFwKCk7XG5cbmV4cG9ydCBmdW5jdGlvbiBzdGFydEFzeW5jVHJhY2luZyhzdGFja1RyYWNlczogYm9vbGVhbiA9IGZhbHNlKSB7XG4gICAgaG9vayA9IG9uQXN5bmNIb29rKHN0YWNrVHJhY2VzKTtcbn1cblxuaW50ZXJmYWNlIFRyYWNlIHtcbiAgICBvYmo6IG9iamVjdDtcbiAgICB0cmFjZTogc3RyaW5nO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gdHJhY2Uob2JqOiBvYmplY3QpOiBUcmFjZSB8IHZvaWQge1xuICAgIGxldCByZXMgPSBvYmplY3RNYXBwaW5nLmdldChvYmopO1xuICAgIGlmICghcmVzKSB7XG4gICAgICAgIC8vIGNvbnNvbGUubG9nKGB0cmFjZTogb2JqZWN0IG5vdCBmb3VuZDogJHt1dGlsLmluc3BlY3Qob2JqKX1gKTtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBsZXQgYXN5bmNUcmFjZSA9IGA9PSBUcmFjaW5nIGxlYWtlZCBvYmplY3QgJHtyZXMuYXN5bmNJZH0gPT1gO1xuICAgIHdoaWxlIChyZXMpIHtcbiAgICAgICAgY29uc3QgeyBzdGFjaywgLi4ucmVzdCB9ID0gcmVzO1xuICAgICAgICBhc3luY1RyYWNlICs9IGAke2luc3BlY3QocmVzdCl9XFxuJHtzdGFja31gO1xuICAgICAgICByZXMgPSBhc3luY09iamVjdHMuZ2V0KHJlcy50cmlnZ2VySWQpO1xuICAgIH1cbiAgICBjb25zb2xlLmxvZyhhc3luY1RyYWNlKTtcbiAgICByZXR1cm4geyBvYmosIHRyYWNlOiBhc3luY1RyYWNlIH07XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBwcmludEFzeW5jU3RhY2soKSB7XG4gICAgY29uc29sZS5sb2coYEFzeW5jIHN0YWNrOmApO1xuICAgIGxldCByZXMgPSBhc3luY09iamVjdHMuZ2V0KGFzeW5jSG9va3MuZXhlY3V0aW9uQXN5bmNJZCgpKTtcbiAgICB3aGlsZSAocmVzKSB7XG4gICAgICAgIGNvbnN0IHsgc3RhY2ssIC4uLnJlc3QgfSA9IHJlcztcbiAgICAgICAgY29uc29sZS5sb2coYCVPXFxuJHtzdGFja31gLCByZXN0KTtcbiAgICAgICAgcmVzID0gYXN5bmNPYmplY3RzLmdldChyZXMudHJpZ2dlcklkKTtcbiAgICB9XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBkZXRlY3RBc3luY0xlYWtzKCk6IG9iamVjdFtdIHtcbiAgICBjb25zdCBsZWFrczogVHJhY2VbXSA9IFtdO1xuICAgIChwcm9jZXNzIGFzIGFueSkuX2dldEFjdGl2ZUhhbmRsZXMoKS5mb3JFYWNoKChoOiBvYmplY3QpID0+IHtcbiAgICAgICAgaWYgKGggIT09IHByb2Nlc3Muc3Rkb3V0ICYmIGggIT09IHByb2Nlc3Muc3RkZXJyKSB7XG4gICAgICAgICAgICBjb25zdCBsZWFrID0gdHJhY2UoaCk7XG4gICAgICAgICAgICBsZWFrICYmIGxlYWtzLnB1c2gobGVhayk7XG4gICAgICAgIH1cbiAgICB9KTtcbiAgICAocHJvY2VzcyBhcyBhbnkpLl9nZXRBY3RpdmVSZXF1ZXN0cygpLmZvckVhY2goKGg6IG9iamVjdCkgPT4ge1xuICAgICAgICBjb25zdCBsZWFrID0gdHJhY2UoaCk7XG4gICAgICAgIGxlYWsgJiYgbGVha3MucHVzaChsZWFrKTtcbiAgICB9KTtcbiAgICByZXR1cm4gbGVha3M7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBwcmludEhvb2tzKCkge1xuICAgIGZvciAoY29uc3Qgb2JqIG9mIGFzeW5jT2JqZWN0cykge1xuICAgICAgICBjb25zb2xlLmxvZyhgJU9gLCBvYmopO1xuICAgIH1cbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHN0b3BBc3luY1RyYWNpbmcoKSB7XG4gICAgaG9vaz8uKCk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBvbkFzeW5jSG9vayhzdGFja1RyYWNlczogYm9vbGVhbikge1xuICAgIGNvbnN0IGhvb2tzOiBhc3luY0hvb2tzLkhvb2tDYWxsYmFja3MgPSB7XG4gICAgICAgIGluaXQsXG4gICAgICAgIGJlZm9yZSxcbiAgICAgICAgYWZ0ZXIsXG4gICAgICAgIGRlc3Ryb3ksXG4gICAgICAgIHByb21pc2VSZXNvbHZlXG4gICAgfTtcblxuICAgIGNvbnN0IGFzeW5jSG9vayA9IGFzeW5jSG9va3MuY3JlYXRlSG9vayhob29rcyk7XG4gICAgYXN5bmNIb29rLmVuYWJsZSgpO1xuXG4gICAgcmV0dXJuICgpID0+IHtcbiAgICAgICAgYXN5bmNIb29rLmRpc2FibGUoKTtcbiAgICB9O1xuXG4gICAgZnVuY3Rpb24gaW5pdChhc3luY0lkOiBudW1iZXIsIHR5cGU6IHN0cmluZywgdHJpZ2dlcklkOiBudW1iZXIsIHJlc291cmNlOiBvYmplY3QpIHtcbiAgICAgICAgY29uc3Qgb2JqOiBBc3luY09iamVjdCA9IHtcbiAgICAgICAgICAgIGFzeW5jSWQsXG4gICAgICAgICAgICB0eXBlLFxuICAgICAgICAgICAgdHJpZ2dlcklkLFxuICAgICAgICAgICAgcmVzb3VyY2UsXG4gICAgICAgICAgICBzdGF0ZTogXCJpbml0XCIsXG4gICAgICAgICAgICBzdGFydGVkQ291bnQ6IDAsXG4gICAgICAgICAgICBmaW5pc2hlZENvdW50OiAwLFxuICAgICAgICAgICAgc3RhY2s6IHN0YWNrVHJhY2VzXG4gICAgICAgICAgICAgICAgPyBuZXcgRXJyb3IoXCJzdGFjazpcIikuc3RhY2shLnJlcGxhY2UoL0Vycm9yOi8sIFwiXCIpXG4gICAgICAgICAgICAgICAgOiB1bmRlZmluZWRcbiAgICAgICAgfTtcbiAgICAgICAgYXN5bmNPYmplY3RzLnNldChhc3luY0lkLCBvYmopO1xuICAgICAgICBvYmplY3RNYXBwaW5nLnNldChyZXNvdXJjZSwgb2JqKTtcbiAgICB9XG4gICAgZnVuY3Rpb24gZGVzdHJveShhc3luY0lkOiBudW1iZXIpIHtcbiAgICAgICAgY29uc3Qgb2JqID0gYXN5bmNPYmplY3RzLmdldChhc3luY0lkKTtcbiAgICAgICAgaWYgKG9iaikge1xuICAgICAgICAgICAgb2JqLnN0YXRlID0gXCJkZXN0cm95ZWRcIjtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIC8vIGNvbnNvbGUubG9nKGBkZXN0cm95ZWQ6IE5vIG9iaiAke2FzeW5jSWR9YCk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgZnVuY3Rpb24gYmVmb3JlKGFzeW5jSWQ6IG51bWJlcikge1xuICAgICAgICBjb25zdCBvYmogPSBhc3luY09iamVjdHMuZ2V0KGFzeW5jSWQpO1xuICAgICAgICBpZiAob2JqKSB7XG4gICAgICAgICAgICBvYmouc3RhdGUgPSBcImJlZm9yZVwiO1xuICAgICAgICAgICAgb2JqLnN0YXJ0ZWRDb3VudCsrO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgLy8gY29uc29sZS5sb2coYGJlZm9yZTogTm8gb2JqICR7YXN5bmNJZH1gKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICBmdW5jdGlvbiBhZnRlcihhc3luY0lkOiBudW1iZXIpIHtcbiAgICAgICAgY29uc3Qgb2JqID0gYXN5bmNPYmplY3RzLmdldChhc3luY0lkKTtcbiAgICAgICAgaWYgKG9iaikge1xuICAgICAgICAgICAgb2JqLnN0YXRlID0gXCJhZnRlclwiO1xuICAgICAgICAgICAgb2JqLmZpbmlzaGVkQ291bnQrKztcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIC8vIGNvbnNvbGUubG9nKGBhZnRlcjogTm8gb2JqICR7YXN5bmNJZH1gKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICBmdW5jdGlvbiBwcm9taXNlUmVzb2x2ZShhc3luY0lkOiBudW1iZXIpIHtcbiAgICAgICAgY29uc3Qgb2JqID0gYXN5bmNPYmplY3RzLmdldChhc3luY0lkKTtcbiAgICAgICAgaWYgKG9iaikge1xuICAgICAgICAgICAgb2JqLnN0YXRlID0gXCJyZXNvbHZlZFwiO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgLy8gY29uc29sZS5sb2coYHJlc29sdmVkOiBObyBvYmogJHthc3luY0lkfWApO1xuICAgICAgICB9XG4gICAgfVxufVxuXG5leHBvcnQgZnVuY3Rpb24gY2xlYXJMZWFrRGV0ZWN0b3IoKSB7XG4gICAgYXN5bmNPYmplY3RzLmNsZWFyKCk7XG4gICAgb2JqZWN0TWFwcGluZy5jbGVhcigpO1xufVxuIl19
;