From 54e1c7f60ed69d32b3358841ee049d3f143ec3bf Mon Sep 17 00:00:00 2001 From: syuilo Date: Sat, 26 Mar 2022 19:09:57 +0900 Subject: [PATCH] perf(server): use cached user info in getUserFromApId --- packages/backend/src/misc/cache.ts | 27 ++++++++++++++++++- .../src/remote/activitypub/db-resolver.ts | 14 +++++----- .../remote/activitypub/kernel/block/index.ts | 2 +- .../backend/src/services/blocking/delete.ts | 4 +-- .../src/services/following/requests/accept.ts | 4 +-- 5 files changed, 38 insertions(+), 13 deletions(-) diff --git a/packages/backend/src/misc/cache.ts b/packages/backend/src/misc/cache.ts index 9ce5c3e8b..01bbe98a8 100644 --- a/packages/backend/src/misc/cache.ts +++ b/packages/backend/src/misc/cache.ts @@ -48,7 +48,32 @@ export class Cache { // Cache MISS const value = await fetcher(); - this.set(key, value); + return value; + } + + /** + * キャッシュがあればそれを返し、無ければfetcherを呼び出して結果をキャッシュ&返します + * optional: キャッシュが存在してもvalidatorでfalseを返すとキャッシュ無効扱いにします + */ + public async fetchMaybe(key: string | null, fetcher: () => Promise, validator?: (cachedValue: T) => boolean): Promise { + const cachedValue = this.get(key); + if (cachedValue !== undefined) { + if (validator) { + if (validator(cachedValue)) { + // Cache HIT + return cachedValue; + } + } else { + // Cache HIT + return cachedValue; + } + } + + // Cache MISS + const value = await fetcher(); + if (value !== undefined) { + this.set(key, value); + } return value; } } diff --git a/packages/backend/src/remote/activitypub/db-resolver.ts b/packages/backend/src/remote/activitypub/db-resolver.ts index 3d61296bf..ef07966e4 100644 --- a/packages/backend/src/remote/activitypub/db-resolver.ts +++ b/packages/backend/src/remote/activitypub/db-resolver.ts @@ -1,14 +1,14 @@ import escapeRegexp from 'escape-regexp'; import config from '@/config/index.js'; import { Note } from '@/models/entities/note.js'; -import { User, IRemoteUser, CacheableRemoteUser } from '@/models/entities/user.js'; +import { User, IRemoteUser, CacheableRemoteUser, CacheableUser } from '@/models/entities/user.js'; import { UserPublickey } from '@/models/entities/user-publickey.js'; import { MessagingMessage } from '@/models/entities/messaging-message.js'; import { Notes, Users, UserPublickeys, MessagingMessages } from '@/models/index.js'; import { IObject, getApId } from './type.js'; import { resolvePerson } from './models/person.js'; import { Cache } from '@/misc/cache.js'; -import { userByIdCache } from '@/services/user-cache.js'; +import { uriPersonCache, userByIdCache } from '@/services/user-cache.js'; const publicKeyCache = new Cache(Infinity); const publicKeyByUserIdCache = new Cache(Infinity); @@ -59,19 +59,19 @@ export default class DbResolver { /** * AP Person => Misskey User in DB */ - public async getUserFromApId(value: string | IObject): Promise { + public async getUserFromApId(value: string | IObject): Promise { const parsed = this.parseUri(value); if (parsed.id) { - return await Users.findOneBy({ + return await userByIdCache.fetchMaybe(parsed.id, () => Users.findOneBy({ id: parsed.id, - }); + }).then(x => x ?? undefined)) ?? null; } if (parsed.uri) { - return await Users.findOneBy({ + return await uriPersonCache.fetch(parsed.uri, () => Users.findOneBy({ uri: parsed.uri, - }); + })); } return null; diff --git a/packages/backend/src/remote/activitypub/kernel/block/index.ts b/packages/backend/src/remote/activitypub/kernel/block/index.ts index 23cee81d5..5e230ad7b 100644 --- a/packages/backend/src/remote/activitypub/kernel/block/index.ts +++ b/packages/backend/src/remote/activitypub/kernel/block/index.ts @@ -18,6 +18,6 @@ export default async (actor: CacheableRemoteUser, activity: IBlock): Promise