diff --git a/.github/workflows/report-backend-memory.yml b/.github/workflows/report-backend-memory.yml index c339ca49b4..bf2e311c83 100644 --- a/.github/workflows/report-backend-memory.yml +++ b/.github/workflows/report-backend-memory.yml @@ -54,55 +54,110 @@ jobs: BASE_MEMORY=$(cat ./artifacts/memory-base.json) HEAD_MEMORY=$(cat ./artifacts/memory-head.json) - BASE_RSS=$(echo "$BASE_MEMORY" | jq -r '.memory.rss // 0') - HEAD_RSS=$(echo "$HEAD_MEMORY" | jq -r '.memory.rss // 0') + variation() { + calc() { + BASE=$(echo "$BASE_MEMORY" | jq -r ".${1}.${2} // 0") + HEAD=$(echo "$HEAD_MEMORY" | jq -r ".${1}.${2} // 0") - # Calculate difference - if [ "$BASE_RSS" -gt 0 ] && [ "$HEAD_RSS" -gt 0 ]; then - DIFF=$((HEAD_RSS - BASE_RSS)) - DIFF_PERCENT=$(echo "scale=2; ($DIFF * 100) / $BASE_RSS" | bc) + DIFF=$((HEAD - BASE)) + if [ "$BASE" -gt 0 ]; then + DIFF_PERCENT=$(echo "scale=2; ($DIFF * 100) / $BASE" | bc) + else + DIFF_PERCENT=0 + fi - # Convert to MB for readability - BASE_MB=$(echo "scale=2; $BASE_RSS / 1048576" | bc) - HEAD_MB=$(echo "scale=2; $HEAD_RSS / 1048576" | bc) - DIFF_MB=$(echo "scale=2; $DIFF / 1048576" | bc) + # Convert KB to MB for readability + BASE_MB=$(echo "scale=2; $BASE / 1024" | bc) + HEAD_MB=$(echo "scale=2; $HEAD / 1024" | bc) + DIFF_MB=$(echo "scale=2; $DIFF / 1024" | bc) - echo "base_mb=$BASE_MB" >> "$GITHUB_OUTPUT" - echo "head_mb=$HEAD_MB" >> "$GITHUB_OUTPUT" - echo "diff_mb=$DIFF_MB" >> "$GITHUB_OUTPUT" - echo "diff_percent=$DIFF_PERCENT" >> "$GITHUB_OUTPUT" - echo "has_data=true" >> "$GITHUB_OUTPUT" + JSON=$(jq -c -n \ + --argjson base "$BASE_MB" \ + --argjson head "$HEAD_MB" \ + --argjson diff "$DIFF_MB" \ + --argjson diff_percent "$DIFF_PERCENT" \ + '{base: $base, head: $head, diff: $diff, diff_percent: $diff_percent}') - # Determine if this is a significant change (more than 5% increase) - if [ "$(echo "$DIFF_PERCENT > 5" | bc)" -eq 1 ]; then - echo "significant_increase=true" >> "$GITHUB_OUTPUT" - else - echo "significant_increase=false" >> "$GITHUB_OUTPUT" - fi - else - echo "has_data=false" >> "$GITHUB_OUTPUT" - fi + echo "$JSON" + } + + JSON=$(jq -c -n \ + --argjson VmRSS "$(calc $1 VmRSS)" \ + --argjson VmHWM "$(calc $1 VmHWM)" \ + --argjson VmSize "$(calc $1 VmSize)" \ + --argjson VmData "$(calc $1 VmData)" \ + '{VmRSS: $VmRSS, VmHWM: $VmHWM, VmSize: $VmSize, VmData: $VmData}') + + echo "$JSON" + } + + JSON=$(jq -c -n \ + --argjson beforeGc "$(variation beforeGc)" \ + --argjson afterGc "$(variation afterGc)" \ + --argjson afterRequest "$(variation afterRequest)" \ + '{beforeGc: $beforeGc, afterGc: $afterGc, afterRequest: $afterRequest}') + + echo "res=$JSON" >> "$GITHUB_OUTPUT" - id: build-comment name: Build memory comment + env: + RES: ${{ steps.compare.outputs.res }} run: | - HEADER="## Backend Memory Usage Comparison" + HEADER="## Backend memory usage comparison" FOOTER="[See workflow logs for details](https://github.com/${GITHUB_REPOSITORY}/actions/runs/${GITHUB_RUN_ID})" echo "$HEADER" > ./output.md echo >> ./output.md - if [ "${{ steps.compare.outputs.has_data }}" == "true" ]; then - echo "| Metric | base | head | Diff |" >> ./output.md - echo "|--------|------|------|------|" >> ./output.md - echo "| RSS | ${{ steps.compare.outputs.base_mb }} MB | ${{ steps.compare.outputs.head_mb }} MB | ${{ steps.compare.outputs.diff_mb }} MB (${{ steps.compare.outputs.diff_percent }}%) |" >> ./output.md - echo >> ./output.md + table() { + echo "| Metric | base (MB) | head (MB) | Diff (MB) | Diff (%) |" >> ./output.md + echo "|--------|------:|------:|------:|------:|" >> ./output.md - if [ "${{ steps.compare.outputs.significant_increase }}" == "true" ]; then - echo "⚠️ **Warning**: Memory usage has increased by more than 5%. Please verify this is not an unintended change." >> ./output.md - echo >> ./output.md - fi - else - echo "Could not retrieve memory usage data." >> ./output.md + line() { + METRIC=$2 + BASE=$(echo "$RES" | jq -r ".${1}.${2}.base") + HEAD=$(echo "$RES" | jq -r ".${1}.${2}.head") + DIFF=$(echo "$RES" | jq -r ".${1}.${2}.diff") + DIFF_PERCENT=$(echo "$RES" | jq -r ".${1}.${2}.diff_percent") + + if (( $(echo "$DIFF_PERCENT > 0" | bc -l) )); then + DIFF="+$DIFF" + DIFF_PERCENT="+$DIFF_PERCENT" + fi + + # highlight VmRSS + if [ "$2" = "VmRSS" ]; then + METRIC="**${METRIC}**" + BASE="**${BASE}**" + HEAD="**${HEAD}**" + DIFF="**${DIFF}**" + DIFF_PERCENT="**${DIFF_PERCENT}**" + fi + + echo "| ${METRIC} | ${BASE} MB | ${HEAD} MB | ${DIFF} MB | ${DIFF_PERCENT}% |" >> ./output.md + } + + line $1 VmRSS + line $1 VmHWM + line $1 VmSize + line $1 VmData + } + + echo "### Before GC" >> ./output.md + table beforeGc + echo >> ./output.md + + echo "### After GC" >> ./output.md + table afterGc + echo >> ./output.md + + echo "### After Request" >> ./output.md + table afterRequest + echo >> ./output.md + + # Determine if this is a significant change (more than 5% increase) + if [ "$(echo "$RES" | jq -r '.afterGc.VmRSS.diff_percent | tonumber > 5')" = "true" ]; then + echo "⚠️ **Warning**: Memory usage has increased by more than 5%. Please verify this is not an unintended change." >> ./output.md echo >> ./output.md fi diff --git a/package.json b/package.json index 129f6841a3..3138cb4375 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,7 @@ "type": "git", "url": "https://github.com/misskey-dev/misskey.git" }, - "packageManager": "pnpm@10.27.0", + "packageManager": "pnpm@10.28.0", "workspaces": [ "packages/misskey-js", "packages/i18n", @@ -52,10 +52,6 @@ "clean-all": "node scripts/clean-all.mjs", "cleanall": "pnpm clean-all" }, - "resolutions": { - "chokidar": "5.0.0", - "lodash": "4.17.21" - }, "dependencies": { "cssnano": "7.1.2", "esbuild": "0.27.2", @@ -63,23 +59,23 @@ "ignore-walk": "8.0.0", "js-yaml": "4.1.1", "postcss": "8.5.6", - "tar": "7.5.2", - "terser": "5.44.1" + "tar": "7.5.6", + "terser": "5.46.0" }, "devDependencies": { "@eslint/js": "9.39.2", "@misskey-dev/eslint-plugin": "2.2.0", "@types/js-yaml": "4.0.9", - "@types/node": "24.10.4", - "@typescript-eslint/eslint-plugin": "8.50.1", - "@typescript-eslint/parser": "8.50.1", - "@typescript/native-preview": "7.0.0-dev.20251226.1", + "@types/node": "24.10.9", + "@typescript-eslint/eslint-plugin": "8.53.0", + "@typescript-eslint/parser": "8.53.0", + "@typescript/native-preview": "7.0.0-dev.20260116.1", "cross-env": "10.1.0", - "cypress": "15.8.1", + "cypress": "15.9.0", "eslint": "9.39.2", "globals": "16.5.0", "ncp": "2.0.0", - "pnpm": "10.27.0", + "pnpm": "10.28.0", "typescript": "5.9.3", "start-server-and-test": "2.1.3" }, @@ -88,7 +84,9 @@ }, "pnpm": { "overrides": { - "@aiscript-dev/aiscript-languageserver": "-" + "@aiscript-dev/aiscript-languageserver": "-", + "chokidar": "5.0.0", + "lodash": "4.17.23" }, "ignoredBuiltDependencies": [ "@sentry-internal/node-cpu-profiler", diff --git a/packages/backend/package.json b/packages/backend/package.json index c1a9ac8829..c3f881292a 100644 --- a/packages/backend/package.json +++ b/packages/backend/package.json @@ -41,17 +41,17 @@ }, "optionalDependencies": { "@swc/core-android-arm64": "1.3.11", - "@swc/core-darwin-arm64": "1.15.7", - "@swc/core-darwin-x64": "1.15.7", + "@swc/core-darwin-arm64": "1.15.8", + "@swc/core-darwin-x64": "1.15.8", "@swc/core-freebsd-x64": "1.3.11", - "@swc/core-linux-arm-gnueabihf": "1.15.7", - "@swc/core-linux-arm64-gnu": "1.15.7", - "@swc/core-linux-arm64-musl": "1.15.7", - "@swc/core-linux-x64-gnu": "1.15.7", - "@swc/core-linux-x64-musl": "1.15.7", - "@swc/core-win32-arm64-msvc": "1.15.7", - "@swc/core-win32-ia32-msvc": "1.15.7", - "@swc/core-win32-x64-msvc": "1.15.7", + "@swc/core-linux-arm-gnueabihf": "1.15.8", + "@swc/core-linux-arm64-gnu": "1.15.8", + "@swc/core-linux-arm64-musl": "1.15.8", + "@swc/core-linux-x64-gnu": "1.15.8", + "@swc/core-linux-x64-musl": "1.15.8", + "@swc/core-win32-arm64-msvc": "1.15.8", + "@swc/core-win32-ia32-msvc": "1.15.8", + "@swc/core-win32-x64-msvc": "1.15.8", "@tensorflow/tfjs": "4.22.0", "@tensorflow/tfjs-node": "4.22.0", "bufferutil": "4.1.0", @@ -71,30 +71,30 @@ "utf-8-validate": "6.0.6" }, "dependencies": { - "@aws-sdk/client-s3": "3.958.0", - "@aws-sdk/lib-storage": "3.958.0", + "@aws-sdk/client-s3": "3.970.0", + "@aws-sdk/lib-storage": "3.970.0", "@discordapp/twemoji": "16.0.1", "@fastify/accepts": "5.0.4", "@fastify/cors": "11.2.0", - "@fastify/express": "4.0.2", + "@fastify/express": "4.0.4", "@fastify/http-proxy": "11.4.1", "@fastify/multipart": "9.3.0", "@fastify/static": "8.3.0", "@kitajs/html": "4.2.11", "@misskey-dev/sharp-read-bmp": "1.2.0", "@misskey-dev/summaly": "5.2.5", - "@napi-rs/canvas": "0.1.87", - "@nestjs/common": "11.1.10", - "@nestjs/core": "11.1.10", - "@nestjs/testing": "11.1.10", + "@napi-rs/canvas": "0.1.88", + "@nestjs/common": "11.1.12", + "@nestjs/core": "11.1.12", + "@nestjs/testing": "11.1.12", "@peertube/http-signature": "1.7.0", - "@sentry/node": "10.32.1", - "@sentry/profiling-node": "10.32.1", + "@sentry/node": "10.34.0", + "@sentry/profiling-node": "10.34.0", "@simplewebauthn/server": "13.2.2", "@sinonjs/fake-timers": "15.1.0", - "@smithy/node-http-handler": "4.4.7", - "@swc/cli": "0.7.9", - "@swc/core": "1.15.7", + "@smithy/node-http-handler": "4.4.8", + "@swc/cli": "0.7.10", + "@swc/core": "1.15.8", "@twemoji/parser": "16.0.0", "accepts": "1.3.8", "ajv": "8.17.1", @@ -102,8 +102,8 @@ "async-mutex": "0.5.0", "bcryptjs": "3.0.3", "blurhash": "2.0.5", - "body-parser": "2.2.1", - "bullmq": "5.66.3", + "body-parser": "2.2.2", + "bullmq": "5.66.5", "cacheable-lookup": "7.0.0", "chalk": "5.6.2", "chalk-template": "1.1.2", @@ -112,24 +112,24 @@ "content-disposition": "1.0.1", "date-fns": "4.1.0", "deep-email-validator": "0.1.21", - "fastify": "5.6.2", + "fastify": "5.7.1", "fastify-raw-body": "5.0.0", - "feed": "5.1.0", - "file-type": "21.2.0", + "feed": "5.2.0", + "file-type": "21.3.0", "fluent-ffmpeg": "2.1.3", "form-data": "4.0.5", - "got": "14.6.5", + "got": "14.6.6", "hpagent": "1.2.0", "http-link-header": "1.1.3", "i18n": "workspace:*", - "ioredis": "5.8.2", + "ioredis": "5.9.2", "ip-cidr": "4.0.2", "ipaddr.js": "2.3.0", "is-svg": "6.1.0", "json5": "2.2.3", "jsonld": "9.0.0", - "juice": "11.0.3", - "meilisearch": "0.54.0", + "juice": "11.1.0", + "meilisearch": "0.55.0", "mfm-js": "0.25.0", "mime-types": "3.0.2", "misskey-js": "workspace:*", @@ -138,14 +138,14 @@ "nanoid": "5.1.6", "nested-property": "4.0.0", "node-fetch": "3.3.2", - "node-html-parser": "7.0.1", + "node-html-parser": "7.0.2", "nodemailer": "7.0.12", "nsfwjs": "4.2.0", "oauth2orize": "1.12.0", "oauth2orize-pkce": "0.1.2", "os-utils": "0.0.14", "otpauth": "9.4.1", - "pg": "8.16.3", + "pg": "8.17.1", "pkce-challenge": "5.0.1", "probe-image-size": "7.2.3", "promise-limit": "2.7.0", @@ -164,7 +164,7 @@ "slacc": "0.0.10", "strict-event-emitter-types": "2.0.0", "stringz": "2.1.0", - "systeminformation": "5.28.1", + "systeminformation": "5.30.5", "tinycolor2": "1.6.0", "tmp": "0.2.5", "tsc-alias": "1.8.16", @@ -172,14 +172,14 @@ "ulid": "3.0.2", "vary": "1.1.2", "web-push": "3.6.7", - "ws": "8.18.3", + "ws": "8.19.0", "xev": "3.0.2" }, "devDependencies": { "@jest/globals": "29.7.0", "@kitajs/ts-html-plugin": "4.1.3", - "@nestjs/platform-express": "11.1.10", - "@sentry/vue": "10.32.1", + "@nestjs/platform-express": "11.1.12", + "@sentry/vue": "10.34.0", "@simplewebauthn/types": "12.0.0", "@swc/jest": "0.2.39", "@types/accepts": "1.3.7", @@ -193,8 +193,8 @@ "@types/jsonld": "1.5.15", "@types/mime-types": "3.0.1", "@types/ms": "2.1.0", - "@types/node": "24.10.4", - "@types/nodemailer": "7.0.4", + "@types/node": "24.10.9", + "@types/nodemailer": "7.0.5", "@types/oauth2orize": "1.11.5", "@types/oauth2orize-pkce": "0.1.2", "@types/pg": "8.16.0", @@ -212,22 +212,22 @@ "@types/vary": "1.1.3", "@types/web-push": "3.6.4", "@types/ws": "8.18.1", - "@typescript-eslint/eslint-plugin": "8.50.1", - "@typescript-eslint/parser": "8.50.1", + "@typescript-eslint/eslint-plugin": "8.53.0", + "@typescript-eslint/parser": "8.53.0", "aws-sdk-client-mock": "4.1.0", "cbor": "10.0.11", "cross-env": "10.1.0", "esbuild-plugin-swc": "1.0.1", "eslint-plugin-import": "2.32.0", "execa": "9.6.1", - "fkill": "10.0.1", + "fkill": "10.0.3", "jest": "29.7.0", "jest-mock": "29.7.0", "js-yaml": "4.1.1", "nodemon": "3.1.11", - "pid-port": "2.0.0", + "pid-port": "2.0.1", "simple-oauth2": "5.1.0", - "supertest": "7.1.4", - "vite": "7.3.0" + "supertest": "7.2.2", + "vite": "7.3.1" } } diff --git a/packages/backend/scripts/measure-memory.mjs b/packages/backend/scripts/measure-memory.mjs index baa4198adf..3f30e24fb4 100644 --- a/packages/backend/scripts/measure-memory.mjs +++ b/packages/backend/scripts/measure-memory.mjs @@ -14,16 +14,46 @@ import { fork } from 'node:child_process'; import { setTimeout } from 'node:timers/promises'; import { fileURLToPath } from 'node:url'; import { dirname, join } from 'node:path'; +import * as http from 'node:http'; +import * as fs from 'node:fs/promises'; const __filename = fileURLToPath(import.meta.url); const __dirname = dirname(__filename); +const SAMPLE_COUNT = 3; // Number of samples to measure 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(); +const keys = { + VmPeak: 0, + VmSize: 0, + VmHWM: 0, + VmRSS: 0, + VmData: 0, + VmStk: 0, + VmExe: 0, + VmLib: 0, + VmPTE: 0, + VmSwap: 0, +}; +async function getMemoryUsage(pid) { + const status = await fs.readFile(`/proc/${pid}/status`, 'utf-8'); + + const result = {}; + for (const key of Object.keys(keys)) { + const match = status.match(new RegExp(`${key}:\\s+(\\d+)\\s+kB`)); + if (match) { + result[key] = parseInt(match[1], 10); + } else { + throw new Error(`Failed to parse ${key} from /proc/${pid}/status`); + } + } + + return result; +} + +async function measureMemory() { // Start the Misskey backend server using fork to enable IPC const serverProcess = fork(join(__dirname, '../built/boot/entry.js'), ['expose-gc'], { cwd: join(__dirname, '..'), @@ -31,9 +61,9 @@ async function measureMemory() { ...process.env, NODE_ENV: 'production', MK_DISABLE_CLUSTERING: '1', - MK_FORCE_GC: '1', }, stdio: ['pipe', 'pipe', 'pipe', 'ipc'], + execArgv: [...process.execArgv, '--expose-gc'], }); let serverReady = false; @@ -59,6 +89,40 @@ async function measureMemory() { process.stderr.write(`[server error] ${err}\n`); }); + async function triggerGc() { + const ok = new Promise((resolve) => { + serverProcess.once('message', (message) => { + if (message === 'gc ok') resolve(); + }); + }); + + serverProcess.send('gc'); + + await ok; + + await setTimeout(1000); + } + + function createRequest() { + return new Promise((resolve, reject) => { + const req = http.request({ + host: 'localhost', + port: 61812, + path: '/api/meta', + method: 'POST', + }, (res) => { + res.on('data', () => { }); + res.on('end', () => { + resolve(); + }); + }); + req.on('error', (err) => { + reject(err); + }); + req.end(); + }); + } + // Wait for server to be ready or timeout const startupStartTime = Date.now(); while (!serverReady) { @@ -75,46 +139,23 @@ async function measureMemory() { // 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'); + const beforeGc = await getMemoryUsage(pid); - // 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/); + await triggerGc(); - 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 afterGc = await getMemoryUsage(pid); - 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', - }; - } - } + // create some http requests to simulate load + const REQUEST_COUNT = 10; + await Promise.all( + Array.from({ length: REQUEST_COUNT }).map(() => createRequest()), + ); + + await triggerGc(); + + const afterRequest = await getMemoryUsage(pid); // Stop the server serverProcess.kill('SIGTERM'); @@ -137,15 +178,51 @@ async function measureMemory() { const result = { timestamp: new Date().toISOString(), - startupTimeMs: startupTime, - memory: memoryInfo, + beforeGc, + afterGc, + afterRequest, + }; + + return result; +} + +async function main() { + // 直列の方が時間的に分散されて正確そうだから直列でやる + const results = []; + for (let i = 0; i < SAMPLE_COUNT; i++) { + const res = await measureMemory(); + results.push(res); + } + + // Calculate averages + const beforeGc = structuredClone(keys); + const afterGc = structuredClone(keys); + const afterRequest = structuredClone(keys); + for (const res of results) { + for (const key of Object.keys(keys)) { + beforeGc[key] += res.beforeGc[key]; + afterGc[key] += res.afterGc[key]; + afterRequest[key] += res.afterRequest[key]; + } + } + for (const key of Object.keys(keys)) { + beforeGc[key] = Math.round(beforeGc[key] / SAMPLE_COUNT); + afterGc[key] = Math.round(afterGc[key] / SAMPLE_COUNT); + afterRequest[key] = Math.round(afterRequest[key] / SAMPLE_COUNT); + } + + const result = { + timestamp: new Date().toISOString(), + beforeGc, + afterGc, + afterRequest, }; // Output as JSON to stdout console.log(JSON.stringify(result, null, 2)); } -measureMemory().catch((err) => { +main().catch((err) => { console.error(JSON.stringify({ error: err.message, timestamp: new Date().toISOString(), diff --git a/packages/backend/src/boot/entry.ts b/packages/backend/src/boot/entry.ts index 56b339b6aa..3a33d198a5 100644 --- a/packages/backend/src/boot/entry.ts +++ b/packages/backend/src/boot/entry.ts @@ -86,9 +86,17 @@ if (!envOption.disableClustering) { ev.mount(); } -if (envOption.forceGc && global.gc != null) { - global.gc(); -} +process.on('message', msg => { + if (msg === 'gc') { + if (global.gc != null) { + logger.info('Manual GC triggered'); + 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.'); + } + } +}); readyRef.value = true; diff --git a/packages/backend/src/core/QueueService.ts b/packages/backend/src/core/QueueService.ts index 8ef235b238..f90ae80731 100644 --- a/packages/backend/src/core/QueueService.ts +++ b/packages/backend/src/core/QueueService.ts @@ -902,7 +902,7 @@ export class QueueService { }, db: { version: db.redis_version, - mode: db.redis_mode, + mode: db.redis_mode as 'cluster' | 'standalone' | 'sentinel', runId: db.run_id, processId: db.process_id, port: parseInt(db.tcp_port), diff --git a/packages/backend/src/env.ts b/packages/backend/src/env.ts index 9957938467..ba44cfa2e6 100644 --- a/packages/backend/src/env.ts +++ b/packages/backend/src/env.ts @@ -11,7 +11,6 @@ const envOption = { verbose: false, withLogTime: false, quiet: false, - forceGc: false, }; for (const key of Object.keys(envOption) as (keyof typeof envOption)[]) { diff --git a/packages/frontend-builder/package.json b/packages/frontend-builder/package.json index 8e77c0f5c3..0ae32117b6 100644 --- a/packages/frontend-builder/package.json +++ b/packages/frontend-builder/package.json @@ -11,15 +11,15 @@ }, "devDependencies": { "@types/estree": "1.0.8", - "@types/node": "24.10.4", - "@typescript-eslint/eslint-plugin": "8.50.1", - "@typescript-eslint/parser": "8.50.1", - "rollup": "4.54.0" + "@types/node": "24.10.9", + "@typescript-eslint/eslint-plugin": "8.53.0", + "@typescript-eslint/parser": "8.53.0", + "rollup": "4.55.1" }, "dependencies": { "i18n": "workspace:*", "estree-walker": "3.0.3", "magic-string": "0.30.21", - "vite": "7.3.0" + "vite": "7.3.1" } } diff --git a/packages/frontend-embed/package.json b/packages/frontend-embed/package.json index 800beb14d5..aadb20cb48 100644 --- a/packages/frontend-embed/package.json +++ b/packages/frontend-embed/package.json @@ -25,12 +25,12 @@ "mfm-js": "0.25.0", "misskey-js": "workspace:*", "punycode.js": "2.3.1", - "rollup": "4.54.0", - "sass": "1.97.1", + "rollup": "4.55.1", + "sass": "1.97.2", "shiki": "3.21.0", "tinycolor2": "1.6.0", "uuid": "13.0.0", - "vite": "7.3.0", + "vite": "7.3.1", "vue": "3.5.26" }, "devDependencies": { @@ -39,29 +39,29 @@ "@testing-library/vue": "8.1.0", "@types/estree": "1.0.8", "@types/micromatch": "4.0.10", - "@types/node": "24.10.4", + "@types/node": "24.10.9", "@types/punycode.js": "npm:@types/punycode@2.1.4", "@types/tinycolor2": "1.4.6", "@types/ws": "8.18.1", - "@typescript-eslint/eslint-plugin": "8.50.1", - "@typescript-eslint/parser": "8.50.1", - "@vitest/coverage-v8": "4.0.16", + "@typescript-eslint/eslint-plugin": "8.53.0", + "@typescript-eslint/parser": "8.53.0", + "@vitest/coverage-v8": "4.0.17", "@vue/runtime-core": "3.5.26", "acorn": "8.15.0", "cross-env": "10.1.0", "eslint-plugin-import": "2.32.0", - "eslint-plugin-vue": "10.6.2", - "happy-dom": "20.0.11", + "eslint-plugin-vue": "10.7.0", + "happy-dom": "20.3.1", "intersection-observer": "0.12.2", "micromatch": "4.0.8", - "msw": "2.12.6", + "msw": "2.12.7", "nodemon": "3.1.11", - "prettier": "3.7.4", + "prettier": "3.8.0", "start-server-and-test": "2.1.3", "tsx": "4.21.0", "vite-plugin-turbosnap": "1.0.3", - "vue-component-type-helpers": "3.2.1", + "vue-component-type-helpers": "3.2.2", "vue-eslint-parser": "10.2.0", - "vue-tsc": "3.2.1" + "vue-tsc": "3.2.2" } } diff --git a/packages/frontend-shared/package.json b/packages/frontend-shared/package.json index 53343907de..a33394661a 100644 --- a/packages/frontend-shared/package.json +++ b/packages/frontend-shared/package.json @@ -21,11 +21,11 @@ "lint": "pnpm typecheck && pnpm eslint" }, "devDependencies": { - "@types/node": "24.10.4", - "@typescript-eslint/eslint-plugin": "8.50.1", - "@typescript-eslint/parser": "8.50.1", + "@types/node": "24.10.9", + "@typescript-eslint/eslint-plugin": "8.53.0", + "@typescript-eslint/parser": "8.53.0", "esbuild": "0.27.2", - "eslint-plugin-vue": "10.6.2", + "eslint-plugin-vue": "10.7.0", "nodemon": "3.1.11", "vue-eslint-parser": "10.2.0" }, diff --git a/packages/frontend/package.json b/packages/frontend/package.json index f9dab22cc9..9f9e899e0e 100644 --- a/packages/frontend/package.json +++ b/packages/frontend/package.json @@ -24,7 +24,7 @@ "@rollup/plugin-json": "6.1.0", "@rollup/plugin-replace": "6.0.3", "@rollup/pluginutils": "5.3.0", - "@sentry/vue": "10.32.1", + "@sentry/vue": "10.34.0", "@shikijs/transformers": "3.21.0", "@syuilo/aiscript": "1.2.1", "@syuilo/aiscript-0-19-0": "npm:@syuilo/aiscript@^0.19.0", @@ -40,14 +40,14 @@ "chartjs-chart-matrix": "3.0.0", "chartjs-plugin-gradient": "0.6.1", "chartjs-plugin-zoom": "2.2.0", - "chromatic": "13.3.4", + "chromatic": "13.3.5", "compare-versions": "6.1.1", "cropperjs": "2.1.0", "date-fns": "4.1.0", "diff": "8.0.3", "eventemitter3": "5.0.1", "execa": "9.6.1", - "exifreader": "4.33.1", + "exifreader": "4.36.0", "frontend-shared": "workspace:*", "i18n": "workspace:*", "icons-subsetter": "workspace:*", @@ -57,7 +57,7 @@ "is-file-animated": "1.0.2", "json5": "2.2.3", "matter-js": "0.20.0", - "mediabunny": "1.27.2", + "mediabunny": "1.28.0", "mfm-js": "0.25.0", "misskey-bubble-game": "workspace:*", "misskey-js": "workspace:*", @@ -66,15 +66,15 @@ "punycode.js": "2.3.1", "qr-code-styling": "1.9.2", "qr-scanner": "1.4.2", - "rollup": "4.54.0", + "rollup": "4.55.1", "sanitize-html": "2.17.0", - "sass": "1.97.1", + "sass": "1.97.2", "shiki": "3.21.0", "textarea-caret": "3.1.0", "three": "0.182.0", "throttle-debounce": "5.0.2", "tinycolor2": "1.6.0", - "vite": "7.3.0", + "vite": "7.3.1", "vue": "3.5.26", "wanakana": "5.3.1" }, @@ -82,7 +82,7 @@ "@misskey-dev/summaly": "5.2.5", "@storybook/addon-essentials": "8.6.15", "@storybook/addon-interactions": "8.6.15", - "@storybook/addon-links": "10.1.10", + "@storybook/addon-links": "10.1.11", "@storybook/addon-mdx-gfm": "8.6.15", "@storybook/addon-storysource": "8.6.15", "@storybook/blocks": "8.6.15", @@ -90,13 +90,13 @@ "@storybook/core-events": "8.6.15", "@storybook/manager-api": "8.6.15", "@storybook/preview-api": "8.6.15", - "@storybook/react": "10.1.10", - "@storybook/react-vite": "10.1.10", + "@storybook/react": "10.1.11", + "@storybook/react-vite": "10.1.11", "@storybook/test": "8.6.15", "@storybook/theming": "8.6.15", "@storybook/types": "8.6.15", - "@storybook/vue3": "10.1.10", - "@storybook/vue3-vite": "10.1.10", + "@storybook/vue3": "10.1.11", + "@storybook/vue3-vite": "10.1.11", "@tabler/icons-webfont": "3.35.0", "@testing-library/vue": "8.1.0", "@types/canvas-confetti": "1.9.0", @@ -104,46 +104,46 @@ "@types/insert-text-at-cursor": "0.3.2", "@types/matter-js": "0.20.2", "@types/micromatch": "4.0.10", - "@types/node": "24.10.4", + "@types/node": "24.10.9", "@types/punycode.js": "npm:@types/punycode@2.1.4", "@types/sanitize-html": "2.16.0", "@types/seedrandom": "3.0.8", "@types/textarea-caret": "3.0.4", "@types/throttle-debounce": "5.0.2", "@types/tinycolor2": "1.4.6", - "@typescript-eslint/eslint-plugin": "8.50.1", - "@typescript-eslint/parser": "8.50.1", - "@vitest/coverage-v8": "4.0.16", + "@typescript-eslint/eslint-plugin": "8.53.0", + "@typescript-eslint/parser": "8.53.0", + "@vitest/coverage-v8": "4.0.17", "@vue/compiler-core": "3.5.26", "acorn": "8.15.0", "astring": "1.9.0", "cross-env": "10.1.0", - "cypress": "15.8.1", + "cypress": "15.9.0", "eslint-plugin-import": "2.32.0", - "eslint-plugin-vue": "10.6.2", + "eslint-plugin-vue": "10.7.0", "estree-walker": "3.0.3", - "happy-dom": "20.0.11", + "happy-dom": "20.3.1", "intersection-observer": "0.12.2", "magic-string": "0.30.21", "micromatch": "4.0.8", "minimatch": "10.1.1", - "msw": "2.12.6", + "msw": "2.12.7", "msw-storybook-addon": "2.0.6", "nodemon": "3.1.11", - "prettier": "3.7.4", + "prettier": "3.8.0", "react": "19.2.3", "react-dom": "19.2.3", "seedrandom": "3.0.5", "start-server-and-test": "2.1.3", - "storybook": "10.1.10", + "storybook": "10.1.11", "storybook-addon-misskey-theme": "github:misskey-dev/storybook-addon-misskey-theme", "tsx": "4.21.0", "vite-plugin-glsl": "1.5.5", "vite-plugin-turbosnap": "1.0.3", - "vitest": "4.0.16", + "vitest": "4.0.17", "vitest-fetch-mock": "0.4.5", - "vue-component-type-helpers": "3.2.1", + "vue-component-type-helpers": "3.2.2", "vue-eslint-parser": "10.2.0", - "vue-tsc": "3.2.1" + "vue-tsc": "3.2.2" } } diff --git a/packages/frontend/src/components/MkMediaImage.vue b/packages/frontend/src/components/MkMediaImage.vue index c7d8c95b7b..4236bd943a 100644 --- a/packages/frontend/src/components/MkMediaImage.vue +++ b/packages/frontend/src/components/MkMediaImage.vue @@ -4,7 +4,7 @@ SPDX-License-Identifier: AGPL-3.0-only -->