From 372714c9b603e6e06ac1f0792c96d4066b7413d5 Mon Sep 17 00:00:00 2001 From: Hazelnoot Date: Sat, 7 Jun 2025 21:32:55 -0400 Subject: [PATCH] implement userFollowersCache --- packages/backend/src/core/CacheService.ts | 17 +++++++++++++++-- packages/backend/test/misc/noOpCaches.ts | 6 ++++++ 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/packages/backend/src/core/CacheService.ts b/packages/backend/src/core/CacheService.ts index 38a93e57f4..e8b26f8b9b 100644 --- a/packages/backend/src/core/CacheService.ts +++ b/packages/backend/src/core/CacheService.ts @@ -47,6 +47,7 @@ export class CacheService implements OnApplicationShutdown { public userBlockedCache: QuantumKVCache>; // NOTE: 「被」Blockキャッシュ public renoteMutingsCache: QuantumKVCache>; public userFollowingsCache: QuantumKVCache>; + public userFollowersCache: QuantumKVCache>; protected userFollowStatsCache = new MemoryKVCache(1000 * 60 * 10); // 10 minutes protected translationsCache: RedisKVCache; @@ -115,6 +116,11 @@ export class CacheService implements OnApplicationShutdown { fetcher: (key) => this.followingsRepository.find({ where: { followerId: key }, select: ['followeeId', 'withReplies'] }).then(xs => new Map(xs.map(f => [f.followeeId, { withReplies: f.withReplies }]))), }); + this.userFollowersCache = new QuantumKVCache>(this.internalEventService, 'userFollowers', { + lifetime: 1000 * 60 * 30, // 30m + fetcher: (key) => this.followingsRepository.find({ where: { followeeId: key }, select: ['followerId'] }).then(xs => new Set(xs.map(x => x.followerId))), + }); + this.translationsCache = new RedisKVCache(this.redisClient, 'translations', { lifetime: 1000 * 60 * 60 * 24 * 7, // 1 week, memoryCacheLifetime: 1000 * 60, // 1 minute @@ -154,6 +160,7 @@ export class CacheService implements OnApplicationShutdown { this.userBlockedCache.delete(body.id), this.renoteMutingsCache.delete(body.id), this.userFollowingsCache.delete(body.id), + this.userFollowersCache.delete(body.id), ]); } } else { @@ -193,7 +200,10 @@ export class CacheService implements OnApplicationShutdown { if (follower) follower.followingCount++; const followee = this.userByIdCache.get(body.followeeId); if (followee) followee.followersCount++; - await this.userFollowingsCache.delete(body.followerId); + await Promise.all([ + this.userFollowingsCache.delete(body.followerId), + this.userFollowersCache.delete(body.followeeId), + ]); this.userFollowStatsCache.delete(body.followerId); this.userFollowStatsCache.delete(body.followeeId); break; @@ -203,7 +213,10 @@ export class CacheService implements OnApplicationShutdown { if (follower) follower.followingCount--; const followee = this.userByIdCache.get(body.followeeId); if (followee) followee.followersCount--; - await this.userFollowingsCache.delete(body.followerId); + await Promise.all([ + this.userFollowingsCache.delete(body.followerId), + this.userFollowersCache.delete(body.followeeId), + ]); this.userFollowStatsCache.delete(body.followerId); this.userFollowStatsCache.delete(body.followeeId); break; diff --git a/packages/backend/test/misc/noOpCaches.ts b/packages/backend/test/misc/noOpCaches.ts index 7e8c27503c..40c5d2dc65 100644 --- a/packages/backend/test/misc/noOpCaches.ts +++ b/packages/backend/test/misc/noOpCaches.ts @@ -112,6 +112,12 @@ export class NoOpCacheService extends CacheService { onSet: this.userFollowingsCache.onSet, onDelete: this.userFollowingsCache.onDelete, }); + this.userFollowersCache = new NoOpQuantumKVCache>({ + internalEventService: fakeInternalEventService, + fetcher: this.userFollowersCache.fetcher, + onSet: this.userFollowersCache.onSet, + onDelete: this.userFollowersCache.onDelete, + }); this.userFollowStatsCache = new NoOpMemoryKVCache(); this.translationsCache = new NoOpRedisKVCache({ redis: fakeRedis,