@mui/internal-docs-infra 0.12.1-canary.43 → 0.12.1-canary.44
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.
- package/cli/runValidate.d.mts +3 -0
- package/cli/runValidate.mjs +51 -3
- package/cli/validateWorker.d.mts +6 -0
- package/cli/validateWorker.mjs +7 -1
- package/package.json +2 -2
- package/pipeline/loadServerTypesMeta/socketClient.d.mts +4 -13
- package/pipeline/loadServerTypesMeta/socketClient.mjs +56 -70
- package/pipeline/loadServerTypesMeta/workerManager.d.mts +2 -2
- package/pipeline/loadServerTypesMeta/workerManager.mjs +28 -22
package/cli/runValidate.d.mts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { CommandModule } from 'yargs';
|
|
2
|
+
import { Worker } from 'node:worker_threads';
|
|
2
3
|
type Args = {
|
|
3
4
|
paths?: string[];
|
|
4
5
|
command?: string;
|
|
@@ -7,5 +8,7 @@ type Args = {
|
|
|
7
8
|
perf?: boolean;
|
|
8
9
|
notableMs?: number;
|
|
9
10
|
};
|
|
11
|
+
export declare function shutdownWorker(worker: Worker, timeoutMs?: number): Promise<void>;
|
|
12
|
+
export declare function shutdownWorkers(workers: Worker[]): Promise<void>;
|
|
10
13
|
declare const runValidate: CommandModule<{}, Args>;
|
|
11
14
|
export default runValidate;
|
package/cli/runValidate.mjs
CHANGED
|
@@ -16,6 +16,51 @@ import { ensureDemoClients } from "./ensureDemoClients.mjs";
|
|
|
16
16
|
import { ensureDemoPages } from "./ensureDemoPages.mjs";
|
|
17
17
|
const completeMessage = message => `✓ ${chalk.green(message)}`;
|
|
18
18
|
const functionName = 'Run Validate';
|
|
19
|
+
export async function shutdownWorker(worker, timeoutMs = 5000) {
|
|
20
|
+
if (worker.threadId === -1) {
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
await new Promise(resolve => {
|
|
24
|
+
let handleMessage;
|
|
25
|
+
let settled = false;
|
|
26
|
+
let timeout;
|
|
27
|
+
const finish = () => {
|
|
28
|
+
if (settled) {
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
settled = true;
|
|
32
|
+
if (timeout) {
|
|
33
|
+
clearTimeout(timeout);
|
|
34
|
+
}
|
|
35
|
+
worker.off('message', handleMessage);
|
|
36
|
+
worker.off('error', finish);
|
|
37
|
+
worker.off('exit', finish);
|
|
38
|
+
resolve();
|
|
39
|
+
};
|
|
40
|
+
handleMessage = result => {
|
|
41
|
+
if (result.type === 'shutdown') {
|
|
42
|
+
finish();
|
|
43
|
+
}
|
|
44
|
+
};
|
|
45
|
+
timeout = setTimeout(finish, timeoutMs);
|
|
46
|
+
worker.on('message', handleMessage);
|
|
47
|
+
worker.once('error', finish);
|
|
48
|
+
worker.once('exit', finish);
|
|
49
|
+
|
|
50
|
+
// The worker may have exited between the initial check and listener setup.
|
|
51
|
+
if (worker.threadId === -1) {
|
|
52
|
+
finish();
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
worker.postMessage({
|
|
56
|
+
type: 'shutdown'
|
|
57
|
+
});
|
|
58
|
+
});
|
|
59
|
+
await worker.terminate();
|
|
60
|
+
}
|
|
61
|
+
export async function shutdownWorkers(workers) {
|
|
62
|
+
await Promise.all(workers.map(worker => shutdownWorker(worker)));
|
|
63
|
+
}
|
|
19
64
|
|
|
20
65
|
/**
|
|
21
66
|
* Recursively find all files matching a specific name in a directory
|
|
@@ -143,6 +188,9 @@ const runValidate = {
|
|
|
143
188
|
let taskIdCounter = 0;
|
|
144
189
|
for (const worker of workers) {
|
|
145
190
|
worker.on('message', result => {
|
|
191
|
+
if (result.type === 'shutdown') {
|
|
192
|
+
return;
|
|
193
|
+
}
|
|
146
194
|
const resolve = pendingResults.get(result.taskId);
|
|
147
195
|
if (resolve) {
|
|
148
196
|
pendingResults.delete(result.taskId);
|
|
@@ -407,11 +455,11 @@ const runValidate = {
|
|
|
407
455
|
currentMark = pagesMark;
|
|
408
456
|
}
|
|
409
457
|
} finally {
|
|
410
|
-
//
|
|
411
|
-
await
|
|
458
|
+
// Let each validation worker release its types-server election lock before exit.
|
|
459
|
+
await shutdownWorkers(workers);
|
|
412
460
|
|
|
413
461
|
// Terminate the types meta worker manager to allow the process to exit
|
|
414
|
-
terminateWorkerManager();
|
|
462
|
+
await terminateWorkerManager();
|
|
415
463
|
}
|
|
416
464
|
if (observer) {
|
|
417
465
|
// Flush any remaining performance entries before disconnecting
|
package/cli/validateWorker.d.mts
CHANGED
|
@@ -22,6 +22,9 @@ interface TypesTask {
|
|
|
22
22
|
syncTypesOptions: Omit<SyncTypesOptions, 'typesMarkdownPath' | 'rootContext' | 'variants'>;
|
|
23
23
|
rootContext: string;
|
|
24
24
|
}
|
|
25
|
+
export interface ShutdownTask {
|
|
26
|
+
type: 'shutdown';
|
|
27
|
+
}
|
|
25
28
|
interface SerializedPerfEntry {
|
|
26
29
|
name: string;
|
|
27
30
|
duration: number;
|
|
@@ -42,6 +45,9 @@ interface TypesResult {
|
|
|
42
45
|
perfEntries?: SerializedPerfEntry[];
|
|
43
46
|
error?: string;
|
|
44
47
|
}
|
|
48
|
+
export interface ShutdownResult {
|
|
49
|
+
type: 'shutdown';
|
|
50
|
+
}
|
|
45
51
|
export type ValidateTask = IndexTask | TypesTask;
|
|
46
52
|
export type ValidateResult = IndexResult | TypesResult;
|
|
47
53
|
export {};
|
package/cli/validateWorker.mjs
CHANGED
|
@@ -8,6 +8,7 @@ import remarkMdx from 'remark-mdx';
|
|
|
8
8
|
import { transformMarkdownMetadata } from "../pipeline/transformMarkdownMetadata/transformMarkdownMetadata.mjs";
|
|
9
9
|
import { parseCreateFactoryCall } from "../pipeline/parseCreateFactoryCall/parseCreateFactoryCall.mjs";
|
|
10
10
|
import { syncTypes } from "../pipeline/syncTypes/syncTypes.mjs";
|
|
11
|
+
import { terminateWorkerManager } from "../pipeline/loadServerTypesMeta/workerManager.mjs";
|
|
11
12
|
function collectPerfEntries() {
|
|
12
13
|
const entries = performance.getEntriesByType('measure').map(entry => ({
|
|
13
14
|
name: entry.name,
|
|
@@ -22,7 +23,12 @@ if (parentPort) {
|
|
|
22
23
|
let taskQueue = Promise.resolve();
|
|
23
24
|
parentPort.on('message', task => {
|
|
24
25
|
taskQueue = taskQueue.then(async () => {
|
|
25
|
-
if (task.type === '
|
|
26
|
+
if (task.type === 'shutdown') {
|
|
27
|
+
await terminateWorkerManager();
|
|
28
|
+
parentPort.postMessage({
|
|
29
|
+
type: 'shutdown'
|
|
30
|
+
});
|
|
31
|
+
} else if (task.type === 'index') {
|
|
26
32
|
try {
|
|
27
33
|
const processor = unified().use(remarkParse).use(remarkMdx).use(transformMarkdownMetadata, {
|
|
28
34
|
extractToIndex: task.processorOptions
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mui/internal-docs-infra",
|
|
3
|
-
"version": "0.12.1-canary.
|
|
3
|
+
"version": "0.12.1-canary.44",
|
|
4
4
|
"author": "MUI Team",
|
|
5
5
|
"description": "MUI Infra - internal documentation creation tools.",
|
|
6
6
|
"license": "MIT",
|
|
@@ -804,5 +804,5 @@
|
|
|
804
804
|
"bin": {
|
|
805
805
|
"docs-infra": "./cli/index.mjs"
|
|
806
806
|
},
|
|
807
|
-
"gitSha": "
|
|
807
|
+
"gitSha": "428843a303d23c4c904fc740058e33e1a8b95c85"
|
|
808
808
|
}
|
|
@@ -23,15 +23,6 @@ export declare function getLockPath(): string;
|
|
|
23
23
|
* Ensure the socket directory exists
|
|
24
24
|
*/
|
|
25
25
|
export declare function ensureSocketDir(): Promise<void>;
|
|
26
|
-
/**
|
|
27
|
-
* Wait for the IPC endpoint to become available.
|
|
28
|
-
* On Unix: Polls the filesystem for the socket file to appear. We avoid
|
|
29
|
-
* `fs.watch` here because on macOS it does not reliably fire events when a
|
|
30
|
-
* unix domain socket file is created.
|
|
31
|
-
* On Windows: Polls by attempting to connect to the named pipe.
|
|
32
|
-
* @param timeoutMs - Timeout in milliseconds (default: 5000)
|
|
33
|
-
*/
|
|
34
|
-
export declare function waitForSocketFile(timeoutMs?: number): Promise<void>;
|
|
35
26
|
/**
|
|
36
27
|
* Try to acquire the server lock using proper-lockfile
|
|
37
28
|
* Returns true if successfully acquired (this worker should be server)
|
|
@@ -42,8 +33,7 @@ export declare function tryAcquireServerLock(): Promise<boolean>;
|
|
|
42
33
|
*/
|
|
43
34
|
export declare function releaseServerLock(): Promise<void>;
|
|
44
35
|
/**
|
|
45
|
-
* Check
|
|
46
|
-
* Note: The socket server will clean up stale sockets on startup
|
|
36
|
+
* Check whether a types server is accepting connections, retrying for up to 500ms.
|
|
47
37
|
*/
|
|
48
38
|
export declare function hasExistingWorker(): Promise<boolean>;
|
|
49
39
|
/**
|
|
@@ -55,9 +45,10 @@ export declare class SocketClient {
|
|
|
55
45
|
private pendingRequests;
|
|
56
46
|
private buffer;
|
|
57
47
|
/**
|
|
58
|
-
* Connect to the worker socket
|
|
48
|
+
* Connect to the worker socket, retrying while the server starts or named-pipe
|
|
49
|
+
* instances are temporarily busy.
|
|
59
50
|
*/
|
|
60
|
-
connect(
|
|
51
|
+
connect(timeoutMs?: number, retryDelay?: number): Promise<void>;
|
|
61
52
|
/**
|
|
62
53
|
* Attempt to connect to the socket
|
|
63
54
|
*/
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
11
|
import { connect } from 'node:net';
|
|
12
|
-
import { mkdir
|
|
12
|
+
import { mkdir } from 'node:fs/promises';
|
|
13
13
|
import { createHash } from 'node:crypto';
|
|
14
14
|
import { tmpdir } from 'node:os';
|
|
15
15
|
import { join } from 'node:path';
|
|
@@ -92,22 +92,10 @@ export async function ensureSocketDir() {
|
|
|
92
92
|
}
|
|
93
93
|
|
|
94
94
|
/**
|
|
95
|
-
*
|
|
96
|
-
*/
|
|
97
|
-
async function fileExists(path) {
|
|
98
|
-
try {
|
|
99
|
-
await stat(path);
|
|
100
|
-
return true;
|
|
101
|
-
} catch {
|
|
102
|
-
return false;
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
/**
|
|
107
|
-
* Try to connect to a named pipe (Windows)
|
|
95
|
+
* Try to connect to an IPC endpoint.
|
|
108
96
|
* @returns true if connection succeeded, false otherwise
|
|
109
97
|
*/
|
|
110
|
-
function
|
|
98
|
+
function tryConnectToSocket(socketPath) {
|
|
111
99
|
return new Promise(resolve => {
|
|
112
100
|
const socket = connect(socketPath);
|
|
113
101
|
socket.on('connect', () => {
|
|
@@ -130,42 +118,25 @@ function sleep(ms) {
|
|
|
130
118
|
}
|
|
131
119
|
|
|
132
120
|
/**
|
|
133
|
-
*
|
|
134
|
-
* On Unix: Polls the filesystem for the socket file to appear. We avoid
|
|
135
|
-
* `fs.watch` here because on macOS it does not reliably fire events when a
|
|
136
|
-
* unix domain socket file is created.
|
|
137
|
-
* On Windows: Polls by attempting to connect to the named pipe.
|
|
138
|
-
* @param timeoutMs - Timeout in milliseconds (default: 5000)
|
|
121
|
+
* Poll an IPC endpoint until it accepts a connection or the timeout expires.
|
|
139
122
|
*/
|
|
140
|
-
|
|
141
|
-
const socketPath = getSocketPath();
|
|
123
|
+
async function waitForSocketConnection(socketPath, timeoutMs) {
|
|
142
124
|
const pollInterval = 50;
|
|
143
125
|
const startTime = Date.now();
|
|
144
|
-
|
|
145
|
-
while (Date.now() - startTime < timeoutMs) {
|
|
146
|
-
// eslint-disable-next-line no-await-in-loop
|
|
147
|
-
if (await tryConnectToPipe(socketPath)) {
|
|
148
|
-
return;
|
|
149
|
-
}
|
|
150
|
-
// eslint-disable-next-line no-await-in-loop
|
|
151
|
-
await sleep(pollInterval);
|
|
152
|
-
}
|
|
153
|
-
throw new Error(`Named pipe did not become available within ${timeoutMs}ms`);
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
// Ensure the directory exists so the first stat doesn't fail spuriously
|
|
157
|
-
await mkdir(getEffectiveSocketDir(), {
|
|
158
|
-
recursive: true
|
|
159
|
-
});
|
|
160
|
-
while (Date.now() - startTime < timeoutMs) {
|
|
126
|
+
do {
|
|
161
127
|
// eslint-disable-next-line no-await-in-loop
|
|
162
|
-
if (await
|
|
163
|
-
return;
|
|
128
|
+
if (await tryConnectToSocket(socketPath)) {
|
|
129
|
+
return true;
|
|
130
|
+
}
|
|
131
|
+
const remainingTime = timeoutMs - (Date.now() - startTime);
|
|
132
|
+
if (remainingTime <= 0) {
|
|
133
|
+
return false;
|
|
164
134
|
}
|
|
135
|
+
|
|
165
136
|
// eslint-disable-next-line no-await-in-loop
|
|
166
|
-
await sleep(pollInterval);
|
|
167
|
-
}
|
|
168
|
-
|
|
137
|
+
await sleep(Math.min(pollInterval, remainingTime));
|
|
138
|
+
} while (Date.now() - startTime < timeoutMs);
|
|
139
|
+
return false;
|
|
169
140
|
}
|
|
170
141
|
|
|
171
142
|
// Store the release function globally so we can call it when needed
|
|
@@ -182,14 +153,27 @@ export async function tryAcquireServerLock() {
|
|
|
182
153
|
await ensureSocketDir();
|
|
183
154
|
try {
|
|
184
155
|
// Try to acquire the lock with no retries (immediate check)
|
|
185
|
-
//
|
|
156
|
+
// Allow enough time for a server worker to start even when validation workers
|
|
157
|
+
// saturate the CPU and delay the lock heartbeat.
|
|
186
158
|
lockReleaseFunction = await lockfile.lock(lockPath, {
|
|
187
159
|
retries: 0,
|
|
188
160
|
// Don't retry, just check once
|
|
189
|
-
stale:
|
|
190
|
-
|
|
191
|
-
|
|
161
|
+
stale: 30_000,
|
|
162
|
+
realpath: false,
|
|
163
|
+
// Don't resolve symlinks (file doesn't need to exist)
|
|
164
|
+
onCompromised: error => {
|
|
165
|
+
console.error('[SocketClient] Server lock compromised:', error);
|
|
166
|
+
lockReleaseFunction = null;
|
|
167
|
+
}
|
|
192
168
|
});
|
|
169
|
+
|
|
170
|
+
// A worker that initialized earlier may have released the election lock after
|
|
171
|
+
// starting the server. Check the endpoint while holding the lock so late
|
|
172
|
+
// workers reuse that server instead of trying to listen on the same address.
|
|
173
|
+
if (await hasExistingWorker()) {
|
|
174
|
+
await releaseServerLock();
|
|
175
|
+
return false;
|
|
176
|
+
}
|
|
193
177
|
return true;
|
|
194
178
|
} catch (error) {
|
|
195
179
|
// Lock is already held by another worker
|
|
@@ -205,10 +189,11 @@ export async function tryAcquireServerLock() {
|
|
|
205
189
|
* Release the server lock
|
|
206
190
|
*/
|
|
207
191
|
export async function releaseServerLock() {
|
|
208
|
-
|
|
192
|
+
const release = lockReleaseFunction;
|
|
193
|
+
lockReleaseFunction = null;
|
|
194
|
+
if (release) {
|
|
209
195
|
try {
|
|
210
|
-
await
|
|
211
|
-
lockReleaseFunction = null;
|
|
196
|
+
await release();
|
|
212
197
|
} catch (error) {
|
|
213
198
|
// Ignore errors during cleanup
|
|
214
199
|
}
|
|
@@ -216,11 +201,12 @@ export async function releaseServerLock() {
|
|
|
216
201
|
}
|
|
217
202
|
|
|
218
203
|
/**
|
|
219
|
-
* Check
|
|
220
|
-
* Note: The socket server will clean up stale sockets on startup
|
|
204
|
+
* Check whether a types server is accepting connections, retrying for up to 500ms.
|
|
221
205
|
*/
|
|
222
206
|
export async function hasExistingWorker() {
|
|
223
|
-
|
|
207
|
+
// The election lock may have been released immediately before the server
|
|
208
|
+
// becomes connectable. Retry briefly before deciding to start another server.
|
|
209
|
+
return waitForSocketConnection(getSocketPath(), 500);
|
|
224
210
|
}
|
|
225
211
|
|
|
226
212
|
/**
|
|
@@ -233,25 +219,25 @@ export class SocketClient {
|
|
|
233
219
|
buffer = '';
|
|
234
220
|
|
|
235
221
|
/**
|
|
236
|
-
* Connect to the worker socket
|
|
222
|
+
* Connect to the worker socket, retrying while the server starts or named-pipe
|
|
223
|
+
* instances are temporarily busy.
|
|
237
224
|
*/
|
|
238
|
-
async connect(
|
|
225
|
+
async connect(timeoutMs = 30_000, retryDelay = 50) {
|
|
239
226
|
const socketPath = getSocketPath();
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
227
|
+
const startTime = Date.now();
|
|
228
|
+
while (true) {
|
|
229
|
+
try {
|
|
230
|
+
// eslint-disable-next-line no-await-in-loop
|
|
231
|
+
await this.attemptConnect(socketPath);
|
|
232
|
+
return;
|
|
233
|
+
} catch (error) {
|
|
234
|
+
if (Date.now() - startTime >= timeoutMs) {
|
|
235
|
+
throw error;
|
|
236
|
+
}
|
|
246
237
|
}
|
|
247
238
|
|
|
248
|
-
//
|
|
249
|
-
await
|
|
250
|
-
setTimeout(resolve, retryDelay);
|
|
251
|
-
});
|
|
252
|
-
|
|
253
|
-
// Recursive retry
|
|
254
|
-
await this.connect(retryCount + 1, maxRetries, retryDelay);
|
|
239
|
+
// eslint-disable-next-line no-await-in-loop
|
|
240
|
+
await sleep(retryDelay);
|
|
255
241
|
}
|
|
256
242
|
}
|
|
257
243
|
|
|
@@ -4,7 +4,7 @@ import type { WorkerRequest, WorkerResponse } from "./worker.mjs";
|
|
|
4
4
|
*/
|
|
5
5
|
export interface TypesProcessor {
|
|
6
6
|
processTypes(request: WorkerRequest): Promise<WorkerResponse>;
|
|
7
|
-
terminate(): void
|
|
7
|
+
terminate(): Promise<void>;
|
|
8
8
|
}
|
|
9
9
|
export declare function getWorkerManager(): TypesProcessor;
|
|
10
|
-
export declare function terminateWorkerManager(): void
|
|
10
|
+
export declare function terminateWorkerManager(): Promise<void>;
|
|
@@ -5,7 +5,7 @@ import path from 'path';
|
|
|
5
5
|
import { fileURLToPath } from 'url';
|
|
6
6
|
// eslint-disable-next-line n/prefer-node-protocol
|
|
7
7
|
import { isMainThread, Worker } from 'worker_threads';
|
|
8
|
-
import { SocketClient, tryAcquireServerLock, releaseServerLock
|
|
8
|
+
import { SocketClient, tryAcquireServerLock, releaseServerLock } from "./socketClient.mjs";
|
|
9
9
|
|
|
10
10
|
/**
|
|
11
11
|
* Shared interface for types processing managers.
|
|
@@ -73,9 +73,9 @@ class TypesMetaWorkerManager {
|
|
|
73
73
|
});
|
|
74
74
|
});
|
|
75
75
|
}
|
|
76
|
-
terminate() {
|
|
76
|
+
async terminate() {
|
|
77
77
|
if (this.worker) {
|
|
78
|
-
this.worker.terminate();
|
|
78
|
+
await this.worker.terminate();
|
|
79
79
|
this.worker = null;
|
|
80
80
|
}
|
|
81
81
|
this.pendingRequests.clear();
|
|
@@ -85,8 +85,7 @@ class TypesMetaWorkerManager {
|
|
|
85
85
|
/**
|
|
86
86
|
* Types processor for validate worker threads.
|
|
87
87
|
* On first processTypes() call, races to acquire the server lock:
|
|
88
|
-
* - Winner:
|
|
89
|
-
* naturally and becomes the socket server via existing worker.ts logic)
|
|
88
|
+
* - Winner: holds the lock and spawns a bare worker that becomes the socket server
|
|
90
89
|
* - Losers: skip spawning
|
|
91
90
|
*
|
|
92
91
|
* All workers then connect to the socket server as clients.
|
|
@@ -121,36 +120,43 @@ class WorkerThreadTypesProcessor {
|
|
|
121
120
|
this.serverWorker.on('error', error => {
|
|
122
121
|
console.error('[WorkerThreadTypesProcessor] Server worker error:', error);
|
|
123
122
|
});
|
|
123
|
+
}
|
|
124
|
+
this.socketClient = new SocketClient();
|
|
125
|
+
try {
|
|
126
|
+
// Establish the persistent client connection directly. A separate probe
|
|
127
|
+
// can consume an available Windows named-pipe instance and make the real
|
|
128
|
+
// connection fail under high concurrency.
|
|
129
|
+
await this.socketClient.connect();
|
|
130
|
+
} catch (error) {
|
|
131
|
+
this.socketClient?.close();
|
|
132
|
+
this.socketClient = null;
|
|
124
133
|
try {
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
134
|
+
if (this.serverWorker) {
|
|
135
|
+
await this.serverWorker.terminate();
|
|
136
|
+
}
|
|
137
|
+
} finally {
|
|
138
|
+
this.serverWorker = null;
|
|
139
|
+
if (isServer) {
|
|
140
|
+
await releaseServerLock();
|
|
141
|
+
}
|
|
132
142
|
}
|
|
133
|
-
|
|
134
|
-
} else {
|
|
135
|
-
// Another worker is the server — wait for the socket file.
|
|
136
|
-
await waitForSocketFile(30_000);
|
|
143
|
+
throw error;
|
|
137
144
|
}
|
|
138
|
-
this.socketClient = new SocketClient();
|
|
139
|
-
await this.socketClient.connect();
|
|
140
145
|
}
|
|
141
146
|
async processTypes(request) {
|
|
142
147
|
await this.ensureInit();
|
|
143
148
|
return this.socketClient.sendRequest(request);
|
|
144
149
|
}
|
|
145
|
-
terminate() {
|
|
150
|
+
async terminate() {
|
|
146
151
|
if (this.socketClient) {
|
|
147
152
|
this.socketClient.close();
|
|
148
153
|
this.socketClient = null;
|
|
149
154
|
}
|
|
150
155
|
if (this.serverWorker) {
|
|
151
|
-
this.serverWorker.terminate();
|
|
156
|
+
await this.serverWorker.terminate();
|
|
152
157
|
this.serverWorker = null;
|
|
153
158
|
}
|
|
159
|
+
await releaseServerLock();
|
|
154
160
|
}
|
|
155
161
|
}
|
|
156
162
|
|
|
@@ -171,10 +177,10 @@ export function getWorkerManager() {
|
|
|
171
177
|
}
|
|
172
178
|
return processObj[WORKER_MANAGER_KEY];
|
|
173
179
|
}
|
|
174
|
-
export function terminateWorkerManager() {
|
|
180
|
+
export async function terminateWorkerManager() {
|
|
175
181
|
const processObj = process;
|
|
176
182
|
if (processObj[WORKER_MANAGER_KEY]) {
|
|
177
|
-
processObj[WORKER_MANAGER_KEY].terminate();
|
|
183
|
+
await processObj[WORKER_MANAGER_KEY].terminate();
|
|
178
184
|
processObj[WORKER_MANAGER_KEY] = undefined;
|
|
179
185
|
}
|
|
180
186
|
}
|