neex 0.6.64 → 0.6.66
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/dist/src/start-manager.js +87 -80
- package/package.json +1 -1
|
@@ -159,90 +159,98 @@ class StartManager {
|
|
|
159
159
|
this.log(`Process started (PID: ${this.masterProcess.pid}, Port: ${port})`);
|
|
160
160
|
}
|
|
161
161
|
}
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
const
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
}
|
|
222
|
-
|
|
162
|
+
startWorker(workerId) {
|
|
163
|
+
return new Promise((resolve, reject) => {
|
|
164
|
+
var _a, _b;
|
|
165
|
+
const nodeArgs = this.getNodeArgs();
|
|
166
|
+
const port = this.options.port || 8000;
|
|
167
|
+
const env = {
|
|
168
|
+
...process.env,
|
|
169
|
+
NODE_ENV: process.env.NODE_ENV || 'production',
|
|
170
|
+
WORKER_ID: workerId.toString(),
|
|
171
|
+
PORT: port.toString(),
|
|
172
|
+
CLUSTER_WORKER: 'true',
|
|
173
|
+
FORCE_COLOR: this.options.color ? '1' : '0',
|
|
174
|
+
NODE_OPTIONS: '--no-deprecation'
|
|
175
|
+
};
|
|
176
|
+
const workerProcess = (0, child_process_1.fork)(this.options.file, [], {
|
|
177
|
+
cwd: this.options.workingDir,
|
|
178
|
+
env,
|
|
179
|
+
execArgv: nodeArgs,
|
|
180
|
+
silent: true
|
|
181
|
+
});
|
|
182
|
+
const workerInfo = {
|
|
183
|
+
process: workerProcess,
|
|
184
|
+
pid: workerProcess.pid,
|
|
185
|
+
restarts: 0,
|
|
186
|
+
startTime: new Date(),
|
|
187
|
+
id: workerId,
|
|
188
|
+
port: port
|
|
189
|
+
};
|
|
190
|
+
this.workers.set(workerId, workerInfo);
|
|
191
|
+
let isReady = false;
|
|
192
|
+
const readinessTimeout = setTimeout(() => {
|
|
193
|
+
if (!isReady) {
|
|
194
|
+
workerProcess.kill();
|
|
195
|
+
reject(new Error(`Worker ${workerId} failed to become ready within 15s.`));
|
|
196
|
+
}
|
|
197
|
+
}, 15000);
|
|
198
|
+
const cleanupReadinessListeners = () => {
|
|
199
|
+
var _a;
|
|
200
|
+
clearTimeout(readinessTimeout);
|
|
201
|
+
(_a = workerProcess.stdout) === null || _a === void 0 ? void 0 : _a.removeListener('data', onDataForReady);
|
|
202
|
+
workerProcess.removeListener('message', onMessageForReady);
|
|
203
|
+
};
|
|
204
|
+
const onReady = () => {
|
|
205
|
+
if (isReady)
|
|
206
|
+
return;
|
|
207
|
+
isReady = true;
|
|
208
|
+
cleanupReadinessListeners();
|
|
209
|
+
if (this.options.verbose) {
|
|
210
|
+
this.log(`Worker ${workerId} is ready (PID: ${workerProcess.pid})`);
|
|
211
|
+
}
|
|
212
|
+
resolve(workerInfo);
|
|
213
|
+
};
|
|
214
|
+
const onDataForReady = (data) => {
|
|
215
|
+
const message = data.toString();
|
|
216
|
+
const prefix = chalk_1.default.dim(`[Worker ${workerId}] `);
|
|
217
|
+
process.stdout.write(prefix + message);
|
|
218
|
+
if (/listening|ready|running on port|local:/i.test(message)) {
|
|
219
|
+
onReady();
|
|
220
|
+
}
|
|
221
|
+
};
|
|
222
|
+
const onMessageForReady = (message) => {
|
|
223
223
|
if (message && message.type === 'ready') {
|
|
224
|
-
|
|
225
|
-
resolve();
|
|
224
|
+
onReady();
|
|
226
225
|
}
|
|
226
|
+
};
|
|
227
|
+
(_a = workerProcess.stdout) === null || _a === void 0 ? void 0 : _a.on('data', onDataForReady);
|
|
228
|
+
(_b = workerProcess.stderr) === null || _b === void 0 ? void 0 : _b.on('data', (data) => {
|
|
229
|
+
const prefix = chalk_1.default.red.dim(`[Worker ${workerId}] `);
|
|
230
|
+
process.stderr.write(prefix + data.toString());
|
|
227
231
|
});
|
|
232
|
+
workerProcess.on('message', onMessageForReady);
|
|
228
233
|
workerProcess.on('error', (error) => {
|
|
229
|
-
|
|
230
|
-
|
|
234
|
+
if (!isReady) {
|
|
235
|
+
cleanupReadinessListeners();
|
|
236
|
+
reject(error);
|
|
237
|
+
}
|
|
238
|
+
this.log(`Worker ${workerId} error: ${error.message}`, 'error');
|
|
231
239
|
});
|
|
232
|
-
workerProcess.on('exit', (code) => {
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
reject(new Error(`Worker ${workerId} exited with code ${code}
|
|
240
|
+
workerProcess.on('exit', (code, signal) => {
|
|
241
|
+
if (!isReady) {
|
|
242
|
+
cleanupReadinessListeners();
|
|
243
|
+
reject(new Error(`Worker ${workerId} exited with code ${code} before becoming ready.`));
|
|
236
244
|
}
|
|
237
245
|
else {
|
|
238
|
-
|
|
246
|
+
this.workers.delete(workerId);
|
|
247
|
+
if (!this.isShuttingDown && code !== 0 && signal !== 'SIGTERM') {
|
|
248
|
+
this.log(`Worker ${workerId} crashed (code: ${code}, signal: ${signal})`, 'error');
|
|
249
|
+
this.restartWorker(workerId);
|
|
250
|
+
}
|
|
239
251
|
}
|
|
240
252
|
});
|
|
241
253
|
});
|
|
242
|
-
if (this.options.verbose) {
|
|
243
|
-
this.log(`Worker ${workerId} started (PID: ${workerProcess.pid})`);
|
|
244
|
-
}
|
|
245
|
-
return workerInfo;
|
|
246
254
|
}
|
|
247
255
|
async restartWorker(workerId) {
|
|
248
256
|
const workerInfo = this.workers.get(workerId);
|
|
@@ -290,16 +298,20 @@ class StartManager {
|
|
|
290
298
|
return;
|
|
291
299
|
}
|
|
292
300
|
// Multi-worker mode
|
|
301
|
+
this.log(`${chalk_1.default.blue(figures_1.default.play)} Starting production server (${this.options.workers} workers)`);
|
|
293
302
|
const startPromises = [];
|
|
294
303
|
for (let i = 0; i < this.options.workers; i++) {
|
|
295
304
|
startPromises.push(this.startWorker(i + 1));
|
|
296
305
|
}
|
|
297
306
|
try {
|
|
298
307
|
await Promise.all(startPromises);
|
|
308
|
+
this.log(`${chalk_1.default.green(figures_1.default.tick)} Server ready on port ${this.options.port || 8000} (${this.workers.size} workers)`);
|
|
299
309
|
}
|
|
300
310
|
catch (error) {
|
|
301
311
|
this.log(`Failed to start some workers: ${error.message}`, 'error');
|
|
302
|
-
|
|
312
|
+
if (this.workers.size > 0) {
|
|
313
|
+
this.log(`${chalk_1.default.yellow(figures_1.default.warning)} Server partially ready on port ${this.options.port || 8000} (${this.workers.size} workers)`);
|
|
314
|
+
}
|
|
303
315
|
}
|
|
304
316
|
}
|
|
305
317
|
setupHealthCheck() {
|
|
@@ -420,11 +432,6 @@ class StartManager {
|
|
|
420
432
|
this.setupWatcher();
|
|
421
433
|
// Start the application
|
|
422
434
|
await this.startCluster();
|
|
423
|
-
// Success message
|
|
424
|
-
const port = this.options.port || 8000;
|
|
425
|
-
const workerInfo = this.options.workers === 1 ?
|
|
426
|
-
'' : ` (${this.workers.size} workers)`;
|
|
427
|
-
logger_manager_js_1.loggerManager.printLine(`${chalk_1.default.green(figures_1.default.tick)} Server ready on port ${port}${workerInfo}`, 'info');
|
|
428
435
|
}
|
|
429
436
|
catch (error) {
|
|
430
437
|
this.log(`Failed to start server: ${error.message}`, 'error');
|