From 28647de1968995e294e2ade365a29685df91eae6 Mon Sep 17 00:00:00 2001 From: syuilo Date: Wed, 5 Apr 2023 12:10:40 +0900 Subject: [PATCH] enhance(backend): improve userkeypair cache --- packages/backend/src/core/CoreModule.ts | 12 +++++------ .../src/core/UserKeypairStoreService.ts | 20 ++++++++++++++----- .../src/core/activitypub/ApRendererService.ts | 8 ++++---- .../src/core/activitypub/ApRequestService.ts | 8 ++++---- .../src/server/ActivityPubServerService.ts | 6 +++--- 5 files changed, 32 insertions(+), 22 deletions(-) diff --git a/packages/backend/src/core/CoreModule.ts b/packages/backend/src/core/CoreModule.ts index 5c867e6cf..ea6e22961 100644 --- a/packages/backend/src/core/CoreModule.ts +++ b/packages/backend/src/core/CoreModule.ts @@ -40,7 +40,7 @@ import { TwoFactorAuthenticationService } from './TwoFactorAuthenticationService import { UserBlockingService } from './UserBlockingService.js'; import { CacheService } from './CacheService.js'; import { UserFollowingService } from './UserFollowingService.js'; -import { UserKeypairStoreService } from './UserKeypairStoreService.js'; +import { UserKeypairService } from './UserKeypairService.js'; import { UserListService } from './UserListService.js'; import { UserMutingService } from './UserMutingService.js'; import { UserSuspendService } from './UserSuspendService.js'; @@ -161,7 +161,7 @@ const $TwoFactorAuthenticationService: Provider = { provide: 'TwoFactorAuthentic const $UserBlockingService: Provider = { provide: 'UserBlockingService', useExisting: UserBlockingService }; const $CacheService: Provider = { provide: 'CacheService', useExisting: CacheService }; const $UserFollowingService: Provider = { provide: 'UserFollowingService', useExisting: UserFollowingService }; -const $UserKeypairStoreService: Provider = { provide: 'UserKeypairStoreService', useExisting: UserKeypairStoreService }; +const $UserKeypairService: Provider = { provide: 'UserKeypairService', useExisting: UserKeypairService }; const $UserListService: Provider = { provide: 'UserListService', useExisting: UserListService }; const $UserMutingService: Provider = { provide: 'UserMutingService', useExisting: UserMutingService }; const $UserSuspendService: Provider = { provide: 'UserSuspendService', useExisting: UserSuspendService }; @@ -284,7 +284,7 @@ const $ApQuestionService: Provider = { provide: 'ApQuestionService', useExisting UserBlockingService, CacheService, UserFollowingService, - UserKeypairStoreService, + UserKeypairService, UserListService, UserMutingService, UserSuspendService, @@ -401,7 +401,7 @@ const $ApQuestionService: Provider = { provide: 'ApQuestionService', useExisting $UserBlockingService, $CacheService, $UserFollowingService, - $UserKeypairStoreService, + $UserKeypairService, $UserListService, $UserMutingService, $UserSuspendService, @@ -519,7 +519,7 @@ const $ApQuestionService: Provider = { provide: 'ApQuestionService', useExisting UserBlockingService, CacheService, UserFollowingService, - UserKeypairStoreService, + UserKeypairService, UserListService, UserMutingService, UserSuspendService, @@ -635,7 +635,7 @@ const $ApQuestionService: Provider = { provide: 'ApQuestionService', useExisting $UserBlockingService, $CacheService, $UserFollowingService, - $UserKeypairStoreService, + $UserKeypairService, $UserListService, $UserMutingService, $UserSuspendService, diff --git a/packages/backend/src/core/UserKeypairStoreService.ts b/packages/backend/src/core/UserKeypairStoreService.ts index 872a0335e..22a9fb2b8 100644 --- a/packages/backend/src/core/UserKeypairStoreService.ts +++ b/packages/backend/src/core/UserKeypairStoreService.ts @@ -1,24 +1,34 @@ import { Inject, Injectable } from '@nestjs/common'; +import Redis from 'ioredis'; import type { User } from '@/models/entities/User.js'; import type { UserKeypairsRepository } from '@/models/index.js'; -import { MemoryKVCache } from '@/misc/cache.js'; +import { RedisKVCache } from '@/misc/cache.js'; import type { UserKeypair } from '@/models/entities/UserKeypair.js'; import { DI } from '@/di-symbols.js'; import { bindThis } from '@/decorators.js'; @Injectable() -export class UserKeypairStoreService { - private cache: MemoryKVCache; +export class UserKeypairService { + private cache: RedisKVCache; constructor( + @Inject(DI.redis) + private redisClient: Redis.Redis, + @Inject(DI.userKeypairsRepository) private userKeypairsRepository: UserKeypairsRepository, ) { - this.cache = new MemoryKVCache(Infinity); + this.cache = new RedisKVCache(this.redisClient, 'userKeypair', { + lifetime: 1000 * 60 * 60 * 24, // 24h + memoryCacheLifetime: Infinity, + fetcher: (key) => this.userKeypairsRepository.findOneByOrFail({ userId: key }), + toRedisConverter: (value) => JSON.stringify(value), + fromRedisConverter: (value) => JSON.parse(value), + }); } @bindThis public async getUserKeypair(userId: User['id']): Promise { - return await this.cache.fetch(userId, () => this.userKeypairsRepository.findOneByOrFail({ userId: userId })); + return await this.cache.fetch(userId); } } diff --git a/packages/backend/src/core/activitypub/ApRendererService.ts b/packages/backend/src/core/activitypub/ApRendererService.ts index 0d03e3d90..15512c8f4 100644 --- a/packages/backend/src/core/activitypub/ApRendererService.ts +++ b/packages/backend/src/core/activitypub/ApRendererService.ts @@ -14,7 +14,7 @@ import type { NoteReaction } from '@/models/entities/NoteReaction.js'; import type { Emoji } from '@/models/entities/Emoji.js'; import type { Poll } from '@/models/entities/Poll.js'; import type { PollVote } from '@/models/entities/PollVote.js'; -import { UserKeypairStoreService } from '@/core/UserKeypairStoreService.js'; +import { UserKeypairService } from '@/core/UserKeypairService.js'; import { MfmService } from '@/core/MfmService.js'; import { UserEntityService } from '@/core/entities/UserEntityService.js'; import { DriveFileEntityService } from '@/core/entities/DriveFileEntityService.js'; @@ -53,7 +53,7 @@ export class ApRendererService { private userEntityService: UserEntityService, private driveFileEntityService: DriveFileEntityService, private ldSignatureService: LdSignatureService, - private userKeypairStoreService: UserKeypairStoreService, + private userKeypairService: UserKeypairService, private apMfmService: ApMfmService, private mfmService: MfmService, ) { @@ -473,7 +473,7 @@ export class ApRendererService { ...hashtagTags, ]; - const keypair = await this.userKeypairStoreService.getUserKeypair(user.id); + const keypair = await this.userKeypairService.getUserKeypair(user.id); const person = { type: isSystem ? 'Application' : user.isBot ? 'Service' : 'Person', @@ -640,7 +640,7 @@ export class ApRendererService { @bindThis public async attachLdSignature(activity: any, user: { id: User['id']; host: null; }): Promise { - const keypair = await this.userKeypairStoreService.getUserKeypair(user.id); + const keypair = await this.userKeypairService.getUserKeypair(user.id); const ldSignature = this.ldSignatureService.use(); ldSignature.debug = false; diff --git a/packages/backend/src/core/activitypub/ApRequestService.ts b/packages/backend/src/core/activitypub/ApRequestService.ts index 71fbc2947..5005612ab 100644 --- a/packages/backend/src/core/activitypub/ApRequestService.ts +++ b/packages/backend/src/core/activitypub/ApRequestService.ts @@ -4,7 +4,7 @@ import { Inject, Injectable } from '@nestjs/common'; import { DI } from '@/di-symbols.js'; import type { Config } from '@/config.js'; import type { User } from '@/models/entities/User.js'; -import { UserKeypairStoreService } from '@/core/UserKeypairStoreService.js'; +import { UserKeypairService } from '@/core/UserKeypairService.js'; import { HttpRequestService } from '@/core/HttpRequestService.js'; import { LoggerService } from '@/core/LoggerService.js'; import { bindThis } from '@/decorators.js'; @@ -131,7 +131,7 @@ export class ApRequestService { @Inject(DI.config) private config: Config, - private userKeypairStoreService: UserKeypairStoreService, + private userKeypairService: UserKeypairService, private httpRequestService: HttpRequestService, private loggerService: LoggerService, ) { @@ -143,7 +143,7 @@ export class ApRequestService { public async signedPost(user: { id: User['id'] }, url: string, object: any) { const body = JSON.stringify(object); - const keypair = await this.userKeypairStoreService.getUserKeypair(user.id); + const keypair = await this.userKeypairService.getUserKeypair(user.id); const req = ApRequestCreator.createSignedPost({ key: { @@ -170,7 +170,7 @@ export class ApRequestService { */ @bindThis public async signedGet(url: string, user: { id: User['id'] }) { - const keypair = await this.userKeypairStoreService.getUserKeypair(user.id); + const keypair = await this.userKeypairService.getUserKeypair(user.id); const req = ApRequestCreator.createSignedGet({ key: { diff --git a/packages/backend/src/server/ActivityPubServerService.ts b/packages/backend/src/server/ActivityPubServerService.ts index da8d0114e..579962207 100644 --- a/packages/backend/src/server/ActivityPubServerService.ts +++ b/packages/backend/src/server/ActivityPubServerService.ts @@ -12,7 +12,7 @@ import type { Config } from '@/config.js'; import { ApRendererService } from '@/core/activitypub/ApRendererService.js'; import { QueueService } from '@/core/QueueService.js'; import type { LocalUser, User } from '@/models/entities/User.js'; -import { UserKeypairStoreService } from '@/core/UserKeypairStoreService.js'; +import { UserKeypairService } from '@/core/UserKeypairService.js'; import type { Following } from '@/models/entities/Following.js'; import { countIf } from '@/misc/prelude/array.js'; import type { Note } from '@/models/entities/Note.js'; @@ -58,7 +58,7 @@ export class ActivityPubServerService { private userEntityService: UserEntityService, private apRendererService: ApRendererService, private queueService: QueueService, - private userKeypairStoreService: UserKeypairStoreService, + private userKeypairService: UserKeypairService, private queryService: QueryService, ) { //this.createServer = this.createServer.bind(this); @@ -540,7 +540,7 @@ export class ActivityPubServerService { return; } - const keypair = await this.userKeypairStoreService.getUserKeypair(user.id); + const keypair = await this.userKeypairService.getUserKeypair(user.id); if (this.userEntityService.isLocalUser(user)) { reply.header('Cache-Control', 'public, max-age=180');