summaryrefslogtreecommitdiff
path: root/src/models
diff options
context:
space:
mode:
authorsyuilo <Syuilotan@yahoo.co.jp>2021-03-20 13:54:59 +0900
committersyuilo <Syuilotan@yahoo.co.jp>2021-03-20 13:54:59 +0900
commitf27e4033a6599203ba37efe01edbd988699b4068 (patch)
tree39249a742055a53c9690f89fdbef8980e48fe01b /src/models
parentperf(server): Reduce database query (diff)
downloadmisskey-f27e4033a6599203ba37efe01edbd988699b4068.tar.gz
misskey-f27e4033a6599203ba37efe01edbd988699b4068.tar.bz2
misskey-f27e4033a6599203ba37efe01edbd988699b4068.zip
perf(server): Reduce database query
Related: #6813
Diffstat (limited to 'src/models')
-rw-r--r--src/models/repositories/note.ts86
-rw-r--r--src/models/repositories/notification.ts45
-rw-r--r--src/models/repositories/user.ts40
3 files changed, 156 insertions, 15 deletions
diff --git a/src/models/repositories/note.ts b/src/models/repositories/note.ts
index 43caaf94b2..1fcedbd56f 100644
--- a/src/models/repositories/note.ts
+++ b/src/models/repositories/note.ts
@@ -85,6 +85,7 @@ export class NoteRepository extends Repository<Note> {
detail?: boolean;
skipHide?: boolean;
_hint_?: {
+ emojis: Emoji[] | null;
myReactions: Map<Note['id'], NoteReaction | null>;
};
}
@@ -141,11 +142,43 @@ export class NoteRepository extends Repository<Note> {
* @param reactionNames Note等にリアクションされたカスタム絵文字名 (:は含めない)
*/
async function populateEmojis(emojiNames: string[], noteUserHost: string | null, reactionNames: string[]) {
+ const customReactions = reactionNames?.map(x => decodeReaction(x)).filter(x => x.name);
+
let all = [] as {
name: string,
url: string
}[];
+ // 与えられたhintだけで十分(=新たにクエリする必要がない)かどうかを表すフラグ
+ let enough = true;
+ if (options?._hint_?.emojis) {
+ for (const name of emojiNames) {
+ const matched = options._hint_.emojis.find(x => x.name === name && x.host === noteUserHost);
+ if (matched) {
+ all.push({
+ name: matched.name,
+ url: matched.url,
+ });
+ } else {
+ enough = false;
+ }
+ }
+ for (const customReaction of customReactions) {
+ const matched = options._hint_.emojis.find(x => x.name === customReaction.name && x.host === customReaction.host);
+ if (matched) {
+ all.push({
+ name: `${matched.name}@${matched.host || '.'}`, // @host付きでローカルは.
+ url: matched.url,
+ });
+ } else {
+ enough = false;
+ }
+ }
+ } else {
+ enough = false;
+ }
+ if (enough) return all;
+
// カスタム絵文字
if (emojiNames?.length > 0) {
const tmp = await Emojis.find({
@@ -164,8 +197,6 @@ export class NoteRepository extends Repository<Note> {
all = concat([all, tmp]);
}
- const customReactions = reactionNames?.map(x => decodeReaction(x)).filter(x => x.name);
-
if (customReactions?.length > 0) {
const where = [] as {}[];
@@ -230,7 +261,12 @@ export class NoteRepository extends Repository<Note> {
id: note.id,
createdAt: note.createdAt.toISOString(),
userId: note.userId,
- user: Users.pack(note.user || note.userId, meId),
+ user: Users.pack(note.user || note.userId, meId, {
+ detail: false,
+ _hint_: {
+ emojis: options?._hint_?.emojis || null
+ }
+ }),
text: text,
cw: note.cw,
visibility: note.visibility,
@@ -258,12 +294,12 @@ export class NoteRepository extends Repository<Note> {
_prId_: (note as any)._prId_ || undefined,
...(opts.detail ? {
- reply: note.replyId ? this.pack(note.replyId, meId, {
+ reply: note.replyId ? this.pack(note.reply || note.replyId, meId, {
detail: false,
_hint_: options?._hint_
}) : undefined,
- renote: note.renoteId ? this.pack(note.renoteId, meId, {
+ renote: note.renoteId ? this.pack(note.renote || note.renoteId, meId, {
detail: true,
_hint_: options?._hint_
}) : undefined,
@@ -314,10 +350,48 @@ export class NoteRepository extends Repository<Note> {
}
}
+ // TODO: ここら辺の処理をaggregateEmojisみたいな関数に切り出したい
+ let emojisWhere: any[] = [];
+ for (const note of notes) {
+ if (typeof note !== 'object') continue;
+ emojisWhere.push({
+ name: In(note.emojis),
+ host: note.userHost
+ });
+ if (note.renote) {
+ emojisWhere.push({
+ name: In(note.renote.emojis),
+ host: note.renote.userHost
+ });
+ if (note.renote.user) {
+ emojisWhere.push({
+ name: In(note.renote.user.emojis),
+ host: note.renote.userHost
+ });
+ }
+ }
+ const customReactions = Object.keys(note.reactions).map(x => decodeReaction(x)).filter(x => x.name);
+ emojisWhere = emojisWhere.concat(customReactions.map(x => ({
+ name: x.name,
+ host: x.host
+ })));
+ if (note.user) {
+ emojisWhere.push({
+ name: In(note.user.emojis),
+ host: note.userHost
+ });
+ }
+ }
+ const emojis = emojisWhere.length > 0 ? await Emojis.find({
+ where: emojisWhere,
+ select: ['name', 'host', 'url']
+ }) : null;
+
return await Promise.all(notes.map(n => this.pack(n, me, {
...options,
_hint_: {
- myReactions: myReactionsMap
+ myReactions: myReactionsMap,
+ emojis: emojis
}
})));
}
diff --git a/src/models/repositories/notification.ts b/src/models/repositories/notification.ts
index a9fe5e7b4e..1027155873 100644
--- a/src/models/repositories/notification.ts
+++ b/src/models/repositories/notification.ts
@@ -1,11 +1,13 @@
import { EntityRepository, In, Repository } from 'typeorm';
-import { Users, Notes, UserGroupInvitations, AccessTokens, NoteReactions } from '..';
+import { Users, Notes, UserGroupInvitations, AccessTokens, NoteReactions, Emojis } from '..';
import { Notification } from '../entities/notification';
import { awaitAll } from '../../prelude/await-all';
import { SchemaType } from '../../misc/schema';
import { Note } from '../entities/note';
import { NoteReaction } from '../entities/note-reaction';
import { User } from '../entities/user';
+import { decodeReaction } from '../../misc/reaction-lib';
+import { Emoji } from '../entities/emoji';
export type PackedNotification = SchemaType<typeof packedNotificationSchema>;
@@ -15,6 +17,7 @@ export class NotificationRepository extends Repository<Notification> {
src: Notification['id'] | Notification,
options: {
_hintForEachNotes_: {
+ emojis: Emoji[] | null;
myReactions: Map<Note['id'], NoteReaction | null>;
};
}
@@ -98,9 +101,47 @@ export class NotificationRepository extends Repository<Notification> {
myReactionsMap.set(target, myReactions.find(reaction => reaction.noteId === target) || null);
}
+ // TODO: ここら辺の処理をaggregateEmojisみたいな関数に切り出したい
+ let emojisWhere: any[] = [];
+ for (const note of notes) {
+ if (typeof note !== 'object') continue;
+ emojisWhere.push({
+ name: In(note.emojis),
+ host: note.userHost
+ });
+ if (note.renote) {
+ emojisWhere.push({
+ name: In(note.renote.emojis),
+ host: note.renote.userHost
+ });
+ if (note.renote.user) {
+ emojisWhere.push({
+ name: In(note.renote.user.emojis),
+ host: note.renote.userHost
+ });
+ }
+ }
+ const customReactions = Object.keys(note.reactions).map(x => decodeReaction(x)).filter(x => x.name);
+ emojisWhere = emojisWhere.concat(customReactions.map(x => ({
+ name: x.name,
+ host: x.host
+ })));
+ if (note.user) {
+ emojisWhere.push({
+ name: In(note.user.emojis),
+ host: note.userHost
+ });
+ }
+ }
+ const emojis = emojisWhere.length > 0 ? await Emojis.find({
+ where: emojisWhere,
+ select: ['name', 'host', 'url']
+ }) : null;
+
return await Promise.all(notifications.map(x => this.pack(x, {
_hintForEachNotes_: {
- myReactions: myReactionsMap
+ myReactions: myReactionsMap,
+ emojis: emojis,
}
})));
}
diff --git a/src/models/repositories/user.ts b/src/models/repositories/user.ts
index 3a6ab48c5f..19b0e54239 100644
--- a/src/models/repositories/user.ts
+++ b/src/models/repositories/user.ts
@@ -5,6 +5,7 @@ import { Emojis, Notes, NoteUnreads, FollowRequests, Notifications, MessagingMes
import config from '../../config';
import { SchemaType } from '../../misc/schema';
import { awaitAll } from '../../prelude/await-all';
+import { Emoji } from '../entities/emoji';
export type PackedUser = SchemaType<typeof packedUserSchema>;
@@ -149,6 +150,9 @@ export class UserRepository extends Repository<User> {
options?: {
detail?: boolean,
includeSecrets?: boolean,
+ _hint_?: {
+ emojis: Emoji[] | null;
+ };
}
): Promise<PackedUser> {
const opts = Object.assign({
@@ -166,6 +170,34 @@ export class UserRepository extends Repository<User> {
}) : [];
const profile = opts.detail ? await UserProfiles.findOneOrFail(user.id) : null;
+ let emojis: Emoji[] = [];
+ if (user.emojis.length > 0) {
+ // 与えられたhintだけで十分(=新たにクエリする必要がない)かどうかを表すフラグ
+ let enough = true;
+ if (options?._hint_?.emojis) {
+ for (const name of user.emojis) {
+ const matched = options._hint_.emojis.find(x => x.name === name && x.host === user.host);
+ if (matched) {
+ emojis.push(matched);
+ } else {
+ enough = false;
+ }
+ }
+ } else {
+ enough = false;
+ }
+
+ if (!enough) {
+ emojis = await Emojis.find({
+ where: {
+ name: In(user.emojis),
+ host: user.host
+ },
+ select: ['name', 'host', 'url', 'aliases']
+ });
+ }
+ }
+
const falsy = opts.detail ? false : undefined;
const packed = {
@@ -190,13 +222,7 @@ export class UserRepository extends Repository<User> {
} : undefined) : undefined,
// カスタム絵文字添付
- emojis: user.emojis.length > 0 ? Emojis.find({
- where: {
- name: In(user.emojis),
- host: user.host
- },
- select: ['name', 'host', 'url', 'aliases']
- }) : [],
+ emojis: emojis,
...(opts.detail ? {
url: profile!.url,