From cba2c2fd7a281446498d66611ee492c56a731be2 Mon Sep 17 00:00:00 2001 From: Remi Date: Wed, 28 Oct 2020 16:22:35 +0100 Subject: [PATCH] feat(jest-worker): factory pattern --- packages/jest-haste-map/src/index.ts | 44 ++++++++++-------- .../jest-reporters/src/coverage_reporter.ts | 2 +- packages/jest-runner/src/index.ts | 4 +- packages/jest-worker/README.md | 6 +-- .../src/__performance_tests__/test.js | 13 ++++-- packages/jest-worker/src/index.ts | 46 +++++++++++++------ 6 files changed, 71 insertions(+), 44 deletions(-) diff --git a/packages/jest-haste-map/src/index.ts b/packages/jest-haste-map/src/index.ts index f0e4aa25e605..b0017c8e6200 100644 --- a/packages/jest-haste-map/src/index.ts +++ b/packages/jest-haste-map/src/index.ts @@ -546,14 +546,16 @@ class HasteMap extends EventEmitter { if (this._options.retainAllFiles && filePath.includes(NODE_MODULES)) { if (computeSha1) { return this._getWorker(workerOptions) - .getSha1({ - computeDependencies: this._options.computeDependencies, - computeSha1, - dependencyExtractor: this._options.dependencyExtractor, - filePath, - hasteImplModulePath: this._options.hasteImplModulePath, - rootDir, - }) + .then(workerInstance => + workerInstance.getSha1({ + computeDependencies: this._options.computeDependencies, + computeSha1, + dependencyExtractor: this._options.dependencyExtractor, + filePath, + hasteImplModulePath: this._options.hasteImplModulePath, + rootDir, + }), + ) .then(workerReply, workerError); } @@ -622,14 +624,16 @@ class HasteMap extends EventEmitter { } return this._getWorker(workerOptions) - .worker({ - computeDependencies: this._options.computeDependencies, - computeSha1, - dependencyExtractor: this._options.dependencyExtractor, - filePath, - hasteImplModulePath: this._options.hasteImplModulePath, - rootDir, - }) + .then(workerInstance => + workerInstance.worker({ + computeDependencies: this._options.computeDependencies, + computeSha1, + dependencyExtractor: this._options.dependencyExtractor, + filePath, + hasteImplModulePath: this._options.hasteImplModulePath, + rootDir, + }), + ) .then(workerReply, workerError); } @@ -714,17 +718,19 @@ class HasteMap extends EventEmitter { /** * Creates workers or parses files and extracts metadata in-process. */ - private _getWorker(options?: {forceInBand: boolean}): WorkerInterface { + private async _getWorker(options?: { + forceInBand: boolean; + }): Promise { if (!this._worker) { if ((options && options.forceInBand) || this._options.maxWorkers <= 1) { this._worker = {getSha1, worker}; } else { // @ts-expect-error: assignment of a worker with custom properties. - this._worker = new Worker(require.resolve('./worker'), { + this._worker = (await Worker.create(require.resolve('./worker'), { exposedMethods: ['getSha1', 'worker'], maxRetries: 3, numWorkers: this._options.maxWorkers, - }) as WorkerInterface; + })) as WorkerInterface; } } diff --git a/packages/jest-reporters/src/coverage_reporter.ts b/packages/jest-reporters/src/coverage_reporter.ts index 9e1918bc8726..86633f7681be 100644 --- a/packages/jest-reporters/src/coverage_reporter.ts +++ b/packages/jest-reporters/src/coverage_reporter.ts @@ -151,7 +151,7 @@ export default class CoverageReporter extends BaseReporter { if (this._globalConfig.maxWorkers <= 1) { worker = require('./coverage_worker'); } else { - worker = new Worker(require.resolve('./coverage_worker'), { + worker = await Worker.create(require.resolve('./coverage_worker'), { exposedMethods: ['worker'], maxRetries: 2, numWorkers: this._globalConfig.maxWorkers, diff --git a/packages/jest-runner/src/index.ts b/packages/jest-runner/src/index.ts index b74d6842dbfd..c00b49cab94e 100644 --- a/packages/jest-runner/src/index.ts +++ b/packages/jest-runner/src/index.ts @@ -168,7 +168,7 @@ class TestRunner { } } - const worker = new Worker(TEST_WORKER_PATH, { + const worker = (await Worker.create(TEST_WORKER_PATH, { exposedMethods: ['worker'], forkOptions: {stdio: 'pipe'}, maxRetries: 3, @@ -178,7 +178,7 @@ class TestRunner { serializableResolvers: Array.from(resolvers.values()), }, ], - }) as WorkerInterface; + })) as WorkerInterface; if (worker.getStdout()) worker.getStdout().pipe(process.stdout); if (worker.getStderr()) worker.getStderr().pipe(process.stderr); diff --git a/packages/jest-worker/README.md b/packages/jest-worker/README.md index b12d5b1d2267..1c742b6953c7 100644 --- a/packages/jest-worker/README.md +++ b/packages/jest-worker/README.md @@ -24,7 +24,7 @@ This example covers the minimal usage: import JestWorker from 'jest-worker'; async function main() { - const worker = new JestWorker(require.resolve('./Worker')); + const worker = await JestWorker.create(require.resolve('./Worker')); const result = await worker.hello('Alice'); // "Hello, Alice" } @@ -144,7 +144,7 @@ This example covers the standard usage: import JestWorker from 'jest-worker'; async function main() { - const myWorker = new JestWorker(require.resolve('./Worker'), { + const myWorker = await JestWorker.create(require.resolve('./Worker'), { exposedMethods: ['foo', 'bar', 'getWorkerId'], numWorkers: 4, }); @@ -188,7 +188,7 @@ This example covers the usage with a `computeWorkerKey` method: import JestWorker from 'jest-worker'; async function main() { - const myWorker = new JestWorker(require.resolve('./Worker'), { + const myWorker = await JestWorker.create(require.resolve('./Worker'), { computeWorkerKey: (method, filename) => filename, }); diff --git a/packages/jest-worker/src/__performance_tests__/test.js b/packages/jest-worker/src/__performance_tests__/test.js index 3a688eae05e4..8be80a08b8fa 100644 --- a/packages/jest-worker/src/__performance_tests__/test.js +++ b/packages/jest-worker/src/__performance_tests__/test.js @@ -93,11 +93,14 @@ function testJestWorker() { } } - const farm = new JestWorker(require.resolve('./workers/jest_worker'), { - exposedMethods: [method], - forkOptions: {execArgv: []}, - workers: threads, - }); + const farm = await JestWorker.create( + require.resolve('./workers/jest_worker'), + { + exposedMethods: [method], + forkOptions: {execArgv: []}, + workers: threads, + }, + ); farm.getStdout().pipe(process.stdout); farm.getStderr().pipe(process.stderr); diff --git a/packages/jest-worker/src/index.ts b/packages/jest-worker/src/index.ts index 0466cea3a32a..564373dd5f6e 100644 --- a/packages/jest-worker/src/index.ts +++ b/packages/jest-worker/src/index.ts @@ -79,8 +79,6 @@ export default class JestWorker { this._options = {...options}; this._ending = false; - this._inspectorSession = this.setUpInspector(); - const workerPoolOptions: WorkerPoolOptions = { enableWorkerThreads: this._options.enableWorkerThreads ?? false, forkOptions: this._options.forkOptions ?? {}, @@ -111,19 +109,39 @@ export default class JestWorker { this._bindExposedWorkerMethods(workerPath, this._options); } - private setUpInspector() { - // Open V8 Inspector - inspector.open(); + public static create = async ( + workerPath: string, + options?: FarmOptions, + ): Promise => { + const setUpInspector = async () => { + // Open V8 Inspector + inspector.open(); + + const inspectorUrl = inspector.url(); + if (inspectorUrl) { + const session = new inspector.Session(); + session.connect(); + await new Promise((resolve, reject) => { + session.post('Debugger.enable', (err: Error) => { + if (err === null) { + resolve(); + } else { + reject(err); + } + }); + }); + return session; + } + return undefined; + }; + + const jestWorker = new JestWorker(workerPath, options); + const inspectorSession = await setUpInspector(); - const inspectorUrl = inspector.url(); - let session; - if (inspectorUrl !== undefined) { - session = new inspector.Session(); - session.connect(); - session.post('Debugger.enable'); - } - return session; - } + jestWorker._inspectorSession = inspectorSession; + + return jestWorker; + }; private _bindExposedWorkerMethods( workerPath: string,