perf: reduce query

This commit is contained in:
syuilo 2021-03-18 17:35:47 +09:00
parent e632806349
commit 449ea4b669
1 changed files with 29 additions and 22 deletions

View File

@ -11,33 +11,40 @@ import { perUserReactionsChart } from '../../chart';
import { genId } from '../../../misc/gen-id'; import { genId } from '../../../misc/gen-id';
import { createNotification } from '../../create-notification'; import { createNotification } from '../../create-notification';
import deleteReaction from './delete'; import deleteReaction from './delete';
import { isDuplicateKeyValueError } from '../../../misc/is-duplicate-key-value-error';
export default async (user: User, note: Note, reaction?: string) => { export default async (user: User, note: Note, reaction?: string) => {
reaction = await toDbReaction(reaction, user.host); reaction = await toDbReaction(reaction, user.host);
const exist = await NoteReactions.findOne({ let record;
noteId: note.id,
userId: user.id,
});
if (exist) {
if (exist.reaction !== reaction) {
// 別のリアクションがすでにされていたら置き換える
await deleteReaction(user, note);
} else {
// 同じリアクションがすでにされていたら何もしない
return;
}
}
// Create reaction // Create reaction
const inserted = await NoteReactions.save({ try {
record = await NoteReactions.save({
id: genId(), id: genId(),
createdAt: new Date(), createdAt: new Date(),
noteId: note.id, noteId: note.id,
userId: user.id, userId: user.id,
reaction reaction
}); });
} catch (e) {
if (isDuplicateKeyValueError(e)) {
record = await NoteReactions.findOneOrFail({
noteId: note.id,
userId: user.id,
});
if (record.reaction !== reaction) {
// 別のリアクションがすでにされていたら置き換える
await deleteReaction(user, note);
} else {
// 同じリアクションがすでにされていたら何もしない
return;
}
} else {
throw e;
}
}
// Increment reactions count // Increment reactions count
const sql = `jsonb_set("reactions", '{${reaction}}', (COALESCE("reactions"->>'${reaction}', '0')::int + 1)::text::jsonb)`; const sql = `jsonb_set("reactions", '{${reaction}}', (COALESCE("reactions"->>'${reaction}', '0')::int + 1)::text::jsonb)`;
@ -101,7 +108,7 @@ export default async (user: User, note: Note, reaction?: string) => {
//#region 配信 //#region 配信
if (Users.isLocalUser(user) && !note.localOnly) { if (Users.isLocalUser(user) && !note.localOnly) {
const content = renderActivity(await renderLike(inserted, note)); const content = renderActivity(await renderLike(record, note));
const dm = new DeliverManager(user, content); const dm = new DeliverManager(user, content);
if (note.userHost !== null) { if (note.userHost !== null) {
const reactee = await Users.findOne(note.userId); const reactee = await Users.findOne(note.userId);