parallel-park
Version:
Parallel/concurrent async work, optionally using multiple processes
135 lines (134 loc) • 6.94 kB
JavaScript
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.inChildProcess = void 0;
const child_process_1 = __importDefault(require("child_process"));
const error_utils_1 = require("@suchipi/error-utils");
const debug_1 = __importDefault(require("debug"));
const util_1 = __importDefault(require("util"));
const read_until_end_1 = require("./read-until-end");
const debug = (0, debug_1.default)("parallel-park:in-child-process");
const runnerPath = require.resolve("../dist/child-process-worker");
const inChildProcess = (...args) => {
var _a;
const inputs = typeof args[0] === "function" ? {} : args[0];
const functionToRun = typeof args[0] === "function" ? args[0] : args[1];
if (typeof inputs !== "object") {
throw new Error("The first argument to inChildProcess should be an object of input data to pass to the child process.");
}
if (typeof functionToRun !== "function") {
throw new Error("The second argument to inChildProcess should be a function to run in the child process.");
}
const here = new error_utils_1.ParsedError(new Error("here"));
const callingFrame = here.stackFrames[1];
const callingFile = (_a = callingFrame === null || callingFrame === void 0 ? void 0 : callingFrame.fileName) !== null && _a !== void 0 ? _a : "unknown file";
debug("spawning child process: %o", [process.argv[0], runnerPath]);
const child = child_process_1.default.spawn(process.argv[0], [runnerPath], {
stdio: ["inherit", "inherit", "inherit", "pipe", "pipe"],
});
return new Promise((resolve, reject) => {
child.on("error", reject);
const commsOut = child.stdio[3];
const commsIn = child.stdio[4];
child.on("spawn", () => {
const dataToSend = JSON.stringify([
inputs,
functionToRun.toString(),
callingFile,
]);
debug("sending inputs to child process: %o", dataToSend);
commsOut.end(dataToSend, "utf-8");
});
let receivedData = "";
(0, read_until_end_1.readUntilEnd)(commsIn).then((data) => {
debug("received data from child process: %o", data);
receivedData = data;
});
child.on("close", (code, signal) => {
debug("child process closed: %o", { code, signal });
if (code !== 0) {
reject(new Error(`Child process exited with nonzero status code: ${JSON.stringify({
code,
signal,
})}`));
}
else {
debug("parsing received data from child process...");
let result;
try {
result = JSON.parse(receivedData);
}
catch (err) {
reject(new Error(`parallel-park error: failed to parse received data as JSON. data was: ${util_1.default.inspect(receivedData, { colors: true, depth: Infinity })}`));
return;
}
switch (result.type) {
case "success": {
debug("child process finished successfully with result: %o", result.data);
resolve(result.data);
break;
}
case "error": {
debug("child process errored: %o", result.error);
const error = new Error(result.error.message);
Object.defineProperty(error, "name", { value: result.error.name });
Object.defineProperty(error, "stack", {
value: result.error.name +
": " +
result.error.message +
"\n" +
result.error.stack
.split("\n")
.slice(1)
.filter((line) => !/node:internal|node:events/.test(line))
.map((line) => {
if (/evalmachine/.test(line)) {
const lineWithoutEvalMachine = line.replace(/evalmachine(?:\.<anonymous>)?/, "<function passed into inChildProcess>");
const matches = line.match(/:(\d+):(\d+)\)?$/);
if (!matches) {
return lineWithoutEvalMachine;
}
else {
let [_, row, col] = matches;
// subtract 1 from row to skip the module wrapper function line
row = row - 1;
// subtract the length of the `return ` keywords in front of the function
if (row === 1) {
col = col - `return `.length;
}
const hadParen = /\)$/.test(lineWithoutEvalMachine);
return lineWithoutEvalMachine.replace(/:\d+:\d+\)?$/, `:${row}:${col - 1}${hadParen ? ")" : ""}`);
}
}
else {
return line;
}
})
.join("\n") +
"\n" +
error
.stack.split("\n")
.slice(1)
.filter((line) => !/node:internal|node:events/.test(line))
.join("\n") +
"\n" +
here
.stack.split("\n")
.slice(2)
.filter((line) => !/node:internal|node:events/.test(line))
.join("\n"),
});
reject(error);
break;
}
default: {
reject(new Error(`Internal parallel-park error: unhandled result type: ${result.type}`));
}
}
}
});
});
};
exports.inChildProcess = inChildProcess;
;