From eb9e6d230f41798615e45f00b036e0a48e3ac044 Mon Sep 17 00:00:00 2001 From: syuilo <Syuilotan@yahoo.co.jp> Date: Mon, 21 Mar 2022 01:22:00 +0900 Subject: [PATCH] perf(server): reduce db query --- packages/backend/src/misc/cache.ts | 17 ++++++++++++++--- .../backend/src/models/repositories/user.ts | 12 ++++++++++-- 2 files changed, 24 insertions(+), 5 deletions(-) diff --git a/packages/backend/src/misc/cache.ts b/packages/backend/src/misc/cache.ts index 76835b44b1..e9966b7785 100644 --- a/packages/backend/src/misc/cache.ts +++ b/packages/backend/src/misc/cache.ts @@ -28,11 +28,22 @@ export class Cache<T> { this.cache.delete(key); } - public async fetch(key: string | null, fetcher: () => Promise<T>): Promise<T> { + /** + * ã‚ャッシュãŒã‚ã‚Œã°ãれを返ã—ã€ç„¡ã‘ã‚Œã°fetcherを呼ã³å‡ºã—ã¦çµæžœã‚’ã‚ャッシュ&è¿”ã—ã¾ã™ + * optional: ã‚ャッシュãŒå˜åœ¨ã—ã¦ã‚‚validatorã§falseã‚’è¿”ã™ã¨ã‚ャッシュ無効扱ã„ã«ã—ã¾ã™ + */ + public async fetch(key: string | null, fetcher: () => Promise<T>, validator?: (cachedValue: T) => boolean): Promise<T> { const cachedValue = this.get(key); if (cachedValue !== undefined) { - // Cache HIT - return cachedValue; + if (validator) { + if (validator(cachedValue)) { + // Cache HIT + return cachedValue; + } + } else { + // Cache HIT + return cachedValue; + } } // Cache MISS diff --git a/packages/backend/src/models/repositories/user.ts b/packages/backend/src/models/repositories/user.ts index a909ab3ba6..17b7987a4e 100644 --- a/packages/backend/src/models/repositories/user.ts +++ b/packages/backend/src/models/repositories/user.ts @@ -8,6 +8,10 @@ import { awaitAll, Promiseable } from '@/prelude/await-all.js'; import { populateEmojis } from '@/misc/populate-emojis.js'; import { getAntennas } from '@/misc/antenna-cache.js'; import { USER_ACTIVE_THRESHOLD, USER_ONLINE_THRESHOLD } from '@/const.js'; +import { Cache } from '@/misc/cache.js'; +import { Instance } from '../entities/instance.js'; + +const userInstanceCache = new Cache<Instance | null>(1000 * 60 * 60 * 3); type IsUserDetailed<Detailed extends boolean> = Detailed extends true ? Packed<'UserDetailed'> : Packed<'UserLite'>; type IsMeAndIsUserDetailed<ExpectsMe extends boolean | null, Detailed extends boolean> = @@ -254,8 +258,11 @@ export class UserRepository extends Repository<User> { isModerator: user.isModerator || falsy, isBot: user.isBot || falsy, isCat: user.isCat || falsy, - showTimelineReplies: user.showTimelineReplies || falsy, - instance: user.host ? Instances.findOne({ host: user.host }).then(instance => instance ? { + // TODO: typeorm 3.0ã«ã—ãŸã‚‰ .then(x => x || null) ã¯æ¶ˆã›ã‚‹ + instance: user.host ? userInstanceCache.fetch(user.host, + () => Instances.findOne({ host: user.host }).then(x => x || null), + v => v != null + ).then(instance => instance ? { name: instance.name, softwareName: instance.softwareName, softwareVersion: instance.softwareVersion, @@ -334,6 +341,7 @@ export class UserRepository extends Repository<User> { mutedInstances: profile!.mutedInstances, mutingNotificationTypes: profile!.mutingNotificationTypes, emailNotificationTypes: profile!.emailNotificationTypes, + showTimelineReplies: user.showTimelineReplies || falsy, } : {}), ...(opts.includeSecrets ? { -- GitLab