Files
misskey/packages/backend/src/boot/entry.ts
T
おさむのひと 3de6b610b5 enhance: JSON形式の構造化ログ出力に対応 (#17728)
* enhance: JSON形式の構造化ログ出力に対応

* 起動時ログがJSON化出来ていなかったのを調整

---------

Co-authored-by: syuilo <4439005+syuilo@users.noreply.github.com>
2026-07-17 12:45:26 +09:00

127 lines
3.5 KiB
TypeScript

/*
* SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
/**
* Misskey Entry Point!
*/
import cluster from 'node:cluster';
import { EventEmitter } from 'node:events';
import { writeHeapSnapshot } from 'node:v8';
import Xev from 'xev';
import Logger from '@/logger.js';
import { envOption } from '../env.js';
import { installProcessErrorHandlers } from './process-error-handler.js';
import { isShutdownInProgress } from './shutdown-handler.js';
import { readyRef } from './ready.js';
import 'reflect-metadata';
process.title = `Misskey (${cluster.isPrimary ? 'master' : 'worker'})`;
Error.stackTraceLimit = Infinity;
EventEmitter.defaultMaxListeners = 128;
const logger = new Logger('core', 'cyan');
const clusterLogger = logger.createSubLogger('cluster', 'orange');
const ev = new Xev();
installProcessErrorHandlers({ logger, quiet: envOption.quiet });
//#region Events
// Listen new workers
cluster.on('fork', worker => {
clusterLogger.debug(`Process forked: [${worker.id}]`);
});
// Listen online workers
cluster.on('online', worker => {
clusterLogger.debug(`Process is now online: [${worker.id}]`);
});
// Listen for dying workers
cluster.on('exit', worker => {
if (isShutdownInProgress()) {
clusterLogger.info(`Process exited during shutdown: [${worker.id}]`);
return;
}
// 終了したワーカーは従来どおり再生成し、表示色は出力処理へ任せます。
clusterLogger.error(`[${worker.id}] died :(`);
cluster.fork();
});
// Dying away...
process.on('exit', code => {
if (isShutdownInProgress()) return;
logger.info(`The process is going to exit with code ${code}`);
});
//#endregion
if (!envOption.disableClustering) {
if (cluster.isPrimary) {
const { masterMain } = await import('./master.js');
await masterMain();
ev.mount();
} else if (cluster.isWorker) {
const { workerMain } = await import('./worker.js');
await workerMain();
} else {
throw new Error('Unknown process type');
}
} else {
// 非clusterの場合はMasterのみが起動するため、Workerの処理は行わない(cluster.isWorker === trueの状態でこのブロックに来ることはない)
const { masterMain } = await import('./master.js');
await masterMain();
ev.mount();
}
process.on('message', msg => {
if (msg === 'gc') {
if (global.gc != null) {
logger.info('Manual GC triggered');
for (let i = 0; i < 3; i++) {
global.gc();
}
if (process.send != null) process.send('gc ok');
} else {
logger.warn('Manual GC requested but gc is not available. Start the process with --expose-gc to enable this feature.');
if (process.send != null) process.send('gc unavailable');
}
} else if (msg === 'memory usage') {
if (process.send != null) {
process.send({
type: 'memory usage',
value: process.memoryUsage(),
});
}
} else if (msg != null && typeof msg === 'object' && 'type' in msg && msg.type === 'heap snapshot' && 'path' in msg && typeof msg.path === 'string') {
if (process.send != null) {
try {
const path = writeHeapSnapshot(msg.path);
process.send({
type: 'heap snapshot',
path,
});
} catch (err) {
process.send({
type: 'heap snapshot error',
message: err instanceof Error ? err.message : String(err),
});
}
}
}
});
readyRef.value = true;
// ユニットテスト時にMisskeyが子プロセスで起動された時のため
// それ以外のときは process.send は使えないので弾く
if (process.send) {
process.send('ok');
}