From a32092a8b25dc83cbfd15cf284c36363e4e9d56c Mon Sep 17 00:00:00 2001 From: okayurisotto <47853651+okayurisotto@users.noreply.github.com> Date: Tue, 19 Nov 2024 00:21:12 +0900 Subject: [PATCH] =?UTF-8?q?WebSocket=E3=81=AE`mainStream`=E3=81=AB?= =?UTF-8?q?=E6=B5=81=E3=82=8C=E3=82=8B`meUpdated`=E3=82=A4=E3=83=99?= =?UTF-8?q?=E3=83=B3=E3=83=88=E3=81=A7=E3=82=A2=E3=83=83=E3=83=97=E3=83=87?= =?UTF-8?q?=E3=83=BC=E3=83=88=E5=BE=8C=E3=81=AE=E3=82=A2=E3=82=AB=E3=82=A6?= =?UTF-8?q?=E3=83=B3=E3=83=88=E6=83=85=E5=A0=B1=E3=82=92=E6=B5=81=E3=81=95?= =?UTF-8?q?=E3=81=AA=E3=81=84=E3=82=88=E3=81=86=E3=81=AB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit フロントエンドが`/api/i`を呼び出すことでアカウント情報を得るようにした。これにより - Redis PubSubストリーム内を巨大なデータが行き来する回数を減らしパフォーマンスが向上することが考えられる - 各`publish`処理が正確なアカウント情報を得るために`UserEntityService`に依存する状況を解消できる 特に後者は重要で、`UserEntityService`という巨大なサービスへの依存を減らせるのはコードの見通しもよくなる。現に`AccountMoveService`は`UserEntityService`への依存のせいで、`ApPersonService`と合わせて循環依存を作ってしまっている。これが解消できるのは大きい。 (cherry picked from commit 0d4cf43e61887c110a840f108ea5fea9afb1263b) --- packages/backend/src/core/AccountMoveService.ts | 2 +- packages/backend/src/core/GlobalEventService.ts | 2 +- .../backend/src/core/UserFollowingService.ts | 12 +++--------- .../src/server/api/endpoints/i/2fa/done.ts | 7 +------ .../src/server/api/endpoints/i/2fa/key-done.ts | 7 +------ .../server/api/endpoints/i/2fa/password-less.ts | 7 +------ .../src/server/api/endpoints/i/2fa/remove-key.ts | 7 +------ .../src/server/api/endpoints/i/2fa/unregister.ts | 7 +------ .../src/server/api/endpoints/i/2fa/update-key.ts | 7 +------ .../src/server/api/endpoints/i/update-email.ts | 2 +- .../backend/src/server/api/endpoints/i/update.ts | 2 +- packages/frontend/src/account.ts | 16 ++++++++++++---- packages/frontend/src/boot/main-boot.ts | 6 +++--- 13 files changed, 28 insertions(+), 56 deletions(-) diff --git a/packages/backend/src/core/AccountMoveService.ts b/packages/backend/src/core/AccountMoveService.ts index 24d11f29ff..69824ca69f 100644 --- a/packages/backend/src/core/AccountMoveService.ts +++ b/packages/backend/src/core/AccountMoveService.ts @@ -96,7 +96,7 @@ export class AccountMoveService { // Publish meUpdated event const iObj = await this.userEntityService.pack(src.id, src, { schema: 'MeDetailed', includeSecrets: true }); - this.globalEventService.publishMainStream(src.id, 'meUpdated', iObj); + this.globalEventService.publishMainStream(src.id, 'meUpdated'); // Unfollow after 24 hours const followings = await this.followingsRepository.findBy({ diff --git a/packages/backend/src/core/GlobalEventService.ts b/packages/backend/src/core/GlobalEventService.ts index 03646ff566..6311c1df02 100644 --- a/packages/backend/src/core/GlobalEventService.ts +++ b/packages/backend/src/core/GlobalEventService.ts @@ -57,7 +57,7 @@ export interface MainEventTypes { follow: Packed<'UserDetailedNotMe'>; followed: Packed<'UserLite'>; unfollow: Packed<'UserDetailedNotMe'>; - meUpdated: Packed<'MeDetailed'>; + meUpdated: undefined; pageEvent: { pageId: MiPage['id']; event: string; diff --git a/packages/backend/src/core/UserFollowingService.ts b/packages/backend/src/core/UserFollowingService.ts index 8963003057..8c544fc739 100644 --- a/packages/backend/src/core/UserFollowingService.ts +++ b/packages/backend/src/core/UserFollowingService.ts @@ -544,9 +544,7 @@ export class UserFollowingService implements OnModuleInit { if (this.userEntityService.isLocalUser(followee)) { this.userEntityService.pack(follower.id, followee).then(packed => this.globalEventService.publishMainStream(followee.id, 'receiveFollowRequest', packed)); - this.userEntityService.pack(followee.id, followee, { - schema: 'MeDetailed', - }).then(packed => this.globalEventService.publishMainStream(followee.id, 'meUpdated', packed)); + this.globalEventService.publishMainStream(followee.id, 'meUpdated'); // 通知を作成 this.notificationService.createNotification(followee.id, 'receiveFollowRequest', { @@ -592,9 +590,7 @@ export class UserFollowingService implements OnModuleInit { followerId: follower.id, }); - this.userEntityService.pack(followee.id, followee, { - schema: 'MeDetailed', - }).then(packed => this.globalEventService.publishMainStream(followee.id, 'meUpdated', packed)); + this.globalEventService.publishMainStream(followee.id, 'meUpdated'); } @bindThis @@ -619,9 +615,7 @@ export class UserFollowingService implements OnModuleInit { this.deliverAccept(follower, followee as MiPartialLocalUser, request.requestId ?? undefined); } - this.userEntityService.pack(followee.id, followee, { - schema: 'MeDetailed', - }).then(packed => this.globalEventService.publishMainStream(followee.id, 'meUpdated', packed)); + this.globalEventService.publishMainStream(followee.id, 'meUpdated'); } @bindThis diff --git a/packages/backend/src/server/api/endpoints/i/2fa/done.ts b/packages/backend/src/server/api/endpoints/i/2fa/done.ts index 2a30e8b0c3..c42d1facfd 100644 --- a/packages/backend/src/server/api/endpoints/i/2fa/done.ts +++ b/packages/backend/src/server/api/endpoints/i/2fa/done.ts @@ -6,7 +6,6 @@ import * as OTPAuth from 'otpauth'; import { Inject, Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; -import { UserEntityService } from '@/core/entities/UserEntityService.js'; import type { UserProfilesRepository } from '@/models/_.js'; import { GlobalEventService } from '@/core/GlobalEventService.js'; import { DI } from '@/di-symbols.js'; @@ -44,7 +43,6 @@ export default class extends Endpoint { // eslint- @Inject(DI.userProfilesRepository) private userProfilesRepository: UserProfilesRepository, - private userEntityService: UserEntityService, private globalEventService: GlobalEventService, ) { super(meta, paramDef, async (ps, me) => { @@ -76,10 +74,7 @@ export default class extends Endpoint { // eslint- }); // Publish meUpdated event - this.globalEventService.publishMainStream(me.id, 'meUpdated', await this.userEntityService.pack(me.id, me, { - schema: 'MeDetailed', - includeSecrets: true, - })); + this.globalEventService.publishMainStream(me.id, 'meUpdated'); return { backupCodes: backupCodes, diff --git a/packages/backend/src/server/api/endpoints/i/2fa/key-done.ts b/packages/backend/src/server/api/endpoints/i/2fa/key-done.ts index 65eece5b97..cd70693a10 100644 --- a/packages/backend/src/server/api/endpoints/i/2fa/key-done.ts +++ b/packages/backend/src/server/api/endpoints/i/2fa/key-done.ts @@ -6,7 +6,6 @@ import bcrypt from 'bcryptjs'; import { Inject, Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; -import { UserEntityService } from '@/core/entities/UserEntityService.js'; import { DI } from '@/di-symbols.js'; import { GlobalEventService } from '@/core/GlobalEventService.js'; import type { UserProfilesRepository, UserSecurityKeysRepository } from '@/models/_.js'; @@ -67,7 +66,6 @@ export default class extends Endpoint { private webAuthnService: WebAuthnService, private userAuthService: UserAuthService, - private userEntityService: UserEntityService, private globalEventService: GlobalEventService, ) { super(meta, paramDef, async (ps, me) => { @@ -110,10 +108,7 @@ export default class extends Endpoint { }); // Publish meUpdated event - this.globalEventService.publishMainStream(me.id, 'meUpdated', await this.userEntityService.pack(me.id, me, { - schema: 'MeDetailed', - includeSecrets: true, - })); + this.globalEventService.publishMainStream(me.id, 'meUpdated'); return { id: keyId, diff --git a/packages/backend/src/server/api/endpoints/i/2fa/password-less.ts b/packages/backend/src/server/api/endpoints/i/2fa/password-less.ts index bf039ccd16..8bc46d2ff1 100644 --- a/packages/backend/src/server/api/endpoints/i/2fa/password-less.ts +++ b/packages/backend/src/server/api/endpoints/i/2fa/password-less.ts @@ -5,7 +5,6 @@ import { Inject, Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; -import { UserEntityService } from '@/core/entities/UserEntityService.js'; import type { UserProfilesRepository, UserSecurityKeysRepository } from '@/models/_.js'; import { GlobalEventService } from '@/core/GlobalEventService.js'; import { DI } from '@/di-symbols.js'; @@ -42,7 +41,6 @@ export default class extends Endpoint { // eslint- @Inject(DI.userSecurityKeysRepository) private userSecurityKeysRepository: UserSecurityKeysRepository, - private userEntityService: UserEntityService, private globalEventService: GlobalEventService, ) { super(meta, paramDef, async (ps, me) => { @@ -73,10 +71,7 @@ export default class extends Endpoint { // eslint- }); // Publish meUpdated event - this.globalEventService.publishMainStream(me.id, 'meUpdated', await this.userEntityService.pack(me.id, me, { - schema: 'MeDetailed', - includeSecrets: true, - })); + this.globalEventService.publishMainStream(me.id, 'meUpdated'); }); } } diff --git a/packages/backend/src/server/api/endpoints/i/2fa/remove-key.ts b/packages/backend/src/server/api/endpoints/i/2fa/remove-key.ts index c350136eae..b411e066af 100644 --- a/packages/backend/src/server/api/endpoints/i/2fa/remove-key.ts +++ b/packages/backend/src/server/api/endpoints/i/2fa/remove-key.ts @@ -7,7 +7,6 @@ import bcrypt from 'bcryptjs'; import { Inject, Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; import type { UserProfilesRepository, UserSecurityKeysRepository } from '@/models/_.js'; -import { UserEntityService } from '@/core/entities/UserEntityService.js'; import { GlobalEventService } from '@/core/GlobalEventService.js'; import { DI } from '@/di-symbols.js'; import { ApiError } from '@/server/api/error.js'; @@ -46,7 +45,6 @@ export default class extends Endpoint { // eslint- @Inject(DI.userProfilesRepository) private userProfilesRepository: UserProfilesRepository, - private userEntityService: UserEntityService, private userAuthService: UserAuthService, private globalEventService: GlobalEventService, ) { @@ -96,10 +94,7 @@ export default class extends Endpoint { // eslint- } // Publish meUpdated event - this.globalEventService.publishMainStream(me.id, 'meUpdated', await this.userEntityService.pack(me.id, me, { - schema: 'MeDetailed', - includeSecrets: true, - })); + this.globalEventService.publishMainStream(me.id, 'meUpdated'); return {}; }); diff --git a/packages/backend/src/server/api/endpoints/i/2fa/unregister.ts b/packages/backend/src/server/api/endpoints/i/2fa/unregister.ts index b5a53cc889..fe718ef09a 100644 --- a/packages/backend/src/server/api/endpoints/i/2fa/unregister.ts +++ b/packages/backend/src/server/api/endpoints/i/2fa/unregister.ts @@ -6,7 +6,6 @@ import bcrypt from 'bcryptjs'; import { Inject, Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; -import { UserEntityService } from '@/core/entities/UserEntityService.js'; import type { UserProfilesRepository } from '@/models/_.js'; import { GlobalEventService } from '@/core/GlobalEventService.js'; import { DI } from '@/di-symbols.js'; @@ -42,7 +41,6 @@ export default class extends Endpoint { // eslint- @Inject(DI.userProfilesRepository) private userProfilesRepository: UserProfilesRepository, - private userEntityService: UserEntityService, private userAuthService: UserAuthService, private globalEventService: GlobalEventService, ) { @@ -75,10 +73,7 @@ export default class extends Endpoint { // eslint- }); // Publish meUpdated event - this.globalEventService.publishMainStream(me.id, 'meUpdated', await this.userEntityService.pack(me.id, me, { - schema: 'MeDetailed', - includeSecrets: true, - })); + this.globalEventService.publishMainStream(me.id, 'meUpdated'); }); } } diff --git a/packages/backend/src/server/api/endpoints/i/2fa/update-key.ts b/packages/backend/src/server/api/endpoints/i/2fa/update-key.ts index cfa07cc8d7..fe2a248742 100644 --- a/packages/backend/src/server/api/endpoints/i/2fa/update-key.ts +++ b/packages/backend/src/server/api/endpoints/i/2fa/update-key.ts @@ -7,7 +7,6 @@ import bcrypt from 'bcryptjs'; import { Inject, Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; import type { UserSecurityKeysRepository } from '@/models/_.js'; -import { UserEntityService } from '@/core/entities/UserEntityService.js'; import { GlobalEventService } from '@/core/GlobalEventService.js'; import { DI } from '@/di-symbols.js'; import { ApiError } from '../../../error.js'; @@ -47,7 +46,6 @@ export default class extends Endpoint { // eslint- @Inject(DI.userSecurityKeysRepository) private userSecurityKeysRepository: UserSecurityKeysRepository, - private userEntityService: UserEntityService, private globalEventService: GlobalEventService, ) { super(meta, paramDef, async (ps, me) => { @@ -68,10 +66,7 @@ export default class extends Endpoint { // eslint- }); // Publish meUpdated event - this.globalEventService.publishMainStream(me.id, 'meUpdated', await this.userEntityService.pack(me.id, me, { - schema: 'MeDetailed', - includeSecrets: true, - })); + this.globalEventService.publishMainStream(me.id, 'meUpdated'); return {}; }); diff --git a/packages/backend/src/server/api/endpoints/i/update-email.ts b/packages/backend/src/server/api/endpoints/i/update-email.ts index da1faee30d..aafd99c0eb 100644 --- a/packages/backend/src/server/api/endpoints/i/update-email.ts +++ b/packages/backend/src/server/api/endpoints/i/update-email.ts @@ -122,7 +122,7 @@ export default class extends Endpoint { // eslint- }); // Publish meUpdated event - this.globalEventService.publishMainStream(me.id, 'meUpdated', iObj); + this.globalEventService.publishMainStream(me.id, 'meUpdated'); if (ps.email != null) { const code = secureRndstr(16, { chars: L_CHARS }); diff --git a/packages/backend/src/server/api/endpoints/i/update.ts b/packages/backend/src/server/api/endpoints/i/update.ts index d3eeb75b27..90672339b1 100644 --- a/packages/backend/src/server/api/endpoints/i/update.ts +++ b/packages/backend/src/server/api/endpoints/i/update.ts @@ -527,7 +527,7 @@ export default class extends Endpoint { // eslint- this.cacheService.userProfileCache.set(user.id, updatedProfile); // Publish meUpdated event - this.globalEventService.publishMainStream(user.id, 'meUpdated', iObj); + this.globalEventService.publishMainStream(user.id, 'meUpdated'); // 鍵垢を解除したとき、溜まっていたフォローリクエストがあるならすべて承認 if (user.isLocked && ps.isLocked === false) { diff --git a/packages/frontend/src/account.ts b/packages/frontend/src/account.ts index 36186ecac1..aed128521e 100644 --- a/packages/frontend/src/account.ts +++ b/packages/frontend/src/account.ts @@ -22,7 +22,7 @@ type Account = Misskey.entities.MeDetailed & { token: string }; const accountData = miLocalStorage.getItem('account'); // TODO: 外部からはreadonlyに -export const $i = accountData ? reactive(JSON.parse(accountData) as Account) : null; +export let $i = accountData ? reactive(JSON.parse(accountData) as Account) : null; export const iAmModerator = $i != null && ($i.isAdmin === true || $i.isModerator === true); export const iAmAdmin = $i != null && $i.isAdmin; @@ -178,10 +178,18 @@ export function updateAccount(accountData: Account) { export function updateAccountPartial(accountData: Partial) { if (!$i) return; - for (const [key, value] of Object.entries(accountData)) { - $i[key] = value; + + if (accountData === null) { + void fetchAccount($i.token).then((accountData) => { + $i = accountData; + miLocalStorage.setItem('account', JSON.stringify($i)); + }); + } else { + for (const [key, value] of Object.entries(accountData)) { + $i[key] = value; + } + miLocalStorage.setItem('account', JSON.stringify($i)); } - miLocalStorage.setItem('account', JSON.stringify($i)); } export async function refreshAccount() { diff --git a/packages/frontend/src/boot/main-boot.ts b/packages/frontend/src/boot/main-boot.ts index 2bf9029479..89281d1243 100644 --- a/packages/frontend/src/boot/main-boot.ts +++ b/packages/frontend/src/boot/main-boot.ts @@ -11,7 +11,7 @@ import { i18n } from '@/i18n.js'; import { alert, confirm, popup, post, toast } from '@/os.js'; import { useStream } from '@/stream.js'; import * as sound from '@/scripts/sound.js'; -import { $i, signout, updateAccountPartial } from '@/account.js'; +import { $i, refreshAccount, signout, updateAccountPartial } from '@/account.js'; import { instance } from '@/instance.js'; import { ColdDeviceStorage, defaultStore } from '@/store.js'; import { reactionPicker } from '@/scripts/reaction-picker.js'; @@ -320,8 +320,8 @@ export async function mainBoot() { const main = markRaw(stream.useChannel('main', null, 'System')); // 自分の情報が更新されたとき - main.on('meUpdated', i => { - updateAccountPartial(i); + main.on('meUpdated', () => { + refreshAccount(); }); main.on('readAllNotifications', () => {