UNPKG

parallel-park

Version:

Parallel/concurrent async work, optionally using multiple processes

135 lines (134 loc) 6.94 kB
"use strict"; 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;