Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add unique id for each worker and pass it to the child process #5494

Merged
merged 6 commits into from
Feb 8, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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