From 8c81bb9b6ac02a7a01848227e99922fab9392b86 Mon Sep 17 00:00:00 2001 From: riku6460 <17585784+riku6460@users.noreply.github.com> Date: Wed, 25 Dec 2024 11:35:41 +0900 Subject: [PATCH 1/5] =?UTF-8?q?perf(queue):=20BullMQ=20+=20DragonflyDB=20?= =?UTF-8?q?=E3=81=A7=20Hashtag=20=E3=82=92=E4=BD=BF=E7=94=A8=E3=81=97?= =?UTF-8?q?=E3=81=99=E3=81=B9=E3=81=A6=E3=82=92=E3=83=AD=E3=83=83=E3=82=AF?= =?UTF-8?q?=E3=81=97=E3=81=AA=E3=81=84=E3=82=88=E3=81=86=E3=81=AB=E3=81=99?= =?UTF-8?q?=E3=82=8B=20(MisskeyIO#838)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .devcontainer/docker-compose.yml | 2 +- .github/workflows/test-backend.yml | 4 ++-- chart/templates/Deployment.yml | 4 ++-- docker-compose.local-db.yml | 2 +- docker-compose_example.yml | 2 +- packages/backend/src/config.ts | 1 + packages/backend/src/core/QueueModule.ts | 14 +++++++++----- .../backend/src/queue/QueueProcessorService.ts | 8 ++++---- packages/backend/src/queue/const.ts | 10 ++++++++-- .../backend/src/server/web/ClientServerService.ts | 8 ++++---- packages/backend/test/docker-compose.yml | 2 +- 11 files changed, 34 insertions(+), 23 deletions(-) diff --git a/.devcontainer/docker-compose.yml b/.devcontainer/docker-compose.yml index d9f38b8235fc..a8ad3c6f78b7 100644 --- a/.devcontainer/docker-compose.yml +++ b/.devcontainer/docker-compose.yml @@ -24,7 +24,7 @@ services: DFLY_snapshot_cron: '* * * * *' DFLY_version_check: false DFLY_tcp_backlog: 2048 - DFLY_default_lua_flags: allow-undeclared-keys + DFLY_lock_on_hashtags: true DFLY_pipeline_squash: 0 DFLY_multi_exec_squash: false DFLY_conn_io_threads: 4 diff --git a/.github/workflows/test-backend.yml b/.github/workflows/test-backend.yml index 26c35269970e..20390f444301 100644 --- a/.github/workflows/test-backend.yml +++ b/.github/workflows/test-backend.yml @@ -38,7 +38,7 @@ jobs: env: DFLY_version_check: false DFLY_tcp_backlog: 2048 - DFLY_default_lua_flags: allow-undeclared-keys + DFLY_lock_on_hashtags: true DFLY_pipeline_squash: 0 DFLY_multi_exec_squash: false DFLY_conn_io_threads: 4 @@ -99,7 +99,7 @@ jobs: env: DFLY_version_check: false DFLY_tcp_backlog: 2048 - DFLY_default_lua_flags: allow-undeclared-keys + DFLY_lock_on_hashtags: true DFLY_pipeline_squash: 0 DFLY_multi_exec_squash: false DFLY_conn_io_threads: 4 diff --git a/chart/templates/Deployment.yml b/chart/templates/Deployment.yml index 2d3c89e673b9..d45dfebcaa8e 100644 --- a/chart/templates/Deployment.yml +++ b/chart/templates/Deployment.yml @@ -44,8 +44,8 @@ spec: value: false - name: DFLY_tcp_backlog value: 2048 - - name: DFLY_default_lua_flags - value: allow-undeclared-keys + - name: DFLY_lock_on_hashtags + value: true - name: DFLY_pipeline_squash value: 0 - name: DFLY_multi_exec_squash diff --git a/docker-compose.local-db.yml b/docker-compose.local-db.yml index 25793bc4f852..db2c4a8b5c7a 100644 --- a/docker-compose.local-db.yml +++ b/docker-compose.local-db.yml @@ -12,7 +12,7 @@ services: DFLY_snapshot_cron: '* * * * *' DFLY_version_check: false DFLY_tcp_backlog: 2048 - DFLY_default_lua_flags: allow-undeclared-keys + DFLY_lock_on_hashtags: true DFLY_pipeline_squash: 0 DFLY_multi_exec_squash: false DFLY_conn_io_threads: 4 diff --git a/docker-compose_example.yml b/docker-compose_example.yml index 379bc3d77f7c..eceda396f353 100644 --- a/docker-compose_example.yml +++ b/docker-compose_example.yml @@ -32,7 +32,7 @@ services: DFLY_snapshot_cron: '* * * * *' DFLY_version_check: false DFLY_tcp_backlog: 2048 - DFLY_default_lua_flags: allow-undeclared-keys + DFLY_lock_on_hashtags: true DFLY_pipeline_squash: 0 DFLY_multi_exec_squash: false DFLY_conn_io_threads: 4 diff --git a/packages/backend/src/config.ts b/packages/backend/src/config.ts index 046d9fe1b3ea..65e58a5606d8 100644 --- a/packages/backend/src/config.ts +++ b/packages/backend/src/config.ts @@ -17,6 +17,7 @@ export type RedisOptionsSource = Partial & { pass: string; db?: number; prefix?: string; + queueNameSuffix?: string; }; /** diff --git a/packages/backend/src/core/QueueModule.ts b/packages/backend/src/core/QueueModule.ts index d89fff81ee19..815443dd5703 100644 --- a/packages/backend/src/core/QueueModule.ts +++ b/packages/backend/src/core/QueueModule.ts @@ -6,8 +6,8 @@ import { Inject, Module, OnApplicationShutdown } from '@nestjs/common'; import * as Bull from 'bullmq'; import { DI } from '@/di-symbols.js'; -import type { Config } from '@/config.js'; -import { QUEUE, baseQueueOptions } from '@/queue/const.js'; +import type { Config, RedisOptionsSource } from '@/config.js'; +import { QUEUE, baseQueueOptions, formatQueueName } from '@/queue/const.js'; import { allSettled } from '@/misc/promise-tracker.js'; import { Queues } from '@/misc/queues.js'; import type { Provider } from '@nestjs/common'; @@ -36,13 +36,13 @@ const $endedPollNotification: Provider = { const $deliver: Provider = { provide: 'queue:deliver', - useFactory: (config: Config) => new Queues(config.redisForDeliverQueues.map(queueConfig => new Bull.Queue(QUEUE.DELIVER, baseQueueOptions(queueConfig, config.bullmqQueueOptions, QUEUE.DELIVER)))), + useFactory: (config: Config) => createQueues(QUEUE.DELIVER, config.redisForDeliverQueues, config.bullmqQueueOptions), inject: [DI.config], }; const $inbox: Provider = { provide: 'queue:inbox', - useFactory: (config: Config) => new Queues(config.redisForInboxQueues.map(queueConfig => new Bull.Queue(QUEUE.INBOX, baseQueueOptions(queueConfig, config.bullmqQueueOptions, QUEUE.INBOX)))), + useFactory: (config: Config) => createQueues(QUEUE.INBOX, config.redisForInboxQueues, config.bullmqQueueOptions), inject: [DI.config], }; @@ -54,7 +54,7 @@ const $db: Provider = { const $relationship: Provider = { provide: 'queue:relationship', - useFactory: (config: Config) => new Queues(config.redisForRelationshipQueues.map(queueConfig => new Bull.Queue(QUEUE.RELATIONSHIP, baseQueueOptions(queueConfig, config.bullmqQueueOptions, QUEUE.RELATIONSHIP)))), + useFactory: (config: Config) => createQueues(QUEUE.RELATIONSHIP, config.redisForRelationshipQueues, config.bullmqQueueOptions), inject: [DI.config], }; @@ -70,6 +70,10 @@ const $webhookDeliver: Provider = { inject: [DI.config], }; +function createQueues(name: typeof QUEUE[keyof typeof QUEUE], config: RedisOptionsSource[], queueOptions: Partial): Queues { + return new Queues(config.map(queueConfig => new Bull.Queue(formatQueueName(queueConfig, name), baseQueueOptions(queueConfig, queueOptions, name)))); +} + @Module({ imports: [ ], diff --git a/packages/backend/src/queue/QueueProcessorService.ts b/packages/backend/src/queue/QueueProcessorService.ts index ac571db25902..1e68f750abcd 100644 --- a/packages/backend/src/queue/QueueProcessorService.ts +++ b/packages/backend/src/queue/QueueProcessorService.ts @@ -42,7 +42,7 @@ import { CheckExpiredMutingsProcessorService } from './processors/CheckExpiredMu import { CleanProcessorService } from './processors/CleanProcessorService.js'; import { AggregateRetentionProcessorService } from './processors/AggregateRetentionProcessorService.js'; import { QueueLoggerService } from './QueueLoggerService.js'; -import { QUEUE, baseWorkerOptions } from './const.js'; +import { QUEUE, baseWorkerOptions, formatQueueName } from './const.js'; // ref. https://github.com/misskey-dev/misskey/pull/7635#issue-971097019 function httpRelatedBackoff(attemptsMade: number) { @@ -208,7 +208,7 @@ export class QueueProcessorService implements OnApplicationShutdown { //#region deliver this.deliverQueueWorkers = this.config.redisForDeliverQueues .filter((_, index) => process.env.QUEUE_WORKER_INDEX == null || index === Number.parseInt(process.env.QUEUE_WORKER_INDEX, 10)) - .map(config => new Bull.Worker(QUEUE.DELIVER, (job) => this.deliverProcessorService.process(job), { + .map(config => new Bull.Worker(formatQueueName(config, QUEUE.DELIVER), (job) => this.deliverProcessorService.process(job), { ...baseWorkerOptions(config, this.config.bullmqWorkerOptions, QUEUE.DELIVER), autorun: false, concurrency: this.config.deliverJobConcurrency ?? 128, @@ -236,7 +236,7 @@ export class QueueProcessorService implements OnApplicationShutdown { //#region inbox this.inboxQueueWorkers = this.config.redisForInboxQueues .filter((_, index) => process.env.QUEUE_WORKER_INDEX == null || index === Number.parseInt(process.env.QUEUE_WORKER_INDEX, 10)) - .map(config => new Bull.Worker(QUEUE.INBOX, (job) => this.inboxProcessorService.process(job), { + .map(config => new Bull.Worker(formatQueueName(config, QUEUE.INBOX), (job) => this.inboxProcessorService.process(job), { ...baseWorkerOptions(config, this.config.bullmqWorkerOptions, QUEUE.INBOX), autorun: false, concurrency: this.config.inboxJobConcurrency ?? 16, @@ -288,7 +288,7 @@ export class QueueProcessorService implements OnApplicationShutdown { //#region relationship this.relationshipQueueWorkers = this.config.redisForRelationshipQueues .filter((_, index) => process.env.QUEUE_WORKER_INDEX == null || index === Number.parseInt(process.env.QUEUE_WORKER_INDEX, 10)) - .map(config => new Bull.Worker(QUEUE.RELATIONSHIP, (job) => { + .map(config => new Bull.Worker(formatQueueName(config, QUEUE.RELATIONSHIP), (job) => { switch (job.name) { case 'follow': return this.relationshipProcessorService.processFollow(job); case 'unfollow': return this.relationshipProcessorService.processUnfollow(job); diff --git a/packages/backend/src/queue/const.ts b/packages/backend/src/queue/const.ts index 06edef1a2003..0c64a6d3f8c0 100644 --- a/packages/backend/src/queue/const.ts +++ b/packages/backend/src/queue/const.ts @@ -18,7 +18,12 @@ export const QUEUE = { WEBHOOK_DELIVER: 'webhookDeliver', }; +export function formatQueueName(config: RedisOptionsSource, queueName: typeof QUEUE[keyof typeof QUEUE]): string { + return typeof config.queueNameSuffix === 'string' ? `${queueName}-${config.queueNameSuffix}` : queueName; +} + export function baseQueueOptions(config: RedisOptions & RedisOptionsSource, queueOptions: Partial, queueName: typeof QUEUE[keyof typeof QUEUE]): Bull.QueueOptions { + const name = formatQueueName(config, queueName); return { ...queueOptions, connection: { @@ -33,11 +38,12 @@ export function baseQueueOptions(config: RedisOptions & RedisOptionsSource, queu return 1; }, }, - prefix: config.prefix ? `${config.prefix}:queue:${queueName}` : `queue:${queueName}`, + prefix: config.prefix ? `{${config.prefix}:queue:${name}}` : `{queue:${name}}`, }; } export function baseWorkerOptions(config: RedisOptions & RedisOptionsSource, workerOptions: Partial, queueName: typeof QUEUE[keyof typeof QUEUE]): Bull.WorkerOptions { + const name = formatQueueName(config, queueName); return { ...workerOptions, connection: { @@ -52,6 +58,6 @@ export function baseWorkerOptions(config: RedisOptions & RedisOptionsSource, wor return 1; }, }, - prefix: config.prefix ? `${config.prefix}:queue:${queueName}` : `queue:${queueName}`, + prefix: config.prefix ? `{${config.prefix}:queue:${name}}` : `{queue:${name}}`, }; } diff --git a/packages/backend/src/server/web/ClientServerService.ts b/packages/backend/src/server/web/ClientServerService.ts index 9c8ee94d6ae0..eef7c389bc76 100644 --- a/packages/backend/src/server/web/ClientServerService.ts +++ b/packages/backend/src/server/web/ClientServerService.ts @@ -245,13 +245,13 @@ export class ClientServerService { queues: [ this.systemQueue, this.endedPollNotificationQueue, + ...this.deliverQueue.queues, + ...this.inboxQueue.queues, this.dbQueue, + ...this.relationshipQueue.queues, this.objectStorageQueue, this.webhookDeliverQueue, - ].map(q => new BullMQAdapter(q)) - .concat(this.deliverQueue.queues.map((q, index) => new BullMQAdapter(q, { prefix: `${index}-` }))) - .concat(this.inboxQueue.queues.map((q, index) => new BullMQAdapter(q, { prefix: `${index}-` }))) - .concat(this.relationshipQueue.queues.map((q, index) => new BullMQAdapter(q, { prefix: `${index}-` }))), + ].map(q => new BullMQAdapter(q)), serverAdapter, }); diff --git a/packages/backend/test/docker-compose.yml b/packages/backend/test/docker-compose.yml index 74659a952ae8..d54d61ae7420 100644 --- a/packages/backend/test/docker-compose.yml +++ b/packages/backend/test/docker-compose.yml @@ -8,7 +8,7 @@ services: environment: DFLY_version_check: false DFLY_tcp_backlog: 2048 - DFLY_default_lua_flags: allow-undeclared-keys + DFLY_lock_on_hashtags: true DFLY_pipeline_squash: 0 DFLY_multi_exec_squash: false DFLY_conn_io_threads: 4 From 36e238197e508ed72e3609817df736828a25028f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E3=81=82=E3=82=8F=E3=82=8F=E3=82=8F=E3=81=A8=E3=83=BC?= =?UTF-8?q?=E3=81=AB=E3=82=85?= <17376330+u1-liquid@users.noreply.github.com> Date: Wed, 25 Dec 2024 11:37:24 +0900 Subject: [PATCH 2/5] Bump up version to 2024.5.0-io.5a (MisskeyIO#847) --- package.json | 2 +- packages/misskey-js/package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index ebf3a60d3933..e4970c592b86 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "misskey", - "version": "2024.5.0-io.5", + "version": "2024.5.0-io.5a", "codename": "nasubi", "repository": { "type": "git", diff --git a/packages/misskey-js/package.json b/packages/misskey-js/package.json index a09b05d90a6d..b095ac4743b0 100644 --- a/packages/misskey-js/package.json +++ b/packages/misskey-js/package.json @@ -1,7 +1,7 @@ { "type": "module", "name": "misskey-js", - "version": "2024.5.0-io.5", + "version": "2024.5.0-io.5a", "description": "Misskey SDK for JavaScript", "types": "./built/dts/index.d.ts", "exports": { From 5073467f1db8cec48238061136ef93b6bad9bb8a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E3=81=82=E3=82=8F=E3=82=8F=E3=82=8F=E3=81=A8=E3=83=BC?= =?UTF-8?q?=E3=81=AB=E3=82=85?= <17376330+u1-liquid@users.noreply.github.com> Date: Wed, 25 Dec 2024 13:02:32 +0900 Subject: [PATCH 3/5] enhance(data-usage): remove GA timing report on fetch note json (MisskeyIO#849) --- packages/frontend/src/components/MkTimeline.vue | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/packages/frontend/src/components/MkTimeline.vue b/packages/frontend/src/components/MkTimeline.vue index 94d89f8ce685..9c7e4587ddac 100644 --- a/packages/frontend/src/components/MkTimeline.vue +++ b/packages/frontend/src/components/MkTimeline.vue @@ -78,7 +78,6 @@ async function prepend(data) { // チェックするプロパティはなんでも良い // idOnlyが有効でid以外が存在しない場合は取得する if (!data.visibility) { - const initiateTime = Date.now(); const res = await window.fetch(`/notes/${data.id}.json`, { method: 'GET', credentials: 'omit', @@ -86,15 +85,6 @@ async function prepend(data) { 'Authorization': 'anonymous', 'X-Client-Transaction-Id': generateClientTransactionId('misskey'), }, - }).then(res => { - if (instance.googleAnalyticsId) { - gtagTime({ - name: 'api-get', - event_category: `/notes/${data.id}.json`, - value: Date.now() - initiateTime, - }); - } - return res; }); if (!res.ok) return; note = await res.json(); From 8b17ab77b4d7d4a87ee8dbfbaef983539d626c25 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E3=81=82=E3=82=8F=E3=82=8F=E3=82=8F=E3=81=A8=E3=83=BC?= =?UTF-8?q?=E3=81=AB=E3=82=85?= <17376330+u1-liquid@users.noreply.github.com> Date: Wed, 25 Dec 2024 14:13:45 +0900 Subject: [PATCH 4/5] =?UTF-8?q?fix(cdn-caching):=20=E8=87=AA=E5=88=86?= =?UTF-8?q?=E3=81=AE=E3=83=AA=E3=82=A2=E3=82=AF=E3=82=B7=E3=83=A7=E3=83=B3?= =?UTF-8?q?=E3=81=8C=E8=A1=A8=E7=A4=BA=E3=81=95=E3=82=8C=E3=81=AA=E3=81=84?= =?UTF-8?q?=E5=95=8F=E9=A1=8C=E3=82=92=E4=BF=AE=E6=AD=A3=20(MisskeyIO#851)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/server/api/stream/channels/antenna.ts | 14 ++++++---- .../src/server/api/stream/channels/channel.ts | 14 ++++++---- .../api/stream/channels/global-timeline.ts | 14 ++++++---- .../api/stream/channels/home-timeline.ts | 14 ++++++---- .../api/stream/channels/hybrid-timeline.ts | 14 ++++++---- .../api/stream/channels/local-timeline.ts | 14 ++++++---- .../api/stream/channels/role-timeline.ts | 14 ++++++---- .../server/api/stream/channels/user-list.ts | 14 ++++++---- packages/backend/test/utils.ts | 2 +- .../frontend/src/components/MkTimeline.vue | 26 +++++++++---------- packages/frontend/src/scripts/merge.ts | 2 +- packages/misskey-js/etc/misskey-js.api.md | 16 ++++++------ packages/misskey-js/src/streaming.types.ts | 16 ++++++------ 13 files changed, 103 insertions(+), 71 deletions(-) diff --git a/packages/backend/src/server/api/stream/channels/antenna.ts b/packages/backend/src/server/api/stream/channels/antenna.ts index 5c16cea60740..7fd34ccfdd70 100644 --- a/packages/backend/src/server/api/stream/channels/antenna.ts +++ b/packages/backend/src/server/api/stream/channels/antenna.ts @@ -15,7 +15,7 @@ class AntennaChannel extends Channel { public static readonly requireCredential = true as const; public static readonly kind = 'read:account'; private antennaId: string; - private idOnly: boolean; + private minimize: boolean; constructor( private noteEntityService: NoteEntityService, @@ -30,7 +30,7 @@ class AntennaChannel extends Channel { @bindThis public async init(params: any) { this.antennaId = params.antennaId as string; - this.idOnly = params.idOnly ?? false; + this.minimize = params.minimize ?? false; // Subscribe stream this.subscriber.on(`antennaStream:${this.antennaId}`, this.onEvent); @@ -51,9 +51,13 @@ class AntennaChannel extends Channel { if (this.isNoteMutedOrBlocked(note)) return; - if (this.idOnly && ['public', 'home'].includes(note.visibility)) { - const idOnlyNote = { id: note.id }; - this.send('note', idOnlyNote); + if (this.minimize && ['public', 'home'].includes(note.visibility)) { + this.send('note', { + id: note.id, myReaction: note.myReaction, + poll: note.poll ? { choices: note.poll.choices } : undefined, + reply: note.reply ? { myReaction: note.reply.myReaction } : undefined, + renote: note.renote ? { myReaction: note.renote.myReaction } : undefined, + }); } else { this.connection.cacheNote(note); this.send('note', note); diff --git a/packages/backend/src/server/api/stream/channels/channel.ts b/packages/backend/src/server/api/stream/channels/channel.ts index 94ffcd5d6273..e97928c8d40f 100644 --- a/packages/backend/src/server/api/stream/channels/channel.ts +++ b/packages/backend/src/server/api/stream/channels/channel.ts @@ -15,7 +15,7 @@ class ChannelChannel extends Channel { public static readonly shouldShare = false; public static readonly requireCredential = false as const; private channelId: string; - private idOnly: boolean; + private minimize: boolean; constructor( private noteEntityService: NoteEntityService, @@ -30,7 +30,7 @@ class ChannelChannel extends Channel { @bindThis public async init(params: any) { this.channelId = params.channelId as string; - this.idOnly = params.idOnly ?? false; + this.minimize = params.minimize ?? false; // Subscribe stream this.subscriber.on('notesStream', this.onNote); @@ -57,9 +57,13 @@ class ChannelChannel extends Channel { } } - if (this.idOnly && ['public', 'home'].includes(note.visibility)) { - const idOnlyNote = { id: note.id }; - this.send('note', idOnlyNote); + if (this.minimize && ['public', 'home'].includes(note.visibility)) { + this.send('note', { + id: note.id, myReaction: note.myReaction, + poll: note.poll ? { choices: note.poll.choices } : undefined, + reply: note.reply ? { myReaction: note.reply.myReaction } : undefined, + renote: note.renote ? { myReaction: note.renote.myReaction } : undefined, + }); } else { this.connection.cacheNote(note); this.send('note', note); diff --git a/packages/backend/src/server/api/stream/channels/global-timeline.ts b/packages/backend/src/server/api/stream/channels/global-timeline.ts index 64f194160388..d5f32c91f154 100644 --- a/packages/backend/src/server/api/stream/channels/global-timeline.ts +++ b/packages/backend/src/server/api/stream/channels/global-timeline.ts @@ -18,7 +18,7 @@ class GlobalTimelineChannel extends Channel { public static readonly requireCredential = false as const; private withRenotes: boolean; private withFiles: boolean; - private idOnly: boolean; + private minimize: boolean; constructor( private metaService: MetaService, @@ -39,7 +39,7 @@ class GlobalTimelineChannel extends Channel { this.withRenotes = params.withRenotes ?? true; this.withFiles = params.withFiles ?? false; - this.idOnly = params.idOnly ?? false; + this.minimize = params.minimize ?? false; // Subscribe events this.subscriber.on('notesStream', this.onNote); @@ -87,9 +87,13 @@ class GlobalTimelineChannel extends Channel { } } - if (this.idOnly && ['public', 'home'].includes(note.visibility)) { - const idOnlyNote = { id: note.id }; - this.send('note', idOnlyNote); + if (this.minimize && ['public', 'home'].includes(note.visibility)) { + this.send('note', { + id: note.id, myReaction: note.myReaction, + poll: note.poll ? { choices: note.poll.choices } : undefined, + reply: note.reply ? { myReaction: note.reply.myReaction } : undefined, + renote: note.renote ? { myReaction: note.renote.myReaction } : undefined, + }); } else { this.connection.cacheNote(note); this.send('note', note); diff --git a/packages/backend/src/server/api/stream/channels/home-timeline.ts b/packages/backend/src/server/api/stream/channels/home-timeline.ts index 3ee1935227ea..0f983c977a53 100644 --- a/packages/backend/src/server/api/stream/channels/home-timeline.ts +++ b/packages/backend/src/server/api/stream/channels/home-timeline.ts @@ -17,7 +17,7 @@ class HomeTimelineChannel extends Channel { public static readonly kind = 'read:account'; private withRenotes: boolean; private withFiles: boolean; - private idOnly: boolean; + private minimize: boolean; constructor( private noteEntityService: NoteEntityService, @@ -33,7 +33,7 @@ class HomeTimelineChannel extends Channel { public async init(params: any) { this.withRenotes = params.withRenotes ?? true; this.withFiles = params.withFiles ?? false; - this.idOnly = params.idOnly ?? false; + this.minimize = params.minimize ?? false; this.subscriber.on('notesStream', this.onNote); } @@ -91,9 +91,13 @@ class HomeTimelineChannel extends Channel { } } - if (this.idOnly && ['public', 'home'].includes(note.visibility)) { - const idOnlyNote = { id: note.id }; - this.send('note', idOnlyNote); + if (this.minimize && ['public', 'home'].includes(note.visibility)) { + this.send('note', { + id: note.id, myReaction: note.myReaction, + poll: note.poll ? { choices: note.poll.choices } : undefined, + reply: note.reply ? { myReaction: note.reply.myReaction } : undefined, + renote: note.renote ? { myReaction: note.renote.myReaction } : undefined, + }); } else { this.connection.cacheNote(note); this.send('note', note); diff --git a/packages/backend/src/server/api/stream/channels/hybrid-timeline.ts b/packages/backend/src/server/api/stream/channels/hybrid-timeline.ts index 20337f85b94b..8234d5c233be 100644 --- a/packages/backend/src/server/api/stream/channels/hybrid-timeline.ts +++ b/packages/backend/src/server/api/stream/channels/hybrid-timeline.ts @@ -20,7 +20,7 @@ class HybridTimelineChannel extends Channel { private withRenotes: boolean; private withReplies: boolean; private withFiles: boolean; - private idOnly: boolean; + private minimize: boolean; constructor( private metaService: MetaService, @@ -42,7 +42,7 @@ class HybridTimelineChannel extends Channel { this.withRenotes = params.withRenotes ?? true; this.withReplies = params.withReplies ?? false; this.withFiles = params.withFiles ?? false; - this.idOnly = params.idOnly ?? false; + this.minimize = params.minimize ?? false; // Subscribe events this.subscriber.on('notesStream', this.onNote); @@ -105,9 +105,13 @@ class HybridTimelineChannel extends Channel { } } - if (this.idOnly && ['public', 'home'].includes(note.visibility)) { - const idOnlyNote = { id: note.id }; - this.send('note', idOnlyNote); + if (this.minimize && ['public', 'home'].includes(note.visibility)) { + this.send('note', { + id: note.id, myReaction: note.myReaction, + poll: note.poll ? { choices: note.poll.choices } : undefined, + reply: note.reply ? { myReaction: note.reply.myReaction } : undefined, + renote: note.renote ? { myReaction: note.renote.myReaction } : undefined, + }); } else { this.connection.cacheNote(note); this.send('note', note); diff --git a/packages/backend/src/server/api/stream/channels/local-timeline.ts b/packages/backend/src/server/api/stream/channels/local-timeline.ts index 441b0132a52d..eae05fca653c 100644 --- a/packages/backend/src/server/api/stream/channels/local-timeline.ts +++ b/packages/backend/src/server/api/stream/channels/local-timeline.ts @@ -19,7 +19,7 @@ class LocalTimelineChannel extends Channel { private withRenotes: boolean; private withReplies: boolean; private withFiles: boolean; - private idOnly: boolean; + private minimize: boolean; constructor( private metaService: MetaService, @@ -41,7 +41,7 @@ class LocalTimelineChannel extends Channel { this.withRenotes = params.withRenotes ?? true; this.withReplies = params.withReplies ?? false; this.withFiles = params.withFiles ?? false; - this.idOnly = params.idOnly ?? false; + this.minimize = params.minimize ?? false; // Subscribe events this.subscriber.on('notesStream', this.onNote); @@ -90,9 +90,13 @@ class LocalTimelineChannel extends Channel { } } - if (this.idOnly && ['public', 'home'].includes(note.visibility)) { - const idOnlyNote = { id: note.id }; - this.send('note', idOnlyNote); + if (this.minimize && ['public', 'home'].includes(note.visibility)) { + this.send('note', { + id: note.id, myReaction: note.myReaction, + poll: note.poll ? { choices: note.poll.choices } : undefined, + reply: note.reply ? { myReaction: note.reply.myReaction } : undefined, + renote: note.renote ? { myReaction: note.renote.myReaction } : undefined, + }); } else { this.connection.cacheNote(note); this.send('note', note); diff --git a/packages/backend/src/server/api/stream/channels/role-timeline.ts b/packages/backend/src/server/api/stream/channels/role-timeline.ts index 3fb88857179d..746608c27347 100644 --- a/packages/backend/src/server/api/stream/channels/role-timeline.ts +++ b/packages/backend/src/server/api/stream/channels/role-timeline.ts @@ -16,7 +16,7 @@ class RoleTimelineChannel extends Channel { public static readonly shouldShare = false; public static readonly requireCredential = false as const; private roleId: string; - private idOnly: boolean; + private minimize: boolean; constructor( private noteEntityService: NoteEntityService, @@ -32,7 +32,7 @@ class RoleTimelineChannel extends Channel { @bindThis public async init(params: any) { this.roleId = params.roleId as string; - this.idOnly = params.idOnly ?? false; + this.minimize = params.minimize ?? false; this.subscriber.on(`roleTimelineStream:${this.roleId}`, this.onEvent); } @@ -73,9 +73,13 @@ class RoleTimelineChannel extends Channel { } } - if (this.idOnly && ['public', 'home'].includes(note.visibility)) { - const idOnlyNote = { id: note.id }; - this.send('note', idOnlyNote); + if (this.minimize && ['public', 'home'].includes(note.visibility)) { + this.send('note', { + id: note.id, myReaction: note.myReaction, + poll: note.poll ? { choices: note.poll.choices } : undefined, + reply: note.reply ? { myReaction: note.reply.myReaction } : undefined, + renote: note.renote ? { myReaction: note.renote.myReaction } : undefined, + }); } else { this.connection.cacheNote(note); this.send('note', note); diff --git a/packages/backend/src/server/api/stream/channels/user-list.ts b/packages/backend/src/server/api/stream/channels/user-list.ts index 651ab05f3402..3faeaddc7a1d 100644 --- a/packages/backend/src/server/api/stream/channels/user-list.ts +++ b/packages/backend/src/server/api/stream/channels/user-list.ts @@ -21,7 +21,7 @@ class UserListChannel extends Channel { private listUsersClock: NodeJS.Timeout; private withFiles: boolean; private withRenotes: boolean; - private idOnly: boolean; + private minimize: boolean; constructor( private userListsRepository: UserListsRepository, @@ -41,7 +41,7 @@ class UserListChannel extends Channel { this.listId = params.listId as string; this.withFiles = params.withFiles ?? false; this.withRenotes = params.withRenotes ?? true; - this.idOnly = params.idOnly ?? false; + this.minimize = params.minimize ?? false; // Check existence and owner const listExist = await this.userListsRepository.exists({ @@ -130,9 +130,13 @@ class UserListChannel extends Channel { } } - if (this.idOnly && ['public', 'home'].includes(note.visibility)) { - const idOnlyNote = { id: note.id }; - this.send('note', idOnlyNote); + if (this.minimize && ['public', 'home'].includes(note.visibility)) { + this.send('note', { + id: note.id, myReaction: note.myReaction, + poll: note.poll ? { choices: note.poll.choices } : undefined, + reply: note.reply ? { myReaction: note.reply.myReaction } : undefined, + renote: note.renote ? { myReaction: note.renote.myReaction } : undefined, + }); } else { this.connection.cacheNote(note); this.send('note', note); diff --git a/packages/backend/test/utils.ts b/packages/backend/test/utils.ts index 6ef69f4d3c58..573cafad6fe2 100644 --- a/packages/backend/test/utils.ts +++ b/packages/backend/test/utils.ts @@ -400,7 +400,7 @@ export const waitFire = async (user: UserToken if (timer) clearTimeout(timer); res(true); } - }, { ...params, idOnly: false }); + }, { ...params, minimize: false }); } catch (e) { rej(e); } diff --git a/packages/frontend/src/components/MkTimeline.vue b/packages/frontend/src/components/MkTimeline.vue index 9c7e4587ddac..cf451d4a008a 100644 --- a/packages/frontend/src/components/MkTimeline.vue +++ b/packages/frontend/src/components/MkTimeline.vue @@ -18,12 +18,12 @@ SPDX-License-Identifier: AGPL-3.0-only