perf(backend): cache avatar and banner url to db
This commit is contained in:
@@ -415,7 +415,7 @@ export class NoteEntityService implements OnModuleInit {
|
||||
await this.customEmojiService.prefetchEmojis(this.aggregateNoteEmojis(notes));
|
||||
// TODO: 本当は renote とか reply がないのに renoteId とか replyId があったらここで解決しておく
|
||||
const fileIds = notes.map(n => [n.fileIds, n.renote?.fileIds, n.reply?.fileIds]).flat(2).filter(isNotNull);
|
||||
const packedFiles = await this.driveFileEntityService.packManyByIdsMap(fileIds);
|
||||
const packedFiles = fileIds.length > 0 ? await this.driveFileEntityService.packManyByIdsMap(fileIds) : new Map();
|
||||
|
||||
return await Promise.all(notes.map(n => this.pack(n, me, {
|
||||
...options,
|
||||
|
@@ -113,7 +113,7 @@ export class NotificationEntityService implements OnModuleInit {
|
||||
const noteIds = validNotifications.map(x => x.noteId).filter(isNotNull);
|
||||
const notes = noteIds.length > 0 ? await this.notesRepository.find({
|
||||
where: { id: In(noteIds) },
|
||||
relations: ['user', 'user.avatar', 'user.banner', 'reply', 'reply.user', 'reply.user.avatar', 'reply.user.banner', 'renote', 'renote.user', 'renote.user.avatar', 'renote.user.banner'],
|
||||
relations: ['user', 'reply', 'reply.user', 'renote', 'renote.user'],
|
||||
}) : [];
|
||||
const packedNotesArray = await this.noteEntityService.packMany(notes, { id: meId }, {
|
||||
detail: true,
|
||||
@@ -125,7 +125,6 @@ export class NotificationEntityService implements OnModuleInit {
|
||||
const userIds = validNotifications.map(x => x.notifierId).filter(isNotNull);
|
||||
const users = userIds.length > 0 ? await this.usersRepository.find({
|
||||
where: { id: In(userIds) },
|
||||
relations: ['avatar', 'banner'],
|
||||
}) : [];
|
||||
const packedUsersArray = await this.userEntityService.packMany(users, { id: meId }, {
|
||||
detail: false,
|
||||
|
@@ -269,27 +269,6 @@ export class UserEntityService implements OnModuleInit {
|
||||
);
|
||||
}
|
||||
|
||||
@bindThis
|
||||
public async getAvatarUrl(user: User): Promise<string> {
|
||||
if (user.avatar) {
|
||||
return this.driveFileEntityService.getPublicUrl(user.avatar, 'avatar') ?? this.getIdenticonUrl(user);
|
||||
} else if (user.avatarId) {
|
||||
const avatar = await this.driveFilesRepository.findOneByOrFail({ id: user.avatarId });
|
||||
return this.driveFileEntityService.getPublicUrl(avatar, 'avatar') ?? this.getIdenticonUrl(user);
|
||||
} else {
|
||||
return this.getIdenticonUrl(user);
|
||||
}
|
||||
}
|
||||
|
||||
@bindThis
|
||||
public getAvatarUrlSync(user: User): string {
|
||||
if (user.avatar) {
|
||||
return this.driveFileEntityService.getPublicUrl(user.avatar, 'avatar') ?? this.getIdenticonUrl(user);
|
||||
} else {
|
||||
return this.getIdenticonUrl(user);
|
||||
}
|
||||
}
|
||||
|
||||
@bindThis
|
||||
public getIdenticonUrl(user: User): string {
|
||||
return `${this.config.url}/identicon/${user.username.toLowerCase()}@${user.host ?? this.config.host}`;
|
||||
@@ -309,19 +288,23 @@ export class UserEntityService implements OnModuleInit {
|
||||
includeSecrets: false,
|
||||
}, options);
|
||||
|
||||
let user: User;
|
||||
const user = typeof src === 'object' ? src : await this.usersRepository.findOneByOrFail({ id: src });
|
||||
|
||||
if (typeof src === 'object') {
|
||||
user = src;
|
||||
if (src.avatar === undefined && src.avatarId) src.avatar = await this.driveFilesRepository.findOneBy({ id: src.avatarId }) ?? null;
|
||||
if (src.banner === undefined && src.bannerId) src.banner = await this.driveFilesRepository.findOneBy({ id: src.bannerId }) ?? null;
|
||||
} else {
|
||||
user = await this.usersRepository.findOneOrFail({
|
||||
where: { id: src },
|
||||
relations: {
|
||||
avatar: true,
|
||||
banner: true,
|
||||
},
|
||||
// migration
|
||||
if (user.avatarId != null && user.avatarUrl === null) {
|
||||
const avatar = await this.driveFilesRepository.findOneByOrFail({ id: user.avatarId });
|
||||
user.avatarUrl = this.driveFileEntityService.getPublicUrl(avatar, 'avatar');
|
||||
this.usersRepository.update(user.id, {
|
||||
avatarUrl: user.avatarUrl,
|
||||
avatarBlurhash: avatar.blurhash,
|
||||
});
|
||||
}
|
||||
if (user.bannerId != null && user.bannerUrl === null) {
|
||||
const banner = await this.driveFilesRepository.findOneByOrFail({ id: user.bannerId });
|
||||
user.bannerUrl = this.driveFileEntityService.getPublicUrl(banner);
|
||||
this.usersRepository.update(user.id, {
|
||||
bannerUrl: user.bannerUrl,
|
||||
bannerBlurhash: banner.blurhash,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -356,8 +339,8 @@ export class UserEntityService implements OnModuleInit {
|
||||
name: user.name,
|
||||
username: user.username,
|
||||
host: user.host,
|
||||
avatarUrl: this.getAvatarUrlSync(user),
|
||||
avatarBlurhash: user.avatar?.blurhash ?? null,
|
||||
avatarUrl: user.avatarUrl ?? this.getIdenticonUrl(user),
|
||||
avatarBlurhash: user.avatarBlurhash,
|
||||
isBot: user.isBot ?? falsy,
|
||||
isCat: user.isCat ?? falsy,
|
||||
instance: user.host ? this.userInstanceCache.fetch(user.host,
|
||||
@@ -386,8 +369,8 @@ export class UserEntityService implements OnModuleInit {
|
||||
createdAt: user.createdAt.toISOString(),
|
||||
updatedAt: user.updatedAt ? user.updatedAt.toISOString() : null,
|
||||
lastFetchedAt: user.lastFetchedAt ? user.lastFetchedAt.toISOString() : null,
|
||||
bannerUrl: user.banner ? this.driveFileEntityService.getPublicUrl(user.banner) : null,
|
||||
bannerBlurhash: user.banner?.blurhash ?? null,
|
||||
bannerUrl: user.bannerUrl,
|
||||
bannerBlurhash: user.bannerBlurhash,
|
||||
isLocked: user.isLocked,
|
||||
isSilenced: this.roleService.getUserPolicies(user.id).then(r => !r.canPublicNote),
|
||||
isSuspended: user.isSuspended ?? falsy,
|
||||
|
Reference in New Issue
Block a user