diff --git a/packages/backend/src/misc/populate-emojis.ts b/packages/backend/src/misc/populate-emojis.ts index c77fe31bf..9a1246d4d 100644 --- a/packages/backend/src/misc/populate-emojis.ts +++ b/packages/backend/src/misc/populate-emojis.ts @@ -11,7 +11,7 @@ import { decodeReaction } from './reaction-lib.js'; const cache = new Cache(1000 * 60 * 60 * 12); /** - * 添付用絵文字情報 + * Information needed to attach in ActivityPub */ type PopulatedEmoji = { name: string; @@ -36,17 +36,16 @@ function parseEmojiStr(emojiName: string, noteUserHost: string | null) { const name = match[1]; - // ホスト正規化 const host = toPunyNullable(normalizeHost(match[2], noteUserHost)); return { name, host }; } /** - * 添付用絵文字情報を解決する - * @param emojiName ノートやユーザープロフィールに添付された、またはリアクションのカスタム絵文字名 (:は含めない, リアクションでローカルホストの場合は@.を付ける (これはdecodeReactionで可能)) - * @param noteUserHost ノートやユーザープロフィールの所有者のホスト - * @returns 絵文字情報, nullは未マッチを意味する + * Resolve emoji information from ActivityPub attachment. + * @param emojiName custom emoji names attached to notes, user profiles or in rections. Colons should not be included. Localhost is denote by @. (see also `decodeReaction`) + * @param noteUserHost host that the content is from, to default to + * @returns emoji information. `null` means not found. */ export async function populateEmoji(emojiName: string, noteUserHost: string | null): Promise { const { name, host } = parseEmojiStr(emojiName, noteUserHost); @@ -72,7 +71,7 @@ export async function populateEmoji(emojiName: string, noteUserHost: string | nu } /** - * 複数の添付用絵文字情報を解決する (キャシュ付き, 存在しないものは結果から除外される) + * Retrieve list of emojis from the cache. Uncached emoji are dropped. */ export async function populateEmojis(emojiNames: string[], noteUserHost: string | null): Promise { const emojis = await Promise.all(emojiNames.map(x => populateEmoji(x, noteUserHost))); @@ -103,11 +102,17 @@ export function aggregateNoteEmojis(notes: Note[]) { } /** - * 与えられた絵文字のリストをデータベースから取得し、キャッシュに追加します + * Query list of emojis in bulk and add them to the cache. */ export async function prefetchEmojis(emojis: { name: string; host: string | null; }[]): Promise { const notCachedEmojis = emojis.filter(emoji => cache.get(`${emoji.name} ${emoji.host}`) == null); + + // check if there even are any uncached emoji to handle + if (notCachedEmojis.length === 0) return; + + // query all uncached emoji const emojisQuery: any[] = []; + // group by hosts to try to reduce query size const hosts = new Set(notCachedEmojis.map(e => e.host)); for (const host of hosts) { emojisQuery.push({ @@ -115,11 +120,14 @@ export async function prefetchEmojis(emojis: { name: string; host: string | null host: host ?? IsNull(), }); } - const _emojis = emojisQuery.length > 0 ? await Emojis.find({ + + await Emojis.find({ where: emojisQuery, select: ['name', 'host', 'originalUrl', 'publicUrl'], - }) : []; - for (const emoji of _emojis) { - cache.set(`${emoji.name} ${emoji.host}`, emoji); - } + }).then(emojis => { + // store all emojis into the cache + emojis.forEach(emoji => { + cache.set(`${emoji.name} ${emoji.host}`, emoji); + }); + }); }