Skip to content

Commit

Permalink
Add unique id for each worker and pass it to the child process (#5494)
Browse files Browse the repository at this point in the history
  • Loading branch information
ranyitz authored and mjesun committed Feb 8, 2018
1 parent c8d1c79 commit efec054
Show file tree
Hide file tree
Showing 7 changed files with 51 additions and 4 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
## master

### Features

* `[jest-worker]` Assign a unique id for each worker and pass it to the child
process. It will be available via `process.env.JEST_WORKER_ID`
([#5494](https://github.com/facebook/jest/pull/5494))

## jest 22.2.1

### Fixes
Expand Down
10 changes: 9 additions & 1 deletion packages/jest-worker/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,9 @@ overriding options through `forkOptions`.
Finishes the workers by killing all workers. No further calls can be done to the
`Worker` instance.

**Note:** Each worker has a unique id (index that starts with `1`) which is
available on `process.env.JEST_WORKER_ID`

# More examples

## Standard usage
Expand All @@ -143,12 +146,13 @@ import Worker from 'jest-worker';

async function main() {
const myWorker = new Worker(require.resolve('./worker'), {
exposedMethods: ['foo', 'bar'],
exposedMethods: ['foo', 'bar', 'getWorkerId'],
numWorkers: 4,
});

console.log(await myWorker.foo('Alice')); // "Hello from foo: Alice"
console.log(await myWorker.bar('Bob')); // "Hello from bar: Bob"
console.log(await myWorker.getWorkerId()); // "3" -> this message has sent from the 3rd worker

myWorker.end();
}
Expand All @@ -166,6 +170,10 @@ export function foo(param) {
export function bar(param) {
return 'Hello from bar: ' + param;
}

export function getWorkerId() {
return process.env.JEST_WORKER_ID;
}
```

## Bound worker usage:
Expand Down
16 changes: 16 additions & 0 deletions packages/jest-worker/src/__tests__/index.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -122,10 +122,26 @@ it('tries instantiating workers with the right options', () => {
expect(Worker.mock.calls[0][0]).toEqual({
forkOptions: {execArgv: []},
maxRetries: 6,
workerId: 1,
workerPath: '/tmp/baz.js',
});
});

it('create multiple workers with unique worker ids', () => {
// eslint-disable-next-line no-new
new Farm('/tmp/baz.js', {
exposedMethods: ['foo', 'bar'],
forkOptions: {execArgv: []},
maxRetries: 6,
numWorkers: 3,
});

expect(Worker).toHaveBeenCalledTimes(3);
expect(Worker.mock.calls[0][0].workerId).toEqual(1);
expect(Worker.mock.calls[1][0].workerId).toEqual(2);
expect(Worker.mock.calls[2][0].workerId).toEqual(3);
});

it('makes a non-existing relative worker throw', () => {
expect(
() =>
Expand Down
12 changes: 12 additions & 0 deletions packages/jest-worker/src/__tests__/worker.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ it('passes fork options down to child_process.fork, adding the defaults', () =>
execPath: 'hello',
},
maxRetries: 3,
workerId: process.env.JEST_WORKER_ID,
workerPath: '/tmp/foo/bar/baz.js',
});

Expand All @@ -70,6 +71,17 @@ it('passes fork options down to child_process.fork, adding the defaults', () =>
});
});

it('passes workerId to the child process and assign it to env.JEST_WORKER_ID', () => {
new Worker({
forkOptions: {},
maxRetries: 3,
workerId: 2,
workerPath: '/tmp/foo',
});

expect(childProcess.fork.mock.calls[0][1].env.JEST_WORKER_ID).toEqual(2);
});

it('initializes the child process with the given workerPath', () => {
new Worker({
forkOptions: {},
Expand Down
6 changes: 4 additions & 2 deletions packages/jest-worker/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -66,14 +66,16 @@ export default class {
workerPath = require.resolve(workerPath);
}

// Build the options once for all workers to avoid allocating extra objects.
const workerOptions = {
const sharedWorkerOptions = {
forkOptions: options.forkOptions || {},
maxRetries: options.maxRetries || 3,
workerPath,
};

for (let i = 0; i < numWorkers; i++) {
const workerOptions = Object.assign({}, sharedWorkerOptions, {
workerId: i + 1,
});
const worker = new Worker(workerOptions);
const workerStdout = worker.getStdout();
const workerStderr = worker.getStderr();
Expand Down
1 change: 1 addition & 0 deletions packages/jest-worker/src/types.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ export type FarmOptions = {
export type WorkerOptions = {|
forkOptions: ForkOptions,
maxRetries: number,
workerId: number,
workerPath: string,
|};

Expand Down
4 changes: 3 additions & 1 deletion packages/jest-worker/src/worker.js
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,9 @@ export default class {
Object.assign(
{
cwd: process.cwd(),
env: process.env,
env: Object.assign({}, process.env, {
JEST_WORKER_ID: this._options.workerId,
}),
// suppress --debug / --inspect flags while preserving others (like --harmony)
execArgv: process.execArgv.filter(v => !/^--(debug|inspect)/.test(v)),
silent: true,
Expand Down

0 comments on commit efec054

Please sign in to comment.