perf: pass cached values as params

This commit is contained in:
Namekuji 2023-08-07 06:52:03 -04:00
parent 090bb9a2c3
commit 5475383d94
No known key found for this signature in database
GPG key ID: 1D62332C07FBA532
2 changed files with 90 additions and 33 deletions

View file

@ -428,13 +428,20 @@ export async function filterReply(
export async function filterMutedUser( export async function filterMutedUser(
notes: ScyllaNote[], notes: ScyllaNote[],
user: { id: User["id"] }, user: { id: User["id"] },
mutedIds?: User["id"][],
exclude?: User, exclude?: User,
): Promise<ScyllaNote[]> { ): Promise<ScyllaNote[]> {
const userCache = await UserMutingsCache.init(user.id); let ids: User["id"][];
let mutedUserIds = await userCache.getAll();
if (mutedIds) {
ids = mutedIds;
} else {
const userCache = await UserMutingsCache.init(user.id);
ids = await userCache.getAll();
}
if (exclude) { if (exclude) {
mutedUserIds = mutedUserIds.filter((id) => id !== exclude.id); ids = ids.filter((id) => id !== exclude.id);
} }
const instanceCache = await InstanceMutingsCache.init(user.id); const instanceCache = await InstanceMutingsCache.init(user.id);
@ -442,9 +449,9 @@ export async function filterMutedUser(
return notes.filter( return notes.filter(
(note) => (note) =>
!mutedUserIds.includes(note.userId) && !ids.includes(note.userId) &&
!(note.replyUserId && mutedUserIds.includes(note.replyUserId)) && !(note.replyUserId && ids.includes(note.replyUserId)) &&
!(note.renoteUserId && mutedUserIds.includes(note.renoteUserId)) && !(note.renoteUserId && ids.includes(note.renoteUserId)) &&
!(note.userHost && mutedInstances.includes(note.userHost)) && !(note.userHost && mutedInstances.includes(note.userHost)) &&
!(note.replyUserHost && mutedInstances.includes(note.replyUserHost)) && !(note.replyUserHost && mutedInstances.includes(note.replyUserHost)) &&
!(note.renoteUserHost && mutedInstances.includes(note.renoteUserHost)), !(note.renoteUserHost && mutedInstances.includes(note.renoteUserHost)),
@ -454,44 +461,65 @@ export async function filterMutedUser(
export async function filterMutedNote( export async function filterMutedNote(
notes: ScyllaNote[], notes: ScyllaNote[],
user: { id: User["id"] }, user: { id: User["id"] },
mutedWords?: string[][],
): Promise<ScyllaNote[]> { ): Promise<ScyllaNote[]> {
const mutedWords = await userWordMuteCache.fetchMaybe(user.id, () => let words = mutedWords;
UserProfiles.findOne({
select: ["mutedWords"],
where: { userId: user.id },
}).then((profile) => profile?.mutedWords),
);
if (!mutedWords) { if (!words) {
return notes; words = await userWordMuteCache.fetchMaybe(user.id, () =>
UserProfiles.findOne({
select: ["mutedWords"],
where: { userId: user.id },
}).then((profile) => profile?.mutedWords),
);
} }
return notes.filter((note) => !getWordHardMute(note, user, mutedWords)); if (words && words.length > 0) {
return notes.filter(
(note) => !getWordHardMute(note, user, words as string[][]),
);
}
return notes;
} }
export async function filterBlockedUser( export async function filterBlockedUser(
notes: ScyllaNote[], notes: ScyllaNote[],
user: { id: User["id"] }, user: { id: User["id"] },
blockerIds?: User["id"][],
): Promise<ScyllaNote[]> { ): Promise<ScyllaNote[]> {
const cache = await UserBlockedCache.init(user.id); let ids: User["id"][];
const blockerIds = await cache.getAll();
if (blockerIds) {
ids = blockerIds;
} else {
const cache = await UserBlockedCache.init(user.id);
ids = await cache.getAll();
}
return notes.filter( return notes.filter(
(note) => (note) =>
!blockerIds.includes(note.userId) && !ids.includes(note.userId) &&
!(note.replyUserId && blockerIds.includes(note.replyUserId)) && !(note.replyUserId && ids.includes(note.replyUserId)) &&
!(note.renoteUserId && blockerIds.includes(note.renoteUserId)), !(note.renoteUserId && ids.includes(note.renoteUserId)),
); );
} }
export async function filterMutedRenotes( export async function filterMutedRenotes(
notes: ScyllaNote[], notes: ScyllaNote[],
user: { id: User["id"] }, user: { id: User["id"] },
muteeIds?: User["id"][],
): Promise<ScyllaNote[]> { ): Promise<ScyllaNote[]> {
const cache = await RenoteMutingsCache.init(user.id); let ids: User["id"][];
const muteeIds = await cache.getAll();
if (muteeIds) {
ids = muteeIds;
} else {
const cache = await RenoteMutingsCache.init(user.id);
ids = await cache.getAll();
}
return notes.filter( return notes.filter(
(note) => note.text || !note.renoteId || !muteeIds.includes(note.userId), (note) => note.text || !note.renoteId || !ids.includes(note.userId),
); );
} }

View file

@ -1,5 +1,5 @@
import { Brackets } from "typeorm"; import { Brackets } from "typeorm";
import { Notes, Followings } from "@/models/index.js"; import { Notes, Followings, UserProfiles } from "@/models/index.js";
import { activeUsersChart } from "@/services/chart/index.js"; import { activeUsersChart } from "@/services/chart/index.js";
import define from "../../define.js"; import define from "../../define.js";
import { makePaginationQuery } from "../../common/make-pagination-query.js"; import { makePaginationQuery } from "../../common/make-pagination-query.js";
@ -23,7 +23,7 @@ import {
filterBlockedUser, filterBlockedUser,
filterMutedRenotes, filterMutedRenotes,
} from "@/db/scylla.js"; } from "@/db/scylla.js";
import { ChannelFollowingsCache, LocalFollowingsCache } from "@/misc/cache.js"; import { ChannelFollowingsCache, LocalFollowingsCache, RenoteMutingsCache, UserBlockedCache, UserMutingsCache, userWordMuteCache } from "@/misc/cache.js";
export const meta = { export const meta = {
tags: ["notes"], tags: ["notes"],
@ -79,21 +79,54 @@ export const paramDef = {
export default define(meta, paramDef, async (ps, user) => { export default define(meta, paramDef, async (ps, user) => {
const followingsCache = await LocalFollowingsCache.init(user.id); const followingsCache = await LocalFollowingsCache.init(user.id);
process.nextTick(() => {
activeUsersChart.read(user);
});
if (scyllaClient) { if (scyllaClient) {
const channelCache = await ChannelFollowingsCache.init(user.id); const channelCache = await ChannelFollowingsCache.init(user.id);
const followingChannelIds = await channelCache.getAll(); const followingChannelIds = await channelCache.getAll();
const followingUserIds = await followingsCache.getAll(); const followingUserIds = await followingsCache.getAll();
const validUserIds = [user.id].concat(followingUserIds); const validUserIds = [user.id].concat(followingUserIds);
const userMutingsCache = await UserMutingsCache.init(user.id);
const mutedUserIds = await userMutingsCache.getAll();
const mutedWords = await userWordMuteCache.fetchMaybe(user.id, () =>
UserProfiles.findOne({
select: ["mutedWords"],
where: { userId: user.id },
}).then((profile) => profile?.mutedWords),
);
const blockedCache = await UserBlockedCache.init(user.id);
const blockerIds = await blockedCache.getAll();
const renoteMutingsCache = await RenoteMutingsCache.init(user.id);
const renoteMutedIds = await renoteMutingsCache.getAll();
const optFilter = (n: ScyllaNote) =>
!n.renoteId || !!n.text || n.files.length > 0 || n.hasPoll;
const filter = async (notes: ScyllaNote[]) => { const filter = async (notes: ScyllaNote[]) => {
let filtered = notes.filter((n) => validUserIds.includes(n.userId)); let filtered = notes.filter((n) => validUserIds.includes(n.userId));
filtered = await filterChannel(filtered, user, followingChannelIds); filtered = await filterChannel(filtered, user, followingChannelIds);
filtered = await filterReply(filtered, ps.withReplies, user); filtered = await filterReply(filtered, ps.withReplies, user);
filtered = await filterVisibility(filtered, user, followingUserIds); filtered = await filterVisibility(filtered, user, followingUserIds);
filtered = await filterMutedUser(filtered, user); filtered = await filterMutedUser(filtered, user, mutedUserIds);
filtered = await filterMutedNote(filtered, user); filtered = await filterMutedNote(filtered, user, mutedWords ?? []);
filtered = await filterBlockedUser(filtered, user); filtered = await filterBlockedUser(filtered, user, blockerIds);
filtered = await filterMutedRenotes(filtered, user); filtered = await filterMutedRenotes(filtered, user, renoteMutedIds);
if (!ps.includeMyRenotes) {
filtered = filtered.filter((n) => n.userId !== user.id || optFilter(n));
}
if (!ps.includeRenotedMyNotes) {
filtered = filtered.filter(
(n) => n.renoteUserId !== user.id || optFilter(n),
);
}
if (!ps.includeLocalRenotes) {
filtered = filtered.filter((n) => n.renoteUserHost || optFilter(n));
}
if (ps.withFiles) {
filtered = filtered.filter((n) => n.files.length > 0);
}
filtered = filtered.filter((n) => n.visibility !== "hidden");
return filtered; return filtered;
}; };
@ -183,10 +216,6 @@ export default define(meta, paramDef, async (ps, user) => {
query.andWhere("note.visibility != 'hidden'"); query.andWhere("note.visibility != 'hidden'");
//#endregion //#endregion
process.nextTick(() => {
activeUsersChart.read(user);
});
// We fetch more than requested because some may be filtered out, and if there's less than // We fetch more than requested because some may be filtered out, and if there's less than
// requested, the pagination stops. // requested, the pagination stops.
const found = []; const found = [];