enhance(backend): improve userkeypair cache

This commit is contained in:
syuilo 2023-04-05 12:10:40 +09:00
parent cf6a302f8f
commit 28647de196
5 changed files with 32 additions and 22 deletions

View file

@ -40,7 +40,7 @@ import { TwoFactorAuthenticationService } from './TwoFactorAuthenticationService
import { UserBlockingService } from './UserBlockingService.js'; import { UserBlockingService } from './UserBlockingService.js';
import { CacheService } from './CacheService.js'; import { CacheService } from './CacheService.js';
import { UserFollowingService } from './UserFollowingService.js'; import { UserFollowingService } from './UserFollowingService.js';
import { UserKeypairStoreService } from './UserKeypairStoreService.js'; import { UserKeypairService } from './UserKeypairService.js';
import { UserListService } from './UserListService.js'; import { UserListService } from './UserListService.js';
import { UserMutingService } from './UserMutingService.js'; import { UserMutingService } from './UserMutingService.js';
import { UserSuspendService } from './UserSuspendService.js'; import { UserSuspendService } from './UserSuspendService.js';
@ -161,7 +161,7 @@ const $TwoFactorAuthenticationService: Provider = { provide: 'TwoFactorAuthentic
const $UserBlockingService: Provider = { provide: 'UserBlockingService', useExisting: UserBlockingService }; const $UserBlockingService: Provider = { provide: 'UserBlockingService', useExisting: UserBlockingService };
const $CacheService: Provider = { provide: 'CacheService', useExisting: CacheService }; const $CacheService: Provider = { provide: 'CacheService', useExisting: CacheService };
const $UserFollowingService: Provider = { provide: 'UserFollowingService', useExisting: UserFollowingService }; 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 $UserListService: Provider = { provide: 'UserListService', useExisting: UserListService };
const $UserMutingService: Provider = { provide: 'UserMutingService', useExisting: UserMutingService }; const $UserMutingService: Provider = { provide: 'UserMutingService', useExisting: UserMutingService };
const $UserSuspendService: Provider = { provide: 'UserSuspendService', useExisting: UserSuspendService }; const $UserSuspendService: Provider = { provide: 'UserSuspendService', useExisting: UserSuspendService };
@ -284,7 +284,7 @@ const $ApQuestionService: Provider = { provide: 'ApQuestionService', useExisting
UserBlockingService, UserBlockingService,
CacheService, CacheService,
UserFollowingService, UserFollowingService,
UserKeypairStoreService, UserKeypairService,
UserListService, UserListService,
UserMutingService, UserMutingService,
UserSuspendService, UserSuspendService,
@ -401,7 +401,7 @@ const $ApQuestionService: Provider = { provide: 'ApQuestionService', useExisting
$UserBlockingService, $UserBlockingService,
$CacheService, $CacheService,
$UserFollowingService, $UserFollowingService,
$UserKeypairStoreService, $UserKeypairService,
$UserListService, $UserListService,
$UserMutingService, $UserMutingService,
$UserSuspendService, $UserSuspendService,
@ -519,7 +519,7 @@ const $ApQuestionService: Provider = { provide: 'ApQuestionService', useExisting
UserBlockingService, UserBlockingService,
CacheService, CacheService,
UserFollowingService, UserFollowingService,
UserKeypairStoreService, UserKeypairService,
UserListService, UserListService,
UserMutingService, UserMutingService,
UserSuspendService, UserSuspendService,
@ -635,7 +635,7 @@ const $ApQuestionService: Provider = { provide: 'ApQuestionService', useExisting
$UserBlockingService, $UserBlockingService,
$CacheService, $CacheService,
$UserFollowingService, $UserFollowingService,
$UserKeypairStoreService, $UserKeypairService,
$UserListService, $UserListService,
$UserMutingService, $UserMutingService,
$UserSuspendService, $UserSuspendService,

View file

@ -1,24 +1,34 @@
import { Inject, Injectable } from '@nestjs/common'; import { Inject, Injectable } from '@nestjs/common';
import Redis from 'ioredis';
import type { User } from '@/models/entities/User.js'; import type { User } from '@/models/entities/User.js';
import type { UserKeypairsRepository } from '@/models/index.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 type { UserKeypair } from '@/models/entities/UserKeypair.js';
import { DI } from '@/di-symbols.js'; import { DI } from '@/di-symbols.js';
import { bindThis } from '@/decorators.js'; import { bindThis } from '@/decorators.js';
@Injectable() @Injectable()
export class UserKeypairStoreService { export class UserKeypairService {
private cache: MemoryKVCache<UserKeypair>; private cache: RedisKVCache<UserKeypair>;
constructor( constructor(
@Inject(DI.redis)
private redisClient: Redis.Redis,
@Inject(DI.userKeypairsRepository) @Inject(DI.userKeypairsRepository)
private userKeypairsRepository: UserKeypairsRepository, private userKeypairsRepository: UserKeypairsRepository,
) { ) {
this.cache = new MemoryKVCache<UserKeypair>(Infinity); this.cache = new RedisKVCache<UserKeypair>(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 @bindThis
public async getUserKeypair(userId: User['id']): Promise<UserKeypair> { public async getUserKeypair(userId: User['id']): Promise<UserKeypair> {
return await this.cache.fetch(userId, () => this.userKeypairsRepository.findOneByOrFail({ userId: userId })); return await this.cache.fetch(userId);
} }
} }

View file

@ -14,7 +14,7 @@ import type { NoteReaction } from '@/models/entities/NoteReaction.js';
import type { Emoji } from '@/models/entities/Emoji.js'; import type { Emoji } from '@/models/entities/Emoji.js';
import type { Poll } from '@/models/entities/Poll.js'; import type { Poll } from '@/models/entities/Poll.js';
import type { PollVote } from '@/models/entities/PollVote.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 { MfmService } from '@/core/MfmService.js';
import { UserEntityService } from '@/core/entities/UserEntityService.js'; import { UserEntityService } from '@/core/entities/UserEntityService.js';
import { DriveFileEntityService } from '@/core/entities/DriveFileEntityService.js'; import { DriveFileEntityService } from '@/core/entities/DriveFileEntityService.js';
@ -53,7 +53,7 @@ export class ApRendererService {
private userEntityService: UserEntityService, private userEntityService: UserEntityService,
private driveFileEntityService: DriveFileEntityService, private driveFileEntityService: DriveFileEntityService,
private ldSignatureService: LdSignatureService, private ldSignatureService: LdSignatureService,
private userKeypairStoreService: UserKeypairStoreService, private userKeypairService: UserKeypairService,
private apMfmService: ApMfmService, private apMfmService: ApMfmService,
private mfmService: MfmService, private mfmService: MfmService,
) { ) {
@ -473,7 +473,7 @@ export class ApRendererService {
...hashtagTags, ...hashtagTags,
]; ];
const keypair = await this.userKeypairStoreService.getUserKeypair(user.id); const keypair = await this.userKeypairService.getUserKeypair(user.id);
const person = { const person = {
type: isSystem ? 'Application' : user.isBot ? 'Service' : 'Person', type: isSystem ? 'Application' : user.isBot ? 'Service' : 'Person',
@ -640,7 +640,7 @@ export class ApRendererService {
@bindThis @bindThis
public async attachLdSignature(activity: any, user: { id: User['id']; host: null; }): Promise<IActivity> { public async attachLdSignature(activity: any, user: { id: User['id']; host: null; }): Promise<IActivity> {
const keypair = await this.userKeypairStoreService.getUserKeypair(user.id); const keypair = await this.userKeypairService.getUserKeypair(user.id);
const ldSignature = this.ldSignatureService.use(); const ldSignature = this.ldSignatureService.use();
ldSignature.debug = false; ldSignature.debug = false;

View file

@ -4,7 +4,7 @@ import { Inject, Injectable } from '@nestjs/common';
import { DI } from '@/di-symbols.js'; import { DI } from '@/di-symbols.js';
import type { Config } from '@/config.js'; import type { Config } from '@/config.js';
import type { User } from '@/models/entities/User.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 { HttpRequestService } from '@/core/HttpRequestService.js';
import { LoggerService } from '@/core/LoggerService.js'; import { LoggerService } from '@/core/LoggerService.js';
import { bindThis } from '@/decorators.js'; import { bindThis } from '@/decorators.js';
@ -131,7 +131,7 @@ export class ApRequestService {
@Inject(DI.config) @Inject(DI.config)
private config: Config, private config: Config,
private userKeypairStoreService: UserKeypairStoreService, private userKeypairService: UserKeypairService,
private httpRequestService: HttpRequestService, private httpRequestService: HttpRequestService,
private loggerService: LoggerService, private loggerService: LoggerService,
) { ) {
@ -143,7 +143,7 @@ export class ApRequestService {
public async signedPost(user: { id: User['id'] }, url: string, object: any) { public async signedPost(user: { id: User['id'] }, url: string, object: any) {
const body = JSON.stringify(object); 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({ const req = ApRequestCreator.createSignedPost({
key: { key: {
@ -170,7 +170,7 @@ export class ApRequestService {
*/ */
@bindThis @bindThis
public async signedGet(url: string, user: { id: User['id'] }) { 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({ const req = ApRequestCreator.createSignedGet({
key: { key: {

View file

@ -12,7 +12,7 @@ import type { Config } from '@/config.js';
import { ApRendererService } from '@/core/activitypub/ApRendererService.js'; import { ApRendererService } from '@/core/activitypub/ApRendererService.js';
import { QueueService } from '@/core/QueueService.js'; import { QueueService } from '@/core/QueueService.js';
import type { LocalUser, User } from '@/models/entities/User.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 type { Following } from '@/models/entities/Following.js';
import { countIf } from '@/misc/prelude/array.js'; import { countIf } from '@/misc/prelude/array.js';
import type { Note } from '@/models/entities/Note.js'; import type { Note } from '@/models/entities/Note.js';
@ -58,7 +58,7 @@ export class ActivityPubServerService {
private userEntityService: UserEntityService, private userEntityService: UserEntityService,
private apRendererService: ApRendererService, private apRendererService: ApRendererService,
private queueService: QueueService, private queueService: QueueService,
private userKeypairStoreService: UserKeypairStoreService, private userKeypairService: UserKeypairService,
private queryService: QueryService, private queryService: QueryService,
) { ) {
//this.createServer = this.createServer.bind(this); //this.createServer = this.createServer.bind(this);
@ -540,7 +540,7 @@ export class ActivityPubServerService {
return; return;
} }
const keypair = await this.userKeypairStoreService.getUserKeypair(user.id); const keypair = await this.userKeypairService.getUserKeypair(user.id);
if (this.userEntityService.isLocalUser(user)) { if (this.userEntityService.isLocalUser(user)) {
reply.header('Cache-Control', 'public, max-age=180'); reply.header('Cache-Control', 'public, max-age=180');