perf(backend): createPersonでキャッシュを積極的に利用する, トランザクション回数を減らす
This commit is contained in:
parent
ad9bb773c5
commit
05042a0697
|
@ -43,6 +43,7 @@ import type { ApLoggerService } from '../ApLoggerService.js';
|
||||||
// eslint-disable-next-line @typescript-eslint/consistent-type-imports
|
// eslint-disable-next-line @typescript-eslint/consistent-type-imports
|
||||||
import type { ApImageService } from './ApImageService.js';
|
import type { ApImageService } from './ApImageService.js';
|
||||||
import type { IActor, IObject } from '../type.js';
|
import type { IActor, IObject } from '../type.js';
|
||||||
|
import { ca } from 'date-fns/locale';
|
||||||
|
|
||||||
const nameLength = 128;
|
const nameLength = 128;
|
||||||
const summaryLength = 2048;
|
const summaryLength = 2048;
|
||||||
|
@ -259,13 +260,49 @@ export class ApPersonService implements OnModuleInit {
|
||||||
|
|
||||||
// Create user
|
// Create user
|
||||||
let user: RemoteUser | null = null;
|
let user: RemoteUser | null = null;
|
||||||
|
const userAdditionalInfo: Pick<RemoteUser, 'avatarId' | 'bannerId' | 'avatarUrl' | 'bannerUrl' | 'avatarBlurhash' | 'bannerBlurhash' | 'emojis'> = {
|
||||||
|
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 {
|
try {
|
||||||
// Start transaction
|
// Start transaction
|
||||||
await this.db.transaction(async transactionalEntityManager => {
|
await this.db.transaction(async transactionalEntityManager => {
|
||||||
user = await transactionalEntityManager.save(new User({
|
user = await transactionalEntityManager.save(new User({
|
||||||
id: this.idService.genId(),
|
id: this.idService.genId(),
|
||||||
avatarId: null,
|
|
||||||
bannerId: null,
|
|
||||||
createdAt: new Date(),
|
createdAt: new Date(),
|
||||||
lastFetchedAt: new Date(),
|
lastFetchedAt: new Date(),
|
||||||
name: truncate(person.name, nameLength),
|
name: truncate(person.name, nameLength),
|
||||||
|
@ -285,6 +322,7 @@ export class ApPersonService implements OnModuleInit {
|
||||||
tags,
|
tags,
|
||||||
isBot,
|
isBot,
|
||||||
isCat: (person as any).isCat === true,
|
isCat: (person as any).isCat === true,
|
||||||
|
...userAdditionalInfo,
|
||||||
})) as RemoteUser;
|
})) as RemoteUser;
|
||||||
|
|
||||||
await transactionalEntityManager.save(new UserProfile({
|
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');
|
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
|
// Register host
|
||||||
this.federatedInstanceService.fetch(host).then(async i => {
|
this.federatedInstanceService.fetch(host).then(async i => {
|
||||||
this.instancesRepository.increment({ id: i.id }, 'usersCount', 1);
|
this.instancesRepository.increment({ id: i.id }, 'usersCount', 1);
|
||||||
|
@ -335,48 +376,6 @@ export class ApPersonService implements OnModuleInit {
|
||||||
// ハッシュタグ更新
|
// ハッシュタグ更新
|
||||||
this.hashtagService.updateUsertags(user, tags);
|
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));
|
await this.updateFeatured(user.id, resolver).catch(err => this.logger.error(err));
|
||||||
|
|
||||||
return user;
|
return user;
|
||||||
|
@ -400,7 +399,7 @@ export class ApPersonService implements OnModuleInit {
|
||||||
if (uri.startsWith(`${this.config.url}/`)) return;
|
if (uri.startsWith(`${this.config.url}/`)) return;
|
||||||
|
|
||||||
//#region このサーバーに既に登録されているか
|
//#region このサーバーに既に登録されているか
|
||||||
const exist = await this.usersRepository.findOneBy({ uri }) as RemoteUser | null;
|
const exist = await this.fetchPerson(uri) as RemoteUser | null;
|
||||||
if (exist === null) return;
|
if (exist === null) return;
|
||||||
//#endregion
|
//#endregion
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue