@mongosh/node-runtime-worker-thread 2.3.0 → 2.3.2

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.
Files changed (58) hide show
  1. package/AUTHORS +1 -0
  2. package/dist/153.js +1 -0
  3. package/dist/41.js +1 -0
  4. package/dist/502.js +1 -0
  5. package/dist/{578.js → 503.js} +1 -1
  6. package/dist/{43.js → 527.js} +1 -1
  7. package/dist/534.js +1 -0
  8. package/dist/711.js +1 -0
  9. package/dist/739.js +1 -0
  10. package/dist/index.d.ts +6 -8
  11. package/dist/index.js +1 -1
  12. package/dist/index.js.map +1 -1
  13. package/dist/report.html +2 -2
  14. package/dist/rpc.d.ts +6 -15
  15. package/dist/rpc.js +7 -71
  16. package/dist/rpc.js.map +1 -1
  17. package/dist/worker-process-mongosh-bus.d.ts +7 -0
  18. package/dist/{child-process-mongosh-bus.js → worker-process-mongosh-bus.js} +8 -8
  19. package/dist/worker-process-mongosh-bus.js.map +1 -0
  20. package/dist/worker-runtime.js +16 -16
  21. package/dist/worker-runtime.js.map +1 -1
  22. package/dist/{child-process-evaluation-listener.d.ts → worker-thread-evaluation-listener.d.ts} +2 -4
  23. package/dist/{child-process-evaluation-listener.js → worker-thread-evaluation-listener.js} +6 -6
  24. package/dist/worker-thread-evaluation-listener.js.map +1 -0
  25. package/package.json +13 -12
  26. package/src/index.spec.ts +148 -147
  27. package/src/index.ts +98 -120
  28. package/src/lock.spec.ts +1 -1
  29. package/src/rpc.spec.ts +24 -90
  30. package/src/rpc.ts +17 -98
  31. package/src/{child-process-mongosh-bus.ts → worker-process-mongosh-bus.ts} +5 -6
  32. package/src/worker-runtime.spec.ts +19 -29
  33. package/src/worker-runtime.ts +15 -22
  34. package/src/{child-process-evaluation-listener.ts → worker-thread-evaluation-listener.ts} +3 -4
  35. package/tests/register-worker.js +1 -0
  36. package/tsconfig.json +2 -1
  37. package/webpack.config.js +4 -6
  38. package/__fixtures__/script-that-throws.js +0 -1
  39. package/dist/354.js +0 -1
  40. package/dist/528.js +0 -1
  41. package/dist/650.js +0 -1
  42. package/dist/722.js +0 -1
  43. package/dist/777.js +0 -1
  44. package/dist/942.js +0 -1
  45. package/dist/child-process-evaluation-listener.js.map +0 -1
  46. package/dist/child-process-mongosh-bus.d.ts +0 -9
  47. package/dist/child-process-mongosh-bus.js.map +0 -1
  48. package/dist/child-process-proxy.d.ts +0 -1
  49. package/dist/child-process-proxy.js +0 -1
  50. package/dist/child-process-proxy.js.map +0 -1
  51. package/dist/spawn-child-from-source.d.ts +0 -5
  52. package/dist/spawn-child-from-source.js +0 -74
  53. package/dist/spawn-child-from-source.js.map +0 -1
  54. package/src/child-process-proxy.spec.ts +0 -84
  55. package/src/child-process-proxy.ts +0 -124
  56. package/src/spawn-child-from-source.spec.ts +0 -90
  57. package/src/spawn-child-from-source.ts +0 -102
  58. package/tsconfig.test.json +0 -11
@@ -1,124 +0,0 @@
1
- /* istanbul ignore file */
2
- /* ^^^ we test the dist directly, so isntanbul can't calculate the coverage correctly */
3
-
4
- /**
5
- * This proxy is needed as a workaround for the old electron verison "bug" where
6
- * due to the electron runtime being a chromium, not just node (even with
7
- * `ELECTRON_RUN_AS_NODE` enabled), SIGINT doesn't break code execution. This is
8
- * fixed in the later versions of electron/node but we are still on the older
9
- * one, we have to have this proxy in place
10
- *
11
- * @todo as soon as we update electron version in compass, we can get rid of
12
- * this part of the worker runtime as it becomes redundant
13
- *
14
- * @see {@link https://github.com/nodejs/node/pull/36344}
15
- */
16
- import { once } from 'events';
17
- import { SHARE_ENV, Worker } from 'worker_threads';
18
- import path from 'path';
19
- import { exposeAll, createCaller } from './rpc';
20
- import type { InterruptHandle } from 'interruptor';
21
- import { interrupt as nativeInterrupt } from 'interruptor';
22
-
23
- const workerRuntimeSrcPath =
24
- process.env.WORKER_RUNTIME_SRC_PATH_DO_NOT_USE_THIS_EXCEPT_FOR_TESTING ||
25
- path.resolve(__dirname, 'worker-runtime.js');
26
-
27
- const workerProcess = new Worker(workerRuntimeSrcPath, { env: SHARE_ENV });
28
-
29
- const workerReadyPromise: Promise<void> = (async () => {
30
- const waitForReadyMessage = async () => {
31
- let msg: string;
32
- while (([msg] = await once(workerProcess, 'message'))) {
33
- if (msg === 'ready') return;
34
- }
35
- };
36
-
37
- const waitForError = async () => {
38
- const [err] = await once(workerProcess, 'error');
39
- if (err) {
40
- err.message = `Worker thread failed to start with the following error: ${err.message}`;
41
- throw err;
42
- }
43
- };
44
-
45
- await Promise.race([waitForReadyMessage(), waitForError()]);
46
- })();
47
-
48
- // We expect the amount of listeners to be more than the default value of 10 but
49
- // probably not more than ~25 (all exposed methods on
50
- // ChildProcessEvaluationListener and ChildProcessMongoshBus + any concurrent
51
- // in-flight calls on ChildProcessRuntime) at once
52
- process.setMaxListeners(25);
53
- workerProcess.setMaxListeners(25);
54
-
55
- let interruptHandle: InterruptHandle | null = null;
56
-
57
- const { interrupt } = createCaller(['interrupt'], workerProcess);
58
-
59
- const worker = Object.assign(
60
- createCaller(
61
- ['init', 'evaluate', 'getCompletions', 'getShellPrompt'],
62
- workerProcess
63
- ),
64
- {
65
- interrupt(): boolean {
66
- if (interruptHandle) {
67
- nativeInterrupt(interruptHandle);
68
- return true;
69
- }
70
-
71
- return interrupt();
72
- },
73
- }
74
- );
75
-
76
- function waitForWorkerReadyProxy<T extends Function>(fn: T): T {
77
- return new Proxy(fn, {
78
- async apply(target, thisArg, argumentsList) {
79
- await workerReadyPromise;
80
- return target.call(thisArg, ...Array.from(argumentsList));
81
- },
82
- });
83
- }
84
-
85
- // Every time parent process wants to request something from worker through
86
- // proxy, we want to make sure worker process is ready
87
- (Object.keys(worker) as (keyof typeof worker)[]).forEach((key) => {
88
- worker[key] = waitForWorkerReadyProxy(worker[key]);
89
- });
90
-
91
- exposeAll(worker, process);
92
-
93
- const evaluationListener = Object.assign(
94
- createCaller(
95
- [
96
- 'onPrint',
97
- 'onPrompt',
98
- 'getConfig',
99
- 'setConfig',
100
- 'resetConfig',
101
- 'validateConfig',
102
- 'listConfigOptions',
103
- 'onClearCommand',
104
- 'onExit',
105
- ],
106
- process
107
- ),
108
- {
109
- onRunInterruptible(handle: InterruptHandle | null) {
110
- interruptHandle = handle;
111
- },
112
- }
113
- );
114
-
115
- exposeAll(evaluationListener, workerProcess);
116
-
117
- const messageBus = createCaller(['emit', 'on'], process);
118
-
119
- exposeAll(messageBus, workerProcess);
120
-
121
- process.once('disconnect', () => process.exit());
122
- process.nextTick(() => {
123
- process.send?.('ready');
124
- });
@@ -1,90 +0,0 @@
1
- import { expect } from 'chai';
2
- import type { ChildProcess } from 'child_process';
3
- import childProcess from 'child_process';
4
- import { once } from 'events';
5
- import spawnChildFromSource, { kill } from './spawn-child-from-source';
6
-
7
- describe('spawnChildFromSource', function () {
8
- let spawned: ChildProcess;
9
-
10
- afterEach(async function () {
11
- if (spawned) {
12
- await kill(spawned, 'SIGKILL');
13
- spawned = null;
14
- }
15
- });
16
-
17
- it('should throw if stdin is missing', async function () {
18
- let err: Error;
19
-
20
- try {
21
- spawned = await spawnChildFromSource('console.log("Hi")', {
22
- // Making istanbul happy by passing stuff that's not allowed
23
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
24
- // @ts-expect-error
25
- stdio: 'ignore',
26
- });
27
- } catch (e: any) {
28
- err = e;
29
- }
30
-
31
- expect(err).to.be.instanceof(Error);
32
- expect(err)
33
- .to.have.property('message')
34
- .match(/missing stdin/);
35
- });
36
-
37
- it('should resolve with a child process', async function () {
38
- spawned = await spawnChildFromSource('');
39
- expect(spawned).to.be.instanceof((childProcess as any).ChildProcess);
40
- });
41
-
42
- it('should spawn a process with an ipc channel open', async function () {
43
- spawned = await spawnChildFromSource(
44
- 'process.on("message", (data) => process.send(data))'
45
- );
46
- spawned.send('Hi!');
47
- const [message] = await once(spawned, 'message');
48
- expect(message).to.equal('Hi!');
49
- });
50
-
51
- it('should fail if process exited before successfully starting', async function () {
52
- let err: Error;
53
-
54
- try {
55
- spawned = await spawnChildFromSource(
56
- 'throw new Error("Whoops!")',
57
- {},
58
- undefined,
59
- 'ignore',
60
- 'ignore'
61
- );
62
- } catch (e: any) {
63
- err = e;
64
- }
65
-
66
- expect(err).to.be.instanceof(Error);
67
- expect(err.message).to.match(
68
- /Child process exited with error before starting/
69
- );
70
- });
71
-
72
- it('should fail if a timeout exceeded before the process is "ready"', async function () {
73
- let err: Error;
74
-
75
- try {
76
- spawned = await spawnChildFromSource(
77
- 'let i = 0; while(++i < 10000000000){};',
78
- {},
79
- 10
80
- );
81
- } catch (e: any) {
82
- err = e;
83
- }
84
-
85
- expect(err).to.be.instanceof(Error);
86
- expect(err.message).to.match(
87
- /Timed out while waiting for child process to start/
88
- );
89
- });
90
- });
@@ -1,102 +0,0 @@
1
- import type {
2
- ChildProcess,
3
- Serializable,
4
- SpawnOptions,
5
- StdioNull,
6
- StdioPipe,
7
- } from 'child_process';
8
- import { spawn } from 'child_process';
9
- import { once } from 'events';
10
-
11
- export async function kill(
12
- childProcess: ChildProcess,
13
- code: NodeJS.Signals | number = 'SIGTERM'
14
- ) {
15
- childProcess.kill(code);
16
- if (childProcess.exitCode === null && childProcess.signalCode === null) {
17
- await once(childProcess, 'exit');
18
- }
19
- }
20
-
21
- export default function spawnChildFromSource(
22
- src: string,
23
- spawnOptions: Omit<SpawnOptions, 'stdio'> = {},
24
- timeoutMs?: number,
25
- _stdout: StdioNull | StdioPipe = 'inherit',
26
- _stderr: StdioNull | StdioPipe = 'inherit'
27
- ): Promise<ChildProcess> {
28
- return new Promise((resolve, reject) => {
29
- const readyToken = Date.now().toString(32);
30
-
31
- const childProcess = spawn(process.execPath, {
32
- stdio: ['pipe', _stdout, _stderr, 'ipc'],
33
- ...spawnOptions,
34
- });
35
-
36
- if (!childProcess.stdin) {
37
- kill(childProcess)
38
- .then(() => {
39
- reject(
40
- new Error("Can't write src to the spawned process, missing stdin")
41
- );
42
- })
43
- .catch((err: any) => {
44
- reject(err);
45
- });
46
- return;
47
- }
48
-
49
- // eslint-disable-next-line prefer-const
50
- let timeoutId: NodeJS.Timeout | null;
51
-
52
- function cleanupListeners() {
53
- if (timeoutId) {
54
- clearTimeout(timeoutId);
55
- }
56
- if (childProcess.stdin) {
57
- childProcess.stdin.off('error', onWriteError);
58
- }
59
- childProcess.off('message', onMessage);
60
- childProcess.off('exit', onExit);
61
- }
62
-
63
- function onExit(exitCode: number | null) {
64
- if (exitCode && exitCode > 0) {
65
- cleanupListeners();
66
- reject(new Error('Child process exited with error before starting'));
67
- }
68
- }
69
-
70
- /* really hard to reproduce in tests and coverage is not happy */
71
- /* istanbul ignore next */
72
- async function onWriteError(error: Error) {
73
- cleanupListeners();
74
- await kill(childProcess);
75
- reject(error);
76
- }
77
-
78
- async function onTimeout() {
79
- cleanupListeners();
80
- await kill(childProcess);
81
- reject(new Error('Timed out while waiting for child process to start'));
82
- }
83
-
84
- function onMessage(data: Serializable) {
85
- if (data === readyToken) {
86
- cleanupListeners();
87
- resolve(childProcess);
88
- }
89
- }
90
-
91
- childProcess.on('message', onMessage);
92
- childProcess.on('exit', onExit);
93
- childProcess.stdin.on('error', onWriteError);
94
-
95
- childProcess.stdin.write(src);
96
- childProcess.stdin.write(`;process.send(${JSON.stringify(readyToken)})`);
97
- childProcess.stdin.end();
98
-
99
- timeoutId =
100
- timeoutMs !== undefined ? setTimeout(onTimeout, timeoutMs) : null;
101
- });
102
- }
@@ -1,11 +0,0 @@
1
- {
2
- "extends": "@mongodb-js/tsconfig-mongosh/tsconfig.test.json",
3
- "ts-node": {
4
- "files": true
5
- },
6
- "compilerOptions": {
7
- "outDir": "./lib",
8
- "allowJs": false
9
- },
10
- "files": ["./src/index.d.ts"]
11
- }