1 | const Cause = require("@cause/cause");
|
2 | const { spawn, fork } = require("child_process");
|
3 | const { promisify } = require("util");
|
4 | const pstree = promisify(require("ps-tree"));
|
5 | const Process = require("./process");
|
6 | const legacy = require("@cause/cause/record");
|
7 | const { getUUID, getTypeWithUUID, deserialize, serialize } = require("@algebraic/type");
|
8 |
|
9 |
|
10 |
|
11 | module.exports = function fork_(push, { path, args })
|
12 | {
|
13 | const process = path === "node" ?
|
14 | fork(args[0], args.slice(1)) :
|
15 | spawn(path, args, { stdio: [0, 1, 2] });
|
16 | const { pid } = process;
|
17 | const success = pid !== void 0;
|
18 | const cancel = success && (() => kill(0, pid));
|
19 |
|
20 | process.on("error", error => push(Process.ChildError({ error })));
|
21 |
|
22 |
|
23 |
|
24 | if (success)
|
25 | {
|
26 | process.on("exit", exitCode => push(Process.ChildExited({ exitCode })));
|
27 | process.on("message", message =>
|
28 | push(Process.ChildMessage({ event: inferredDeserialize(message) })));
|
29 |
|
30 | const send = event => process.send(inferredSerialize(event));
|
31 | push(Process.ChildStarted({ pid, send }));
|
32 | }
|
33 |
|
34 | return cancel;
|
35 | }
|
36 |
|
37 | function inferredDeserialize({ isLegacy, UUID, serialized })
|
38 | {
|
39 | if (isLegacy)
|
40 | return legacy.deserialize(serialized);
|
41 |
|
42 | return deserialize(getTypeWithUUID(UUID), serialized);
|
43 | }
|
44 |
|
45 | module.exports.inferredDeserialize = inferredDeserialize;
|
46 |
|
47 | function inferredSerialize(event)
|
48 | {
|
49 | const type = Object.getPrototypeOf(event).constructor;
|
50 | const UUID = getUUID(type);
|
51 |
|
52 | if (typeof UUID !== "string")
|
53 | return { isLegacy: true, serialized: legacy.serialize(event) };
|
54 |
|
55 | return { UUID, serialized: serialize(type, event) };
|
56 | }
|
57 |
|
58 | module.exports.inferredSerialize = inferredSerialize;
|
59 |
|
60 | module.exports.kill = kill;
|
61 |
|
62 | function kill(push, pid)
|
63 | {
|
64 |
|
65 | return pstree(pid)
|
66 | .then(children => children.map(({ PID }) => PID))
|
67 | .then(children => ["-s", "SIGINT", pid, ...children])
|
68 | .then(args => spawn("kill", args, { stdio:[0,1,2] }))
|
69 |
|
70 | .catch(console.log);
|
71 | }
|