diff options
| author | syuilo <Syuilotan@yahoo.co.jp> | 2022-03-21 01:22:00 +0900 |
|---|---|---|
| committer | syuilo <Syuilotan@yahoo.co.jp> | 2022-03-21 01:22:00 +0900 |
| commit | eb9e6d230f41798615e45f00b036e0a48e3ac044 (patch) | |
| tree | 1c0e368f02eaa1ca9597d2063ac69dfd8906b733 | |
| parent | perf(server): reduce db query (diff) | |
| download | misskey-eb9e6d230f41798615e45f00b036e0a48e3ac044.tar.gz misskey-eb9e6d230f41798615e45f00b036e0a48e3ac044.tar.bz2 misskey-eb9e6d230f41798615e45f00b036e0a48e3ac044.zip | |
perf(server): reduce db query
| -rw-r--r-- | packages/backend/src/misc/cache.ts | 17 | ||||
| -rw-r--r-- | packages/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 ? { |