diff --git a/packages/backend/src/misc/cache.ts b/packages/backend/src/misc/cache.ts index 9ce5c3e8b05cd1441f5926efded2ece92737c18a..01bbe98a8503f723e56606645c4a59e318a06304 100644 --- a/packages/backend/src/misc/cache.ts +++ b/packages/backend/src/misc/cache.ts @@ -48,7 +48,32 @@ export class Cache<T> { // Cache MISS const value = await fetcher(); - this.set(key, value); + return value; + } + + /** + * ã‚ャッシュãŒã‚ã‚Œã°ãれを返ã—ã€ç„¡ã‘ã‚Œã°fetcherを呼ã³å‡ºã—ã¦çµæžœã‚’ã‚ャッシュ&è¿”ã—ã¾ã™ + * optional: ã‚ャッシュãŒå˜åœ¨ã—ã¦ã‚‚validatorã§falseã‚’è¿”ã™ã¨ã‚ャッシュ無効扱ã„ã«ã—ã¾ã™ + */ + public async fetchMaybe(key: string | null, fetcher: () => Promise<T | undefined>, validator?: (cachedValue: T) => boolean): Promise<T | undefined> { + 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 3d61296bf5ae740ca4a58c2ce8f1af0bd3c2d3fb..ef07966e42820964b297b050c05a72fcc254ab91 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<UserPublickey | null>(Infinity); const publicKeyByUserIdCache = new Cache<UserPublickey | null>(Infinity); @@ -59,19 +59,19 @@ export default class DbResolver { /** * AP Person => Misskey User in DB */ - public async getUserFromApId(value: string | IObject): Promise<User | null> { + public async getUserFromApId(value: string | IObject): Promise<CacheableUser | null> { 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 23cee81d5bcb17e248d55dc05f0a7d0fc421b68c..5e230ad7b7bedb27bc2b993989263443a8907295 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<str return `skip: ブãƒãƒƒã‚¯ã—よã†ã¨ã—ã¦ã„るユーザーã¯ãƒãƒ¼ã‚«ãƒ«ãƒ¦ãƒ¼ã‚¶ãƒ¼ã§ã¯ã‚ã‚Šã¾ã›ã‚“`; } - await block(await Users.findOneByOrFail({ id: actor.id }), blockee); + await block(await Users.findOneByOrFail({ id: actor.id }), await Users.findOneByOrFail({ id: blockee.id })); return `ok`; }; diff --git a/packages/backend/src/services/blocking/delete.ts b/packages/backend/src/services/blocking/delete.ts index f3a509bb02c825398030b6c8e5a00893fce3c20d..d7b5ddd5ff76d5c492047c86af11aa795bdee54b 100644 --- a/packages/backend/src/services/blocking/delete.ts +++ b/packages/backend/src/services/blocking/delete.ts @@ -3,12 +3,12 @@ import renderBlock from '@/remote/activitypub/renderer/block.js'; import renderUndo from '@/remote/activitypub/renderer/undo.js'; import { deliver } from '@/queue/index.js'; import Logger from '../logger.js'; -import { User } from '@/models/entities/user.js'; +import { CacheableUser, User } from '@/models/entities/user.js'; import { Blockings, Users } from '@/models/index.js'; const logger = new Logger('blocking/delete'); -export default async function(blocker: User, blockee: User) { +export default async function(blocker: CacheableUser, blockee: CacheableUser) { const blocking = await Blockings.findOneBy({ blockerId: blocker.id, blockeeId: blockee.id, diff --git a/packages/backend/src/services/following/requests/accept.ts b/packages/backend/src/services/following/requests/accept.ts index fc9d4062e37f50a2ead828aac72d34a4a5a442ee..20829f70c7f30b5a209f471140377c8dffc2b658 100644 --- a/packages/backend/src/services/following/requests/accept.ts +++ b/packages/backend/src/services/following/requests/accept.ts @@ -4,11 +4,11 @@ import renderAccept from '@/remote/activitypub/renderer/accept.js'; import { deliver } from '@/queue/index.js'; import { publishMainStream } from '@/services/stream.js'; import { insertFollowingDoc } from '../create.js'; -import { User, ILocalUser } from '@/models/entities/user.js'; +import { User, ILocalUser, CacheableUser } from '@/models/entities/user.js'; import { FollowRequests, Users } from '@/models/index.js'; import { IdentifiableError } from '@/misc/identifiable-error.js'; -export default async function(followee: { id: User['id']; host: User['host']; uri: User['host']; inbox: User['inbox']; sharedInbox: User['sharedInbox']; }, follower: User) { +export default async function(followee: { id: User['id']; host: User['host']; uri: User['host']; inbox: User['inbox']; sharedInbox: User['sharedInbox']; }, follower: CacheableUser) { const request = await FollowRequests.findOneBy({ followeeId: followee.id, followerId: follower.id,