From 05042a0697ed6ac80e48c7a50775c3dd9c379322 Mon Sep 17 00:00:00 2001 From: tamaina Date: Wed, 19 Jul 2023 06:39:39 +0000 Subject: [PATCH 1/7] =?UTF-8?q?perf(backend):=20createPerson=E3=81=A7?= =?UTF-8?q?=E3=82=AD=E3=83=A3=E3=83=83=E3=82=B7=E3=83=A5=E3=82=92=E7=A9=8D?= =?UTF-8?q?=E6=A5=B5=E7=9A=84=E3=81=AB=E5=88=A9=E7=94=A8=E3=81=99=E3=82=8B?= =?UTF-8?q?,=20=E3=83=88=E3=83=A9=E3=83=B3=E3=82=B6=E3=82=AF=E3=82=B7?= =?UTF-8?q?=E3=83=A7=E3=83=B3=E5=9B=9E=E6=95=B0=E3=82=92=E6=B8=9B=E3=82=89?= =?UTF-8?q?=E3=81=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../activitypub/models/ApPersonService.ts | 89 +++++++++---------- 1 file changed, 44 insertions(+), 45 deletions(-) diff --git a/packages/backend/src/core/activitypub/models/ApPersonService.ts b/packages/backend/src/core/activitypub/models/ApPersonService.ts index e89ee4632..22ef0b139 100644 --- a/packages/backend/src/core/activitypub/models/ApPersonService.ts +++ b/packages/backend/src/core/activitypub/models/ApPersonService.ts @@ -43,6 +43,7 @@ import type { ApLoggerService } from '../ApLoggerService.js'; // eslint-disable-next-line @typescript-eslint/consistent-type-imports import type { ApImageService } from './ApImageService.js'; import type { IActor, IObject } from '../type.js'; +import { ca } from 'date-fns/locale'; const nameLength = 128; const summaryLength = 2048; @@ -259,13 +260,49 @@ export class ApPersonService implements OnModuleInit { // Create user let user: RemoteUser | null = null; + const userAdditionalInfo: Pick = { + avatarId: null, + bannerId: null, + avatarUrl: null, + bannerUrl: null, + avatarBlurhash: null, + bannerBlurhash: null, + emojis: [], + }; + + try { + //#region アバターとヘッダー画像をフェッチ + const [avatar, banner] = await Promise.all([person.icon, person.image].map(img => { + if (img == null) return null; + if (user == null) throw new Error('failed to create user: user is null'); + return this.apImageService.resolveImage(user, img).catch(() => null); + })); + + userAdditionalInfo.avatarId = avatar?.id ?? null; + userAdditionalInfo.bannerId = banner?.id ?? null; + userAdditionalInfo.avatarUrl = avatar ? this.driveFileEntityService.getPublicUrl(avatar, 'avatar') : null; + userAdditionalInfo.bannerUrl = banner ? this.driveFileEntityService.getPublicUrl(banner) : null; + userAdditionalInfo.avatarBlurhash = avatar?.blurhash ?? null; + userAdditionalInfo.bannerBlurhash = banner?.blurhash ?? null; + //#endregion + } catch (err) { + this.logger.error('error occured while fetching user avatar/banner', { stack: err }); + } + + //#region カスタム絵文字取得 + userAdditionalInfo.emojis = await this.apNoteService.extractEmojis(person.tag ?? [], host) + .then(_emojis => _emojis.map(emoji => emoji.name)) + .catch(err => { + this.logger.error(`error occured while fetching user emojis`, { stack: err }); + return []; + }); + //#endregion + try { // Start transaction await this.db.transaction(async transactionalEntityManager => { user = await transactionalEntityManager.save(new User({ id: this.idService.genId(), - avatarId: null, - bannerId: null, createdAt: new Date(), lastFetchedAt: new Date(), name: truncate(person.name, nameLength), @@ -285,6 +322,7 @@ export class ApPersonService implements OnModuleInit { tags, isBot, isCat: (person as any).isCat === true, + ...userAdditionalInfo, })) as RemoteUser; await transactionalEntityManager.save(new UserProfile({ @@ -321,6 +359,9 @@ export class ApPersonService implements OnModuleInit { if (user == null) throw new Error('failed to create user: user is null'); + // Register to the cache + this.cacheService.uriPersonCache.set(user.uri, user); + // Register host this.federatedInstanceService.fetch(host).then(async i => { this.instancesRepository.increment({ id: i.id }, 'usersCount', 1); @@ -335,48 +376,6 @@ export class ApPersonService implements OnModuleInit { // ハッシュタグ更新 this.hashtagService.updateUsertags(user, tags); - //#region アバターとヘッダー画像をフェッチ - const [avatar, banner] = await Promise.all([person.icon, person.image].map(img => { - if (img == null) return null; - if (user == null) throw new Error('failed to create user: user is null'); - return this.apImageService.resolveImage(user, img).catch(() => null); - })); - - const avatarId = avatar?.id ?? null; - const bannerId = banner?.id ?? null; - const avatarUrl = avatar ? this.driveFileEntityService.getPublicUrl(avatar, 'avatar') : null; - const bannerUrl = banner ? this.driveFileEntityService.getPublicUrl(banner) : null; - const avatarBlurhash = avatar?.blurhash ?? null; - const bannerBlurhash = banner?.blurhash ?? null; - - await this.usersRepository.update(user.id, { - avatarId, - bannerId, - avatarUrl, - bannerUrl, - avatarBlurhash, - bannerBlurhash, - }); - - user.avatarId = avatarId; - user.bannerId = bannerId; - user.avatarUrl = avatarUrl; - user.bannerUrl = bannerUrl; - user.avatarBlurhash = avatarBlurhash; - user.bannerBlurhash = bannerBlurhash; - //#endregion - - //#region カスタム絵文字取得 - const emojis = await this.apNoteService.extractEmojis(person.tag ?? [], host).catch(err => { - this.logger.info(`extractEmojis: ${err}`); - return []; - }); - - const emojiNames = emojis.map(emoji => emoji.name); - - await this.usersRepository.update(user.id, { emojis: emojiNames }); - //#endregion - await this.updateFeatured(user.id, resolver).catch(err => this.logger.error(err)); return user; @@ -400,7 +399,7 @@ export class ApPersonService implements OnModuleInit { if (uri.startsWith(`${this.config.url}/`)) return; //#region このサーバーに既に登録されているか - const exist = await this.usersRepository.findOneBy({ uri }) as RemoteUser | null; + const exist = await this.fetchPerson(uri) as RemoteUser | null; if (exist === null) return; //#endregion From fc50dc7a67b0ddb996dca0f3c5cd687257152022 Mon Sep 17 00:00:00 2001 From: tamaina Date: Wed, 19 Jul 2023 06:43:09 +0000 Subject: [PATCH 2/7] move comment --- .../backend/src/core/activitypub/models/ApPersonService.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/backend/src/core/activitypub/models/ApPersonService.ts b/packages/backend/src/core/activitypub/models/ApPersonService.ts index 22ef0b139..aa3580599 100644 --- a/packages/backend/src/core/activitypub/models/ApPersonService.ts +++ b/packages/backend/src/core/activitypub/models/ApPersonService.ts @@ -270,8 +270,8 @@ export class ApPersonService implements OnModuleInit { emojis: [], }; + //#region アバターとヘッダー画像をフェッチ try { - //#region アバターとヘッダー画像をフェッチ const [avatar, banner] = await Promise.all([person.icon, person.image].map(img => { if (img == null) return null; if (user == null) throw new Error('failed to create user: user is null'); @@ -284,10 +284,10 @@ export class ApPersonService implements OnModuleInit { userAdditionalInfo.bannerUrl = banner ? this.driveFileEntityService.getPublicUrl(banner) : null; userAdditionalInfo.avatarBlurhash = avatar?.blurhash ?? null; userAdditionalInfo.bannerBlurhash = banner?.blurhash ?? null; - //#endregion } catch (err) { this.logger.error('error occured while fetching user avatar/banner', { stack: err }); } + //#endregion //#region カスタム絵文字取得 userAdditionalInfo.emojis = await this.apNoteService.extractEmojis(person.tag ?? [], host) From 660b0302338d912e39bdd3f8d95cad7e58a734b0 Mon Sep 17 00:00:00 2001 From: tamaina Date: Wed, 19 Jul 2023 06:59:12 +0000 Subject: [PATCH 3/7] fix --- .../activitypub/models/ApPersonService.ts | 82 ++++++++----------- 1 file changed, 34 insertions(+), 48 deletions(-) diff --git a/packages/backend/src/core/activitypub/models/ApPersonService.ts b/packages/backend/src/core/activitypub/models/ApPersonService.ts index aa3580599..37177a83e 100644 --- a/packages/backend/src/core/activitypub/models/ApPersonService.ts +++ b/packages/backend/src/core/activitypub/models/ApPersonService.ts @@ -44,6 +44,7 @@ import type { ApLoggerService } from '../ApLoggerService.js'; import type { ApImageService } from './ApImageService.js'; import type { IActor, IObject } from '../type.js'; import { ca } from 'date-fns/locale'; +import { users } from 'systeminformation'; const nameLength = 128; const summaryLength = 2048; @@ -221,6 +222,23 @@ export class ApPersonService implements OnModuleInit { return null; } + private async resolveAvatarAndBanner(user: RemoteUser, icon: any, image: any): Promise> { + const [avatar, banner] = await Promise.all([icon, image].map(img => { + if (img == null) return null; + if (user == null) throw new Error('failed to create user: user is null'); + return this.apImageService.resolveImage(user, img).catch(() => null); + })); + + return { + avatarId: avatar?.id ?? null, + bannerId: banner?.id ?? null, + avatarUrl: avatar ? this.driveFileEntityService.getPublicUrl(avatar, 'avatar') : null, + bannerUrl: banner ? this.driveFileEntityService.getPublicUrl(banner) : null, + avatarBlurhash: avatar?.blurhash ?? null, + bannerBlurhash: banner?.blurhash ?? null, + }; + } + /** * Personを作成します。 */ @@ -260,37 +278,9 @@ export class ApPersonService implements OnModuleInit { // Create user let user: RemoteUser | null = null; - const userAdditionalInfo: Pick = { - avatarId: null, - bannerId: null, - avatarUrl: null, - bannerUrl: null, - avatarBlurhash: null, - bannerBlurhash: null, - emojis: [], - }; - - //#region アバターとヘッダー画像をフェッチ - try { - const [avatar, banner] = await Promise.all([person.icon, person.image].map(img => { - if (img == null) return null; - if (user == null) throw new Error('failed to create user: user is null'); - return this.apImageService.resolveImage(user, img).catch(() => null); - })); - - userAdditionalInfo.avatarId = avatar?.id ?? null; - userAdditionalInfo.bannerId = banner?.id ?? null; - userAdditionalInfo.avatarUrl = avatar ? this.driveFileEntityService.getPublicUrl(avatar, 'avatar') : null; - userAdditionalInfo.bannerUrl = banner ? this.driveFileEntityService.getPublicUrl(banner) : null; - userAdditionalInfo.avatarBlurhash = avatar?.blurhash ?? null; - userAdditionalInfo.bannerBlurhash = banner?.blurhash ?? null; - } catch (err) { - this.logger.error('error occured while fetching user avatar/banner', { stack: err }); - } - //#endregion //#region カスタム絵文字取得 - userAdditionalInfo.emojis = await this.apNoteService.extractEmojis(person.tag ?? [], host) + const emojis = await this.apNoteService.extractEmojis(person.tag ?? [], host) .then(_emojis => _emojis.map(emoji => emoji.name)) .catch(err => { this.logger.error(`error occured while fetching user emojis`, { stack: err }); @@ -322,7 +312,7 @@ export class ApPersonService implements OnModuleInit { tags, isBot, isCat: (person as any).isCat === true, - ...userAdditionalInfo, + emojis, })) as RemoteUser; await transactionalEntityManager.save(new UserProfile({ @@ -362,6 +352,19 @@ export class ApPersonService implements OnModuleInit { // Register to the cache this.cacheService.uriPersonCache.set(user.uri, user); + //#region アバターとヘッダー画像をフェッチ + try { + const updates = await this.resolveAvatarAndBanner(user, person.icon, person.image); + await this.usersRepository.update(user.id, updates); + user = { ...user, ...updates }; + + // Register to the cache + this.cacheService.uriPersonCache.set(user.uri, user); + } catch (err) { + this.logger.error('error occured while fetching user avatar/banner', { stack: err }); + } + //#endregion + // Register host this.federatedInstanceService.fetch(host).then(async i => { this.instancesRepository.increment({ id: i.id }, 'usersCount', 1); @@ -412,12 +415,6 @@ export class ApPersonService implements OnModuleInit { this.logger.info(`Updating the Person: ${person.id}`); - // アバターとヘッダー画像をフェッチ - const [avatar, banner] = await Promise.all([person.icon, person.image].map(img => { - if (img == null) return null; - return this.apImageService.resolveImage(exist, img).catch(() => null); - })); - // カスタム絵文字取得 const emojis = await this.apNoteService.extractEmojis(person.tag ?? [], exist.host).catch(e => { this.logger.info(`extractEmojis: ${e}`); @@ -453,6 +450,7 @@ export class ApPersonService implements OnModuleInit { movedToUri: person.movedTo ?? null, alsoKnownAs: person.alsoKnownAs ?? null, isExplorable: person.discoverable, + ...(await this.resolveAvatarAndBanner(exist, person.icon, person.image).catch(() => ({}))), } as Partial & Pick; const moving = ((): boolean => { @@ -475,18 +473,6 @@ export class ApPersonService implements OnModuleInit { if (moving) updates.movedAt = new Date(); - if (avatar) { - updates.avatarId = avatar.id; - updates.avatarUrl = this.driveFileEntityService.getPublicUrl(avatar, 'avatar'); - updates.avatarBlurhash = avatar.blurhash; - } - - if (banner) { - updates.bannerId = banner.id; - updates.bannerUrl = this.driveFileEntityService.getPublicUrl(banner); - updates.bannerBlurhash = banner.blurhash; - } - // Update user await this.usersRepository.update(exist.id, updates); From 4e7a26e6d5faa9760077062752940ded9662f50d Mon Sep 17 00:00:00 2001 From: tamaina Date: Wed, 19 Jul 2023 07:00:50 +0000 Subject: [PATCH 4/7] oops --- packages/backend/src/core/activitypub/models/ApPersonService.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/packages/backend/src/core/activitypub/models/ApPersonService.ts b/packages/backend/src/core/activitypub/models/ApPersonService.ts index 37177a83e..8f2997ac8 100644 --- a/packages/backend/src/core/activitypub/models/ApPersonService.ts +++ b/packages/backend/src/core/activitypub/models/ApPersonService.ts @@ -43,8 +43,6 @@ import type { ApLoggerService } from '../ApLoggerService.js'; // eslint-disable-next-line @typescript-eslint/consistent-type-imports import type { ApImageService } from './ApImageService.js'; import type { IActor, IObject } from '../type.js'; -import { ca } from 'date-fns/locale'; -import { users } from 'systeminformation'; const nameLength = 128; const summaryLength = 2048; From 4c83663597e424364e3592ad00f12f3141d79236 Mon Sep 17 00:00:00 2001 From: tamaina Date: Wed, 19 Jul 2023 07:03:07 +0000 Subject: [PATCH 5/7] fix --- packages/backend/src/core/activitypub/models/ApPersonService.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/backend/src/core/activitypub/models/ApPersonService.ts b/packages/backend/src/core/activitypub/models/ApPersonService.ts index 8f2997ac8..4f83983be 100644 --- a/packages/backend/src/core/activitypub/models/ApPersonService.ts +++ b/packages/backend/src/core/activitypub/models/ApPersonService.ts @@ -291,6 +291,8 @@ export class ApPersonService implements OnModuleInit { await this.db.transaction(async transactionalEntityManager => { user = await transactionalEntityManager.save(new User({ id: this.idService.genId(), + avatarId: null, + bannerId: null, createdAt: new Date(), lastFetchedAt: new Date(), name: truncate(person.name, nameLength), From a2f6bf3d5c93d02d36c37bdae0235a4ade2620f5 Mon Sep 17 00:00:00 2001 From: tamaina Date: Wed, 19 Jul 2023 07:03:30 +0000 Subject: [PATCH 6/7] fix --- .../core/activitypub/models/ApPersonService.ts | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/packages/backend/src/core/activitypub/models/ApPersonService.ts b/packages/backend/src/core/activitypub/models/ApPersonService.ts index 4f83983be..028b5148b 100644 --- a/packages/backend/src/core/activitypub/models/ApPersonService.ts +++ b/packages/backend/src/core/activitypub/models/ApPersonService.ts @@ -352,6 +352,15 @@ export class ApPersonService implements OnModuleInit { // Register to the cache this.cacheService.uriPersonCache.set(user.uri, user); + // Register host + this.federatedInstanceService.fetch(host).then(async i => { + this.instancesRepository.increment({ id: i.id }, 'usersCount', 1); + this.fetchInstanceMetadataService.fetchInstanceMetadata(i); + if ((await this.metaService.fetch()).enableChartsForFederatedInstances) { + this.instanceChart.newUser(i.host); + } + }); + //#region アバターとヘッダー画像をフェッチ try { const updates = await this.resolveAvatarAndBanner(user, person.icon, person.image); @@ -365,15 +374,6 @@ export class ApPersonService implements OnModuleInit { } //#endregion - // Register host - this.federatedInstanceService.fetch(host).then(async i => { - this.instancesRepository.increment({ id: i.id }, 'usersCount', 1); - this.fetchInstanceMetadataService.fetchInstanceMetadata(i); - if ((await this.metaService.fetch()).enableChartsForFederatedInstances) { - this.instanceChart.newUser(i.host); - } - }); - this.usersChart.update(user, true); // ハッシュタグ更新 From ee1e2aa200f1b0ebc8b7337048b1c3d538961ea8 Mon Sep 17 00:00:00 2001 From: tamaina Date: Wed, 19 Jul 2023 07:05:02 +0000 Subject: [PATCH 7/7] fix --- .../src/core/activitypub/models/ApPersonService.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/backend/src/core/activitypub/models/ApPersonService.ts b/packages/backend/src/core/activitypub/models/ApPersonService.ts index 028b5148b..8fc083719 100644 --- a/packages/backend/src/core/activitypub/models/ApPersonService.ts +++ b/packages/backend/src/core/activitypub/models/ApPersonService.ts @@ -361,6 +361,11 @@ export class ApPersonService implements OnModuleInit { } }); + this.usersChart.update(user, true); + + // ハッシュタグ更新 + this.hashtagService.updateUsertags(user, tags); + //#region アバターとヘッダー画像をフェッチ try { const updates = await this.resolveAvatarAndBanner(user, person.icon, person.image); @@ -374,11 +379,6 @@ export class ApPersonService implements OnModuleInit { } //#endregion - this.usersChart.update(user, true); - - // ハッシュタグ更新 - this.hashtagService.updateUsertags(user, tags); - await this.updateFeatured(user.id, resolver).catch(err => this.logger.error(err)); return user;