summaryrefslogtreecommitdiff
path: root/packages/backend/scripts
diff options
context:
space:
mode:
authormisskey-release-bot[bot] <157398866+misskey-release-bot[bot]@users.noreply.github.com>2025-12-06 12:22:58 +0000
committerGitHub <noreply@github.com>2025-12-06 12:22:58 +0000
commite40c84f31df0202351c5585d3edbca000846b73b (patch)
tree548eafb27b758c55de2e750a0ef9efbe3f056357 /packages/backend/scripts
parentMerge pull request #16840 from misskey-dev/develop (diff)
parentRelease: 2025.12.0 (diff)
downloadmisskey-e40c84f31df0202351c5585d3edbca000846b73b.tar.gz
misskey-e40c84f31df0202351c5585d3edbca000846b73b.tar.bz2
misskey-e40c84f31df0202351c5585d3edbca000846b73b.zip
Merge pull request #16916 from misskey-dev/develop
Release: 2025.12.0
Diffstat (limited to 'packages/backend/scripts')
-rw-r--r--packages/backend/scripts/compile_config.js54
-rw-r--r--packages/backend/scripts/dev.mjs2
-rw-r--r--packages/backend/scripts/measure-memory.mjs152
3 files changed, 207 insertions, 1 deletions
diff --git a/packages/backend/scripts/compile_config.js b/packages/backend/scripts/compile_config.js
new file mode 100644
index 0000000000..e78fa3dc9f
--- /dev/null
+++ b/packages/backend/scripts/compile_config.js
@@ -0,0 +1,54 @@
+/*
+ * SPDX-FileCopyrightText: syuilo and misskey-project
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+/**
+ * YAMLファイルをJSONファイルに変換するスクリプト
+ * ビルド前に実行し、ランタイムにjs-yamlを含まないようにする
+ */
+
+import fs from 'node:fs';
+import { resolve, dirname } from 'node:path';
+import { fileURLToPath } from 'node:url';
+import yaml from 'js-yaml';
+
+const _filename = fileURLToPath(import.meta.url);
+const _dirname = dirname(_filename);
+
+const configDir = resolve(_dirname, '../../../.config');
+const OUTPUT_PATH = resolve(_dirname, '../../../built/.config.json');
+
+// TODO: yamlのパースに失敗したときのエラーハンドリング
+
+/**
+ * YAMLファイルをJSONファイルに変換
+ * @param {string} ymlPath - YAMLファイルのパス
+ */
+function yamlToJson(ymlPath) {
+ if (!fs.existsSync(ymlPath)) {
+ console.warn(`YAML file not found: ${ymlPath}`);
+ return;
+ }
+
+ console.log(`${ymlPath} → ${OUTPUT_PATH}`);
+
+ const yamlContent = fs.readFileSync(ymlPath, 'utf-8');
+ const jsonContent = yaml.load(yamlContent);
+ if (!fs.existsSync(dirname(OUTPUT_PATH))) {
+ fs.mkdirSync(dirname(OUTPUT_PATH), { recursive: true });
+ }
+ fs.writeFileSync(OUTPUT_PATH, JSON.stringify({
+ '_NOTE_': 'This file is auto-generated from YAML file. DO NOT EDIT.',
+ ...jsonContent,
+ }), 'utf-8');
+}
+
+if (process.env.MISSKEY_CONFIG_YML) {
+ const customYmlPath = resolve(configDir, process.env.MISSKEY_CONFIG_YML);
+ yamlToJson(customYmlPath);
+} else {
+ yamlToJson(resolve(configDir, process.env.NODE_ENV === 'test' ? 'test.yml' : 'default.yml'));
+}
+
+console.log('Configuration compiled ✓');
diff --git a/packages/backend/scripts/dev.mjs b/packages/backend/scripts/dev.mjs
index 023eb7eae6..db96eaf976 100644
--- a/packages/backend/scripts/dev.mjs
+++ b/packages/backend/scripts/dev.mjs
@@ -42,7 +42,7 @@ async function killProc() {
'./node_modules/nodemon/bin/nodemon.js',
[
'-w', 'src',
- '-e', 'ts,js,mjs,cjs,json,pug',
+ '-e', 'ts,js,mjs,cjs,tsx,json,pug',
'--exec', 'pnpm', 'run', 'build',
],
{
diff --git a/packages/backend/scripts/measure-memory.mjs b/packages/backend/scripts/measure-memory.mjs
new file mode 100644
index 0000000000..017252d7ec
--- /dev/null
+++ b/packages/backend/scripts/measure-memory.mjs
@@ -0,0 +1,152 @@
+/*
+ * SPDX-FileCopyrightText: syuilo and misskey-project
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+/**
+ * This script starts the Misskey backend server, waits for it to be ready,
+ * measures memory usage, and outputs the result as JSON.
+ *
+ * Usage: node scripts/measure-memory.mjs
+ */
+
+import { fork } from 'node:child_process';
+import { setTimeout } from 'node:timers/promises';
+import { fileURLToPath } from 'node:url';
+import { dirname, join } from 'node:path';
+
+const __filename = fileURLToPath(import.meta.url);
+const __dirname = dirname(__filename);
+
+const STARTUP_TIMEOUT = 120000; // 120 seconds timeout for server startup
+const MEMORY_SETTLE_TIME = 10000; // Wait 10 seconds after startup for memory to settle
+
+async function measureMemory() {
+ const startTime = Date.now();
+
+ // Start the Misskey backend server using fork to enable IPC
+ const serverProcess = fork(join(__dirname, '../built/boot/entry.js'), [], {
+ cwd: join(__dirname, '..'),
+ env: {
+ ...process.env,
+ NODE_ENV: 'test',
+ },
+ stdio: ['pipe', 'pipe', 'pipe', 'ipc'],
+ });
+
+ let serverReady = false;
+
+ // Listen for the 'ok' message from the server indicating it's ready
+ serverProcess.on('message', (message) => {
+ if (message === 'ok') {
+ serverReady = true;
+ }
+ });
+
+ // Handle server output
+ serverProcess.stdout?.on('data', (data) => {
+ process.stderr.write(`[server stdout] ${data}`);
+ });
+
+ serverProcess.stderr?.on('data', (data) => {
+ process.stderr.write(`[server stderr] ${data}`);
+ });
+
+ // Handle server error
+ serverProcess.on('error', (err) => {
+ process.stderr.write(`[server error] ${err}\n`);
+ });
+
+ // Wait for server to be ready or timeout
+ const startupStartTime = Date.now();
+ while (!serverReady) {
+ if (Date.now() - startupStartTime > STARTUP_TIMEOUT) {
+ serverProcess.kill('SIGTERM');
+ throw new Error('Server startup timeout');
+ }
+ await setTimeout(100);
+ }
+
+ const startupTime = Date.now() - startupStartTime;
+ process.stderr.write(`Server started in ${startupTime}ms\n`);
+
+ // Wait for memory to settle
+ await setTimeout(MEMORY_SETTLE_TIME);
+
+ // Get memory usage from the server process via /proc
+ const pid = serverProcess.pid;
+ let memoryInfo;
+
+ try {
+ const fs = await import('node:fs/promises');
+
+ // Read /proc/[pid]/status for detailed memory info
+ const status = await fs.readFile(`/proc/${pid}/status`, 'utf-8');
+ const vmRssMatch = status.match(/VmRSS:\s+(\d+)\s+kB/);
+ const vmDataMatch = status.match(/VmData:\s+(\d+)\s+kB/);
+ const vmSizeMatch = status.match(/VmSize:\s+(\d+)\s+kB/);
+
+ memoryInfo = {
+ rss: vmRssMatch ? parseInt(vmRssMatch[1], 10) * 1024 : null,
+ heapUsed: vmDataMatch ? parseInt(vmDataMatch[1], 10) * 1024 : null,
+ vmSize: vmSizeMatch ? parseInt(vmSizeMatch[1], 10) * 1024 : null,
+ };
+ } catch (err) {
+ // Fallback: use ps command
+ process.stderr.write(`Warning: Could not read /proc/${pid}/status: ${err}\n`);
+
+ const { execSync } = await import('node:child_process');
+ try {
+ const ps = execSync(`ps -o rss= -p ${pid}`, { encoding: 'utf-8' });
+ const rssKb = parseInt(ps.trim(), 10);
+ memoryInfo = {
+ rss: rssKb * 1024,
+ heapUsed: null,
+ vmSize: null,
+ };
+ } catch {
+ memoryInfo = {
+ rss: null,
+ heapUsed: null,
+ vmSize: null,
+ error: 'Could not measure memory',
+ };
+ }
+ }
+
+ // Stop the server
+ serverProcess.kill('SIGTERM');
+
+ // Wait for process to exit
+ let exited = false;
+ await new Promise((resolve) => {
+ serverProcess.on('exit', () => {
+ exited = true;
+ resolve(undefined);
+ });
+ // Force kill after 10 seconds if not exited
+ setTimeout(10000).then(() => {
+ if (!exited) {
+ serverProcess.kill('SIGKILL');
+ }
+ resolve(undefined);
+ });
+ });
+
+ const result = {
+ timestamp: new Date().toISOString(),
+ startupTimeMs: startupTime,
+ memory: memoryInfo,
+ };
+
+ // Output as JSON to stdout
+ console.log(JSON.stringify(result, null, 2));
+}
+
+measureMemory().catch((err) => {
+ console.error(JSON.stringify({
+ error: err.message,
+ timestamp: new Date().toISOString(),
+ }));
+ process.exit(1);
+});