From 35888eb8f49332d4f4e4cc38a4bd8a9b3575345a Mon Sep 17 00:00:00 2001 From: syuilo <4439005+syuilo@users.noreply.github.com> Date: Thu, 31 Jul 2025 18:16:21 +0900 Subject: [PATCH 01/91] =?UTF-8?q?enhance(backend):=20BullMQ=E3=81=AE?= =?UTF-8?q?=E5=BB=83=E6=AD=A2=E3=81=95=E3=82=8C=E3=81=9FRepeatable?= =?UTF-8?q?=E3=81=8B=E3=82=89Job=20Schedulers=E3=81=AB=E7=A7=BB=E8=A1=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/backend/src/core/QueueService.ts | 92 ++++++++++++++--------- 1 file changed, 58 insertions(+), 34 deletions(-) diff --git a/packages/backend/src/core/QueueService.ts b/packages/backend/src/core/QueueService.ts index 04bbc7e38a..fce8cc2067 100644 --- a/packages/backend/src/core/QueueService.ts +++ b/packages/backend/src/core/QueueService.ts @@ -17,6 +17,7 @@ import { bindThis } from '@/decorators.js'; import type { Antenna } from '@/server/api/endpoints/i/import-antennas.js'; import { ApRequestCreator } from '@/core/activitypub/ApRequestService.js'; import { type SystemWebhookPayload } from '@/core/SystemWebhookService.js'; +import type { Packed } from '@/misc/json-schema.js'; import { type UserWebhookPayload } from './UserWebhookService.js'; import type { DbJobData, @@ -39,7 +40,6 @@ import type { } from './QueueModule.js'; import type httpSignature from '@peertube/http-signature'; import type * as Bull from 'bullmq'; -import type { Packed } from '@/misc/json-schema.js'; export const QUEUE_TYPES = [ 'system', @@ -69,61 +69,85 @@ export class QueueService { @Inject('queue:userWebhookDeliver') public userWebhookDeliverQueue: UserWebhookDeliverQueue, @Inject('queue:systemWebhookDeliver') public systemWebhookDeliverQueue: SystemWebhookDeliverQueue, ) { - this.systemQueue.add('tickCharts', { + this.systemQueue.upsertJobScheduler('tickCharts', { + pattern: '55 * * * *', }, { - repeat: { pattern: '55 * * * *' }, - removeOnComplete: 10, - removeOnFail: 30, + name: 'tickCharts', + opts: { + removeOnComplete: 10, + removeOnFail: 30, + }, }); - this.systemQueue.add('resyncCharts', { + this.systemQueue.upsertJobScheduler('resyncCharts', { + pattern: '0 0 * * *', }, { - repeat: { pattern: '0 0 * * *' }, - removeOnComplete: 10, - removeOnFail: 30, + name: 'resyncCharts', + opts: { + removeOnComplete: 10, + removeOnFail: 30, + }, }); - this.systemQueue.add('cleanCharts', { + this.systemQueue.upsertJobScheduler('cleanCharts', { + pattern: '0 0 * * *', }, { - repeat: { pattern: '0 0 * * *' }, - removeOnComplete: 10, - removeOnFail: 30, + name: 'cleanCharts', + opts: { + removeOnComplete: 10, + removeOnFail: 30, + }, }); - this.systemQueue.add('aggregateRetention', { + this.systemQueue.upsertJobScheduler('aggregateRetention', { + pattern: '0 0 * * *', }, { - repeat: { pattern: '0 0 * * *' }, - removeOnComplete: 10, - removeOnFail: 30, + name: 'aggregateRetention', + opts: { + removeOnComplete: 10, + removeOnFail: 30, + }, }); - this.systemQueue.add('clean', { + this.systemQueue.upsertJobScheduler('clean', { + pattern: '0 0 * * *', }, { - repeat: { pattern: '0 0 * * *' }, - removeOnComplete: 10, - removeOnFail: 30, + name: 'clean', + opts: { + removeOnComplete: 10, + removeOnFail: 30, + }, }); - this.systemQueue.add('checkExpiredMutings', { + this.systemQueue.upsertJobScheduler('checkExpiredMutings', { + pattern: '*/5 * * * *', }, { - repeat: { pattern: '*/5 * * * *' }, - removeOnComplete: 10, - removeOnFail: 30, + name: 'checkExpiredMutings', + opts: { + removeOnComplete: 10, + removeOnFail: 30, + }, }); - this.systemQueue.add('bakeBufferedReactions', { + this.systemQueue.upsertJobScheduler('bakeBufferedReactions', { + pattern: '0 0 * * *', }, { - repeat: { pattern: '0 0 * * *' }, - removeOnComplete: 10, - removeOnFail: 30, + name: 'bakeBufferedReactions', + opts: { + removeOnComplete: 10, + removeOnFail: 30, + }, }); - this.systemQueue.add('checkModeratorsActivity', { - }, { + this.systemQueue.upsertJobScheduler('checkModeratorsActivity', { // 毎時30分に起動 - repeat: { pattern: '30 * * * *' }, - removeOnComplete: 10, - removeOnFail: 30, + pattern: '30 * * * *', + }, { + name: 'checkModeratorsActivity', + opts: { + removeOnComplete: 10, + removeOnFail: 30, + }, }); } From a45e89c30058f2bd00a7cf0254f6e4f6dedf4603 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E3=81=8B=E3=81=A3=E3=81=93=E3=81=8B=E3=82=8A?= <67428053+kakkokari-gtyih@users.noreply.github.com> Date: Thu, 31 Jul 2025 18:47:22 +0900 Subject: [PATCH 02/91] =?UTF-8?q?fix(frontend):=20=E9=81=A9=E7=94=A8?= =?UTF-8?q?=E4=B8=AD=E3=81=AE=E3=83=86=E3=83=BC=E3=83=9E=E3=82=92=E4=BF=9D?= =?UTF-8?q?=E6=8C=81=E3=81=99=E3=82=8B=E9=9A=9B=E3=81=AB=E3=83=AA=E3=82=A2?= =?UTF-8?q?=E3=82=AF=E3=83=86=E3=82=A3=E3=83=93=E3=83=86=E3=82=A3=E3=82=82?= =?UTF-8?q?=E4=BF=9D=E6=8C=81=E3=81=95=E3=82=8C=E3=82=8B=E5=95=8F=E9=A1=8C?= =?UTF-8?q?=E3=82=92=E4=BF=AE=E6=AD=A3=20(#16304)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix(frontend): 現在のテーマを保持する際にリアクティビティが保持される問題を修正 * Update Changelog * Update theme.ts --- CHANGELOG.md | 1 + packages/frontend/src/theme.ts | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index af5c0da4a3..e0f9d775e7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ ### Client - Fix: 一部の設定検索結果が存在しないパスになる問題を修正 (Cherry-picked from https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/1171) +- Fix: テーマエディタが動作しない問題を修正 ### Server - Enhance: ノートの削除処理の効率化 diff --git a/packages/frontend/src/theme.ts b/packages/frontend/src/theme.ts index e48eb04103..a2658df374 100644 --- a/packages/frontend/src/theme.ts +++ b/packages/frontend/src/theme.ts @@ -137,7 +137,8 @@ export function applyTheme(theme: Theme, persist = true) { } if (deepEqual(currentTheme, theme)) return; - currentTheme = theme; + // リアクティビティ解除 + currentTheme = deepClone(theme); if (window.document.startViewTransition != null && prefer.s.animation) { window.document.documentElement.classList.add('_themeChanging_'); From 862a6fae793271928fc05de0dfc22a473d3af2d2 Mon Sep 17 00:00:00 2001 From: syuilo <4439005+syuilo@users.noreply.github.com> Date: Thu, 31 Jul 2025 20:57:36 +0900 Subject: [PATCH 03/91] =?UTF-8?q?enhance(backend):=20=E5=8F=A4=E3=81=84?= =?UTF-8?q?=E3=83=90=E3=83=BC=E3=82=B8=E3=83=A7=E3=83=B3=E3=81=A7=E4=BD=9C?= =?UTF-8?q?=E6=88=90=E3=81=95=E3=82=8C=E7=8F=BE=E5=9C=A8=E4=BD=BF=E3=82=8F?= =?UTF-8?q?=E3=82=8C=E3=81=AA=E3=81=8F=E3=81=AA=E3=81=A3=E3=81=9Frepeatabl?= =?UTF-8?q?e=E3=82=B8=E3=83=A7=E3=83=96=E3=82=92=E3=82=AF=E3=83=AA?= =?UTF-8?q?=E3=83=BC=E3=83=B3=E3=82=A2=E3=83=83=E3=83=97=E3=81=99=E3=82=8B?= =?UTF-8?q?=E3=82=88=E3=81=86=E3=81=AB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/backend/src/core/QueueService.ts | 123 ++++++++-------------- 1 file changed, 45 insertions(+), 78 deletions(-) diff --git a/packages/backend/src/core/QueueService.ts b/packages/backend/src/core/QueueService.ts index fce8cc2067..31de66ca88 100644 --- a/packages/backend/src/core/QueueService.ts +++ b/packages/backend/src/core/QueueService.ts @@ -53,6 +53,33 @@ export const QUEUE_TYPES = [ 'systemWebhookDeliver', ] as const; +const REPEATABLE_SYSTEM_JOB_DEF = [{ + name: 'tickCharts', + pattern: '55 * * * *', +}, { + name: 'resyncCharts', + pattern: '0 0 * * *', +}, { + name: 'cleanCharts', + pattern: '0 0 * * *', +}, { + name: 'aggregateRetention', + pattern: '0 0 * * *', +}, { + name: 'clean', + pattern: '0 0 * * *', +}, { + name: 'checkExpiredMutings', + pattern: '*/5 * * * *', +}, { + name: 'bakeBufferedReactions', + pattern: '0 0 * * *', +}, { + name: 'checkModeratorsActivity', + // 毎時30分に起動 + pattern: '30 * * * *', +}]; + @Injectable() export class QueueService { constructor( @@ -69,85 +96,25 @@ export class QueueService { @Inject('queue:userWebhookDeliver') public userWebhookDeliverQueue: UserWebhookDeliverQueue, @Inject('queue:systemWebhookDeliver') public systemWebhookDeliverQueue: SystemWebhookDeliverQueue, ) { - this.systemQueue.upsertJobScheduler('tickCharts', { - pattern: '55 * * * *', - }, { - name: 'tickCharts', - opts: { - removeOnComplete: 10, - removeOnFail: 30, - }, - }); + for (const def of REPEATABLE_SYSTEM_JOB_DEF) { + this.systemQueue.upsertJobScheduler(def.name, { + pattern: def.pattern, + }, { + name: def.name, + opts: { + removeOnComplete: 10, + removeOnFail: 30, + }, + }); + } - this.systemQueue.upsertJobScheduler('resyncCharts', { - pattern: '0 0 * * *', - }, { - name: 'resyncCharts', - opts: { - removeOnComplete: 10, - removeOnFail: 30, - }, - }); - - this.systemQueue.upsertJobScheduler('cleanCharts', { - pattern: '0 0 * * *', - }, { - name: 'cleanCharts', - opts: { - removeOnComplete: 10, - removeOnFail: 30, - }, - }); - - this.systemQueue.upsertJobScheduler('aggregateRetention', { - pattern: '0 0 * * *', - }, { - name: 'aggregateRetention', - opts: { - removeOnComplete: 10, - removeOnFail: 30, - }, - }); - - this.systemQueue.upsertJobScheduler('clean', { - pattern: '0 0 * * *', - }, { - name: 'clean', - opts: { - removeOnComplete: 10, - removeOnFail: 30, - }, - }); - - this.systemQueue.upsertJobScheduler('checkExpiredMutings', { - pattern: '*/5 * * * *', - }, { - name: 'checkExpiredMutings', - opts: { - removeOnComplete: 10, - removeOnFail: 30, - }, - }); - - this.systemQueue.upsertJobScheduler('bakeBufferedReactions', { - pattern: '0 0 * * *', - }, { - name: 'bakeBufferedReactions', - opts: { - removeOnComplete: 10, - removeOnFail: 30, - }, - }); - - this.systemQueue.upsertJobScheduler('checkModeratorsActivity', { - // 毎時30分に起動 - pattern: '30 * * * *', - }, { - name: 'checkModeratorsActivity', - opts: { - removeOnComplete: 10, - removeOnFail: 30, - }, + // 古いバージョンで作成され現在使われなくなったrepeatableジョブをクリーンアップ + this.systemQueue.getJobSchedulers().then(schedulers => { + for (const scheduler of schedulers) { + if (!REPEATABLE_SYSTEM_JOB_DEF.some(def => def.name === scheduler.key)) { + this.systemQueue.removeJobScheduler(scheduler.key); + } + } }); } From 18daf43f705bde35c7f9a3a584ec14650612d7c1 Mon Sep 17 00:00:00 2001 From: syuilo <4439005+syuilo@users.noreply.github.com> Date: Thu, 31 Jul 2025 21:12:07 +0900 Subject: [PATCH 04/91] clean up MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ワイルドカードセレクタはexpensive --- packages/frontend/src/style.scss | 6 ------ packages/frontend/src/theme.ts | 12 +++--------- 2 files changed, 3 insertions(+), 15 deletions(-) diff --git a/packages/frontend/src/style.scss b/packages/frontend/src/style.scss index ebd2b7e48c..d9565841f2 100644 --- a/packages/frontend/src/style.scss +++ b/packages/frontend/src/style.scss @@ -64,12 +64,6 @@ html { } } -html._themeChangingFallback_ { - &, * { - transition: background 0.5s ease, border 0.5s ease !important; - } -} - html._themeChanging_ { view-transition-name: theme-changing; } diff --git a/packages/frontend/src/theme.ts b/packages/frontend/src/theme.ts index a2658df374..036b86cff8 100644 --- a/packages/frontend/src/theme.ts +++ b/packages/frontend/src/theme.ts @@ -140,7 +140,7 @@ export function applyTheme(theme: Theme, persist = true) { // リアクティビティ解除 currentTheme = deepClone(theme); - if (window.document.startViewTransition != null && prefer.s.animation) { + if (window.document.startViewTransition != null) { window.document.documentElement.classList.add('_themeChanging_'); window.document.startViewTransition(async () => { applyThemeInternal(theme, persist); @@ -151,15 +151,9 @@ export function applyTheme(theme: Theme, persist = true) { globalEvents.emit('themeChanged'); }); } else { - // TODO: ViewTransition API が主要ブラウザで対応したら消す - window.document.documentElement.classList.add('_themeChangingFallback_'); - timeout = window.setTimeout(() => { - window.document.documentElement.classList.remove('_themeChangingFallback_'); - // 色計算など再度行えるようにクライアント全体に通知 - globalEvents.emit('themeChanged'); - }, 500); - applyThemeInternal(theme, persist); + // 色計算など再度行えるようにクライアント全体に通知 + globalEvents.emit('themeChanged'); } } From 4be0045826026b36e9e086c892d9b673226121c7 Mon Sep 17 00:00:00 2001 From: syuilo <4439005+syuilo@users.noreply.github.com> Date: Thu, 31 Jul 2025 21:21:44 +0900 Subject: [PATCH 05/91] update minimum nodejs version --- .github/min.node-version | 2 +- CHANGELOG.md | 3 +++ packages/backend/package.json | 2 +- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/.github/min.node-version b/.github/min.node-version index d4b7699d36..b8ffd70759 100644 --- a/.github/min.node-version +++ b/.github/min.node-version @@ -1 +1 @@ -20.18.1 +22.15.0 diff --git a/CHANGELOG.md b/CHANGELOG.md index e0f9d775e7..1e2a82e574 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,8 @@ ## Unreleased +### Note +- サポートされるNode.jsの最小バージョンが**22.15.0**になりました + ### General - ノートを削除した際、関連するノートが同時に削除されないようになりました - APIで、「replyIdが存在しているのにreplyがnull」や「renoteIdが存在しているのにrenoteがnull」であるという、今までにはなかったパターンが表れることになります diff --git a/packages/backend/package.json b/packages/backend/package.json index 1a25f63b83..dbf4a5566c 100644 --- a/packages/backend/package.json +++ b/packages/backend/package.json @@ -4,7 +4,7 @@ "private": true, "type": "module", "engines": { - "node": "^20.18.1 || ^22.0.0" + "node": "^22.15.0" }, "scripts": { "start": "node ./built/boot/entry.js", From 4f5d3f6f7d724eafa6cf82a3ce24f8fbb7fe7f84 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E3=81=8B=E3=81=A3=E3=81=93=E3=81=8B=E3=82=8A?= <67428053+kakkokari-gtyih@users.noreply.github.com> Date: Thu, 31 Jul 2025 21:45:34 +0900 Subject: [PATCH 06/91] =?UTF-8?q?fix(frontend):=20MkNotesTimeline=E3=81=AE?= =?UTF-8?q?=E6=97=A5=E4=BB=98divider=E3=81=AE=E3=82=B9=E3=82=BF=E3=82=A4?= =?UTF-8?q?=E3=83=AB=E4=BF=AE=E6=AD=A3=20(#16306)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/frontend/src/components/MkDrive.vue | 2 +- .../src/components/MkNotesTimeline.vue | 22 ++++++++++++++----- .../components/MkStreamingNotesTimeline.vue | 4 ++-- .../MkStreamingNotificationsTimeline.vue | 6 ++--- 4 files changed, 22 insertions(+), 12 deletions(-) diff --git a/packages/frontend/src/components/MkDrive.vue b/packages/frontend/src/components/MkDrive.vue index 9fe1c7ef21..8a33dfb842 100644 --- a/packages/frontend/src/components/MkDrive.vue +++ b/packages/frontend/src/components/MkDrive.vue @@ -145,7 +145,7 @@ import { claimAchievement } from '@/utility/achievements.js'; import { prefer } from '@/preferences.js'; import { chooseFileFromPcAndUpload, selectDriveFolder } from '@/utility/drive.js'; import { store } from '@/store.js'; -import { isSeparatorNeeded, getSeparatorInfo, makeDateGroupedTimelineComputedRef } from '@/utility/timeline-date-separate.js'; +import { makeDateGroupedTimelineComputedRef } from '@/utility/timeline-date-separate.js'; import { globalEvents, useGlobalEvent } from '@/events.js'; import { checkDragDataType, getDragData, setDragData } from '@/drag-and-drop.js'; import { getDriveFileMenu } from '@/utility/get-drive-file-menu.js'; diff --git a/packages/frontend/src/components/MkNotesTimeline.vue b/packages/frontend/src/components/MkNotesTimeline.vue index 83af7db26f..42d44dffdb 100644 --- a/packages/frontend/src/components/MkNotesTimeline.vue +++ b/packages/frontend/src/components/MkNotesTimeline.vue @@ -10,15 +10,22 @@ SPDX-License-Identifier: AGPL-3.0-only