fix: emoji cache
This commit is contained in:
parent
746e2fac41
commit
63c445554a
7 changed files with 58 additions and 22 deletions
|
@ -137,7 +137,7 @@ export const prepared = {
|
|||
select: {
|
||||
byNoteId: `SELECT * FROM reaction WHERE "noteId" IN ?`,
|
||||
byUserId: `SELECT * FROM reaction_by_userid WHERE "userId" IN ?`,
|
||||
byNoteAndUser: `SELECT * FROM reaction WHERE "noteId" = ? AND "userId" = ?`,
|
||||
byNoteAndUser: `SELECT * FROM reaction WHERE "noteId" IN ? AND "userId" IN ?`,
|
||||
byId: `SELECT * FROM reaction WHERE "id" IN ?`,
|
||||
},
|
||||
delete: `DELETE FROM reaction WHERE "noteId" = ? AND "userId" = ?`,
|
||||
|
|
|
@ -36,6 +36,12 @@ export class Cache<T> {
|
|||
await commander.set(_key, _value, "EX", this.ttl);
|
||||
}
|
||||
|
||||
public async exists(...keys: string[]): Promise<boolean> {
|
||||
return (
|
||||
(await redisClient.exists(keys.map((key) => this.prefixedKey(key)))) > 0
|
||||
);
|
||||
}
|
||||
|
||||
public async get(key: string | null, renew = false): Promise<T | undefined> {
|
||||
const _key = this.prefixedKey(key);
|
||||
const cached = await redisClient.getBuffer(_key);
|
||||
|
|
|
@ -152,9 +152,12 @@ export function aggregateNoteEmojis(notes: Note[]) {
|
|||
export async function prefetchEmojis(
|
||||
emojis: { name: string; host: string | null }[],
|
||||
): Promise<void> {
|
||||
const notCachedEmojis = emojis.filter(
|
||||
async (emoji) => !(await EmojiCache.get(`${emoji.name} ${emoji.host}`)),
|
||||
);
|
||||
const notCachedEmojis: { name: string; host: string | null }[] = [];
|
||||
for (const emoji of emojis) {
|
||||
if (!(await EmojiCache.exists(`${emoji.name} ${emoji.host}`))) {
|
||||
notCachedEmojis.push(emoji);
|
||||
}
|
||||
}
|
||||
const emojisQuery: any[] = [];
|
||||
const hosts = new Set(notCachedEmojis.map((e) => e.host));
|
||||
for (const host of hosts) {
|
||||
|
|
|
@ -28,10 +28,11 @@ import {
|
|||
import { db } from "@/db/postgre.js";
|
||||
import { IdentifiableError } from "@/misc/identifiable-error.js";
|
||||
import {
|
||||
ScyllaNote,
|
||||
type ScyllaNote,
|
||||
parseScyllaNote,
|
||||
prepared,
|
||||
scyllaClient,
|
||||
parseScyllaReaction,
|
||||
} from "@/db/scylla.js";
|
||||
import { LocalFollowingsCache } from "@/misc/cache.js";
|
||||
import { userByIdCache } from "@/services/user-cache.js";
|
||||
|
@ -91,10 +92,22 @@ async function populateMyReaction(
|
|||
// 実装上抜けがあるだけかもしれないので、「ヒントに含まれてなかったら(=undefinedなら)return」のようにはしない
|
||||
}
|
||||
|
||||
const reaction = await NoteReactions.findOneBy({
|
||||
userId: meId,
|
||||
noteId: note.id,
|
||||
});
|
||||
let reaction: NoteReaction | null = null;
|
||||
if (scyllaClient) {
|
||||
const result = await scyllaClient.execute(
|
||||
prepared.reaction.select.byNoteAndUser,
|
||||
[[note.id], [meId]],
|
||||
{ prepare: true },
|
||||
);
|
||||
if (result.rowLength > 0) {
|
||||
reaction = parseScyllaReaction(result.first());
|
||||
}
|
||||
} else {
|
||||
reaction = await NoteReactions.findOneBy({
|
||||
userId: meId,
|
||||
noteId: note.id,
|
||||
});
|
||||
}
|
||||
|
||||
if (reaction) {
|
||||
return convertLegacyReaction(reaction.reaction);
|
||||
|
@ -358,10 +371,20 @@ export const NoteRepository = db.getRepository(Note).extend({
|
|||
.filter((n) => !!n.renoteId)
|
||||
.map((n) => n.renoteId) as string[];
|
||||
const targets = [...notes.map((n) => n.id), ...renoteIds];
|
||||
const myReactions = await NoteReactions.findBy({
|
||||
userId: meId,
|
||||
noteId: In(targets),
|
||||
});
|
||||
let myReactions: NoteReaction[] = [];
|
||||
if (scyllaClient) {
|
||||
const result = await scyllaClient.execute(
|
||||
prepared.reaction.select.byNoteAndUser,
|
||||
[targets, [meId]],
|
||||
{ prepare: true },
|
||||
);
|
||||
myReactions = result.rows.map(parseScyllaReaction);
|
||||
} else {
|
||||
myReactions = await NoteReactions.findBy({
|
||||
userId: meId,
|
||||
noteId: In(targets),
|
||||
});
|
||||
}
|
||||
|
||||
for (const target of targets) {
|
||||
myReactionsMap.set(
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
import type { FindOptionsWhere } from "typeorm";
|
||||
import { DeepPartial } from "typeorm";
|
||||
import { NoteReactions } from "@/models/index.js";
|
||||
import type { NoteReaction } from "@/models/entities/note-reaction.js";
|
||||
import define from "../../define.js";
|
||||
|
|
|
@ -2,6 +2,7 @@ import { Notes } from "@/models/index.js";
|
|||
import define from "../../define.js";
|
||||
import { getNote } from "../../common/getters.js";
|
||||
import { ApiError } from "../../error.js";
|
||||
import { scyllaClient } from "@/db/scylla.js";
|
||||
|
||||
export const meta = {
|
||||
tags: ["notes"],
|
||||
|
@ -44,6 +45,7 @@ export default define(meta, paramDef, async (ps, user) => {
|
|||
return await Notes.pack(note, user, {
|
||||
// FIXME: packing with detail may throw an error if the reply or renote is not visible (#8774)
|
||||
detail: true,
|
||||
scyllaNote: !!scyllaClient
|
||||
}).catch((err) => {
|
||||
if (err.id === "9725d0ce-ba28-4dde-95a7-2cbb2c15de24")
|
||||
throw new ApiError(meta.errors.noSuchNote);
|
||||
|
|
|
@ -22,7 +22,7 @@ import { isDuplicateKeyValueError } from "@/misc/is-duplicate-key-value-error.js
|
|||
import type { NoteReaction } from "@/models/entities/note-reaction.js";
|
||||
import { IdentifiableError } from "@/misc/identifiable-error.js";
|
||||
import { prepared, scyllaClient } from "@/db/scylla.js";
|
||||
import { populateEmojis } from "@/misc/populate-emojis.js";
|
||||
import { EmojiCache } from "@/misc/populate-emojis.js";
|
||||
|
||||
export default async (
|
||||
user: { id: User["id"]; host: User["host"] },
|
||||
|
@ -137,13 +137,16 @@ export default async (
|
|||
// カスタム絵文字リアクションだったら絵文字情報も送る
|
||||
const decodedReaction = decodeReaction(_reaction);
|
||||
|
||||
const emoji = await Emojis.findOne({
|
||||
where: {
|
||||
name: decodedReaction.name,
|
||||
host: decodedReaction.host ?? IsNull(),
|
||||
},
|
||||
select: ["name", "host", "originalUrl", "publicUrl"],
|
||||
});
|
||||
const emoji = await EmojiCache.fetch(
|
||||
`${decodedReaction.name} ${decodedReaction.host}`,
|
||||
() =>
|
||||
Emojis.findOne({
|
||||
where: {
|
||||
name: decodedReaction.name,
|
||||
host: decodedReaction.host ?? IsNull(),
|
||||
},
|
||||
}),
|
||||
);
|
||||
|
||||
publishNoteStream(note.id, "reacted", {
|
||||
reaction: decodedReaction.reaction,
|
||||
|
|
Loading…
Reference in a new issue