Skip to content

Commit 13384f8

Browse files
Merge pull request #49 from cloudbeds/fix/worker-termination
fix(compileTypesAsync): improve worker termination logic
2 parents 7c86483 + e4c8264 commit 13384f8

File tree

3 files changed

+32
-45
lines changed

3 files changed

+32
-45
lines changed

src/compileTypes/__tests__/compileTypesWorker.test.ts

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { afterEach, beforeEach, describe, expect, test, vi } from 'vitest';
33

44
import type { FederationConfig } from '../../models';
55
import { compileTypes } from '../compileTypes';
6-
import type { CompileTypesWorkerMessage, ExitMessage } from '../compileTypesWorker';
6+
import type { CompileTypesWorkerMessage } from '../compileTypesWorker';
77
import { rewritePathsWithExposedFederatedModules } from '../rewritePathsWithExposedFederatedModules';
88
import { workerLogger } from '../workerLogger';
99

@@ -34,7 +34,7 @@ describe('compileTypesWorker', () => {
3434
const mockCompileTypes = vi.mocked(compileTypes);
3535
const mockRewritePaths = vi.mocked(rewritePathsWithExposedFederatedModules);
3636

37-
let messageHandler: (message: CompileTypesWorkerMessage | ExitMessage) => void;
37+
let messageHandler: (message: CompileTypesWorkerMessage) => void;
3838

3939
beforeEach(async () => {
4040
vi.resetAllMocks();
@@ -56,16 +56,6 @@ describe('compileTypesWorker', () => {
5656
vi.resetModules();
5757
});
5858

59-
test('handles exit message', () => {
60-
const exitSpy = vi.spyOn(process, 'exit').mockImplementation(() => undefined as never);
61-
const exitMessage: ExitMessage = { type: 'exit' };
62-
63-
messageHandler(exitMessage);
64-
65-
expect(workerLogger.log).toHaveBeenCalledWith('Exiting by request');
66-
expect(exitSpy).toHaveBeenCalledWith(0);
67-
});
68-
6959
test('handles successful compilation and rewrite', () => {
7060
const workerMessage: CompileTypesWorkerMessage = {
7161
tsconfigPath: 'tsconfig.json',

src/compileTypes/compileTypesAsync.ts

Lines changed: 28 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -7,68 +7,74 @@ import type {
77
CompileTypesWorkerResultMessage,
88
} from './compileTypesWorker';
99

10-
let worker: Worker | null = null;
11-
let workerIndex = 0;
10+
const activeWorkers = new Map<number, Worker>();
11+
let workerIndex = 1;
1212

1313
export function compileTypesAsync(
1414
params: CompileTypesWorkerMessage,
1515
loggerHint = '',
1616
): Promise<void> {
1717
const logger = getLogger();
18-
workerIndex++;
19-
const innerWorkerIndex = workerIndex;
2018

21-
return new Promise((resolve, reject) => {
22-
if (worker) {
23-
logger.log(`Terminating existing worker process #${innerWorkerIndex}`);
24-
worker.postMessage({ type: 'exit' });
25-
}
19+
activeWorkers.forEach((worker, index) => {
20+
logger.log(`Terminating existing worker process #${index}`);
21+
worker.terminate();
22+
});
23+
activeWorkers.clear();
2624

27-
const workerPath = path.join(__dirname, 'compileTypesWorker.js');
28-
worker = new Worker(workerPath);
25+
const currentWorkerIndex = workerIndex++;
26+
const worker = new Worker(path.join(__dirname, 'compileTypesWorker.js'));
27+
activeWorkers.set(currentWorkerIndex, worker);
2928

29+
return new Promise((resolve, reject) => {
3030
worker.on('message', (result: CompileTypesWorkerResultMessage) => {
3131
switch (result.status) {
3232
case 'log':
33-
logger[result.level](`[Worker] run #${innerWorkerIndex}:`, result.message);
33+
logger[result.level](`[Worker] run #${currentWorkerIndex}:`, result.message);
3434
return;
3535
case 'success':
3636
resolve();
3737
break;
3838
case 'failure':
3939
logger.warn(
40-
`[Worker] run #${innerWorkerIndex}: Failed to compile types for exposed modules.`,
40+
`[Worker] run #${currentWorkerIndex}: Failed to compile types for exposed modules.`,
4141
loggerHint,
4242
);
4343
reject(new Error('Failed to compile types for exposed modules.'));
4444
break;
4545
case 'error':
4646
logger.warn(
47-
`[Worker] run #${innerWorkerIndex}: Error compiling types for exposed modules.`,
47+
`[Worker] run #${currentWorkerIndex}: Error compiling types for exposed modules.`,
4848
loggerHint,
4949
);
5050
reject(result.error);
5151
break;
52+
default:
53+
logger.error(`[Worker]: Received unknown status: ${(result as Dict).status}`);
54+
break;
5255
}
53-
worker?.postMessage({ type: 'exit' });
54-
worker = null;
56+
57+
worker.terminate();
5558
});
5659

5760
worker.on('error', error => {
58-
logger.warn(`[Worker] run #${innerWorkerIndex}: Unexpected error.`, loggerHint);
61+
logger.warn(`[Worker] run #${currentWorkerIndex}: Unexpected error.`, loggerHint);
5962
logger.log(error);
6063
reject(error);
61-
worker?.postMessage({ type: 'exit' });
62-
worker = null;
64+
worker.terminate();
6365
});
6466

6567
worker.on('exit', code => {
66-
if (code === null || code === 0) {
68+
const isActiveWorker = activeWorkers.has(currentWorkerIndex);
69+
if (isActiveWorker) {
70+
activeWorkers.delete(currentWorkerIndex);
71+
}
72+
73+
if (!code || !isActiveWorker) {
6774
resolve();
6875
} else {
69-
reject(new Error(`[Worker] run #${innerWorkerIndex}: Process exited with code ${code}`));
76+
reject(new Error(`[Worker] run #${currentWorkerIndex}: Process exited with code ${code}`));
7077
}
71-
worker = null;
7278
});
7379

7480
worker.postMessage(params);

src/compileTypes/compileTypesWorker.ts

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -14,23 +14,14 @@ export type CompileTypesWorkerMessage = CompileTypesParams & {
1414
federationConfig: FederationConfig;
1515
};
1616

17-
export type ExitMessage = {
18-
type: 'exit';
19-
};
20-
2117
export type CompileTypesWorkerResultMessage =
2218
| { status: 'success' }
2319
| { status: 'failure' }
2420
| CompileTypesWorkerResultMessageError
2521
| { status: 'log'; level: LogLevel; message: string };
2622

27-
parentPort?.on('message', (message: CompileTypesWorkerMessage | ExitMessage) => {
28-
if ((message as ExitMessage).type === 'exit') {
29-
workerLogger.log('Exiting by request');
30-
process.exit(0);
31-
}
32-
33-
const { federationConfig, ...params } = message as CompileTypesWorkerMessage;
23+
parentPort?.on('message', (message: CompileTypesWorkerMessage) => {
24+
const { federationConfig, ...params } = message;
3425

3526
try {
3627
const startTime = performance.now();

0 commit comments

Comments
 (0)