summaryrefslogtreecommitdiff
path: root/packages/backend/src/core
diff options
context:
space:
mode:
authorHazelnoot <acomputerdog@gmail.com>2025-06-07 21:27:25 -0400
committerHazelnoot <acomputerdog@gmail.com>2025-06-09 11:02:36 -0400
commit853b548a4369051b8fdaabbda80d7d6ed52adb77 (patch)
tree7aec31303f244cbdec4aee82fdbc0b0e90c33a83 /packages/backend/src/core
parentmove QuantumKVCache to a separate file (diff)
downloadsharkey-853b548a4369051b8fdaabbda80d7d6ed52adb77.tar.gz
sharkey-853b548a4369051b8fdaabbda80d7d6ed52adb77.tar.bz2
sharkey-853b548a4369051b8fdaabbda80d7d6ed52adb77.zip
re-type userFollowingsCache to match the others
Diffstat (limited to 'packages/backend/src/core')
-rw-r--r--packages/backend/src/core/AntennaService.ts3
-rw-r--r--packages/backend/src/core/CacheService.ts38
-rw-r--r--packages/backend/src/core/NotificationService.ts12
-rw-r--r--packages/backend/src/core/entities/NoteEntityService.ts14
4 files changed, 29 insertions, 38 deletions
diff --git a/packages/backend/src/core/AntennaService.ts b/packages/backend/src/core/AntennaService.ts
index cf696e3599..667df57943 100644
--- a/packages/backend/src/core/AntennaService.ts
+++ b/packages/backend/src/core/AntennaService.ts
@@ -130,7 +130,8 @@ export class AntennaService implements OnApplicationShutdown {
}
if (note.visibility === 'followers') {
- const isFollowing = Object.hasOwn(await this.cacheService.userFollowingsCache.fetch(antenna.userId), note.userId);
+ const followings = await this.cacheService.userFollowingsCache.fetch(antenna.userId);
+ const isFollowing = followings.has(note.userId);
if (!isFollowing && antenna.userId !== note.userId) return false;
}
diff --git a/packages/backend/src/core/CacheService.ts b/packages/backend/src/core/CacheService.ts
index e59857b4ce..38a93e57f4 100644
--- a/packages/backend/src/core/CacheService.ts
+++ b/packages/backend/src/core/CacheService.ts
@@ -6,14 +6,14 @@
import { Inject, Injectable } from '@nestjs/common';
import * as Redis from 'ioredis';
import { In, IsNull } from 'typeorm';
-import type { BlockingsRepository, FollowingsRepository, MutingsRepository, RenoteMutingsRepository, MiUserProfile, UserProfilesRepository, UsersRepository, MiFollowing, MiNote } from '@/models/_.js';
+import type { BlockingsRepository, FollowingsRepository, MutingsRepository, RenoteMutingsRepository, MiUserProfile, UserProfilesRepository, UsersRepository, MiNote } from '@/models/_.js';
import { MemoryKVCache, RedisKVCache } from '@/misc/cache.js';
import { QuantumKVCache } from '@/misc/QuantumKVCache.js';
import type { MiLocalUser, MiUser } from '@/models/User.js';
import { DI } from '@/di-symbols.js';
import { UserEntityService } from '@/core/entities/UserEntityService.js';
import { bindThis } from '@/decorators.js';
-import type { GlobalEvents, InternalEventTypes } from '@/core/GlobalEventService.js';
+import type { InternalEventTypes } from '@/core/GlobalEventService.js';
import { InternalEventService } from '@/core/InternalEventService.js';
import type { OnApplicationShutdown } from '@nestjs/common';
@@ -46,7 +46,7 @@ export class CacheService implements OnApplicationShutdown {
public userBlockingCache: QuantumKVCache<Set<string>>;
public userBlockedCache: QuantumKVCache<Set<string>>; // NOTE: 「被」Blockキャッシュ
public renoteMutingsCache: QuantumKVCache<Set<string>>;
- public userFollowingsCache: QuantumKVCache<Record<string, Pick<MiFollowing, 'withReplies'> | undefined>>;
+ public userFollowingsCache: QuantumKVCache<Map<string, { withReplies: boolean }>>;
protected userFollowStatsCache = new MemoryKVCache<FollowStats>(1000 * 60 * 10); // 10 minutes
protected translationsCache: RedisKVCache<CachedTranslationEntity>;
@@ -110,15 +110,9 @@ export class CacheService implements OnApplicationShutdown {
fetcher: (key) => this.renoteMutingsRepository.find({ where: { muterId: key }, select: ['muteeId'] }).then(xs => new Set(xs.map(x => x.muteeId))),
});
- this.userFollowingsCache = new QuantumKVCache<Record<string, Pick<MiFollowing, 'withReplies'> | undefined>>(this.internalEventService, 'userFollowings', {
+ this.userFollowingsCache = new QuantumKVCache<Map<string, { withReplies: boolean }>>(this.internalEventService, 'userFollowings', {
lifetime: 1000 * 60 * 30, // 30m
- fetcher: (key) => this.followingsRepository.find({ where: { followerId: key }, select: ['followeeId', 'withReplies'] }).then(xs => {
- const obj: Record<string, Pick<MiFollowing, 'withReplies'> | undefined> = {};
- for (const x of xs) {
- obj[x.followeeId] = { withReplies: x.withReplies };
- }
- return obj;
- }),
+ fetcher: (key) => this.followingsRepository.find({ where: { followerId: key }, select: ['followeeId', 'withReplies'] }).then(xs => new Map(xs.map(f => [f.followeeId, { withReplies: f.withReplies }]))),
});
this.translationsCache = new RedisKVCache<CachedTranslationEntity>(this.redisClient, 'translations', {
@@ -305,14 +299,14 @@ export class CacheService implements OnApplicationShutdown {
}
@bindThis
- public async getUserFollowings(userIds: Iterable<string>): Promise<Map<string, Set<string>>> {
- const followings = new Map<string, Set<string>>();
+ public async getUserFollowings(userIds: Iterable<string>): Promise<Map<string, Map<string, { withReplies: boolean }>>> {
+ const followings = new Map<string, Map<string, { withReplies: boolean }>>();
const toFetch: string[] = [];
for (const userId of userIds) {
const fromCache = this.userFollowingsCache.get(userId);
if (fromCache) {
- followings.set(userId, new Set(Object.keys(fromCache)));
+ followings.set(userId, fromCache);
} else {
toFetch.push(userId);
}
@@ -331,25 +325,25 @@ export class CacheService implements OnApplicationShutdown {
})
.getMany();
- const toCache = new Map<string, Record<string, Pick<MiFollowing, 'withReplies'> | undefined>>();
+ const toCache = new Map<string, Map<string, { withReplies: boolean }>>();
// Pivot to a map
for (const { followerId, followeeId, withReplies } of fetchedFollowings) {
// Queue for cache
- let cacheSet = toCache.get(followerId);
- if (!cacheSet) {
- cacheSet = {};
- toCache.set(followerId, cacheSet);
+ let cacheMap = toCache.get(followerId);
+ if (!cacheMap) {
+ cacheMap = new Map();
+ toCache.set(followerId, cacheMap);
}
- cacheSet[followeeId] = { withReplies };
+ cacheMap.set(followeeId, { withReplies });
// Queue for return
let returnSet = followings.get(followerId);
if (!returnSet) {
- returnSet = new Set();
+ returnSet = new Map();
followings.set(followerId, returnSet);
}
- returnSet.add(followeeId);
+ returnSet.set(followeeId, { withReplies });
}
// Update cache to speed up future calls
diff --git a/packages/backend/src/core/NotificationService.ts b/packages/backend/src/core/NotificationService.ts
index 0f05f5425d..2ce7bdb5a9 100644
--- a/packages/backend/src/core/NotificationService.ts
+++ b/packages/backend/src/core/NotificationService.ts
@@ -113,27 +113,27 @@ export class NotificationService implements OnApplicationShutdown {
}
if (recieveConfig?.type === 'following') {
- const isFollowing = await this.cacheService.userFollowingsCache.fetch(notifieeId).then(followings => Object.hasOwn(followings, notifierId));
+ const isFollowing = await this.cacheService.userFollowingsCache.fetch(notifieeId).then(followings => followings.has(notifierId));
if (!isFollowing) {
return null;
}
} else if (recieveConfig?.type === 'follower') {
- const isFollower = await this.cacheService.userFollowingsCache.fetch(notifierId).then(followings => Object.hasOwn(followings, notifieeId));
+ const isFollower = await this.cacheService.userFollowingsCache.fetch(notifierId).then(followings => followings.has(notifieeId));
if (!isFollower) {
return null;
}
} else if (recieveConfig?.type === 'mutualFollow') {
const [isFollowing, isFollower] = await Promise.all([
- this.cacheService.userFollowingsCache.fetch(notifieeId).then(followings => Object.hasOwn(followings, notifierId)),
- this.cacheService.userFollowingsCache.fetch(notifierId).then(followings => Object.hasOwn(followings, notifieeId)),
+ this.cacheService.userFollowingsCache.fetch(notifieeId).then(followings => followings.has(notifierId)),
+ this.cacheService.userFollowingsCache.fetch(notifierId).then(followings => followings.has(notifieeId)),
]);
if (!(isFollowing && isFollower)) {
return null;
}
} else if (recieveConfig?.type === 'followingOrFollower') {
const [isFollowing, isFollower] = await Promise.all([
- this.cacheService.userFollowingsCache.fetch(notifieeId).then(followings => Object.hasOwn(followings, notifierId)),
- this.cacheService.userFollowingsCache.fetch(notifierId).then(followings => Object.hasOwn(followings, notifieeId)),
+ this.cacheService.userFollowingsCache.fetch(notifieeId).then(followings => followings.has(notifierId)),
+ this.cacheService.userFollowingsCache.fetch(notifierId).then(followings => followings.has(notifieeId)),
]);
if (!isFollowing && !isFollower) {
return null;
diff --git a/packages/backend/src/core/entities/NoteEntityService.ts b/packages/backend/src/core/entities/NoteEntityService.ts
index 1b3920e13f..3af66b220d 100644
--- a/packages/backend/src/core/entities/NoteEntityService.ts
+++ b/packages/backend/src/core/entities/NoteEntityService.ts
@@ -133,7 +133,7 @@ export class NoteEntityService implements OnModuleInit {
@bindThis
public async hideNote(packedNote: Packed<'Note'>, meId: MiUser['id'] | null, hint?: {
- myFollowing?: ReadonlySet<string>,
+ myFollowing?: ReadonlyMap<string, { withReplies: boolean }>,
myBlockers?: ReadonlySet<string>,
}): Promise<void> {
if (meId === packedNote.userId) return;
@@ -193,7 +193,7 @@ export class NoteEntityService implements OnModuleInit {
} else {
const isFollowing = hint?.myFollowing
? hint.myFollowing.has(packedNote.userId)
- : (await this.cacheService.userFollowingsCache.fetch(meId))[packedNote.userId] != null;
+ : (await this.cacheService.userFollowingsCache.fetch(meId)).has(packedNote.userId);
hide = !isFollowing;
}
@@ -358,14 +358,10 @@ export class NoteEntityService implements OnModuleInit {
: this.cacheService.userBlockingCache.fetch(meId).then((ids) => ids.has(note.userId)),
hint?.myFollowing
? hint.myFollowing.has(note.userId)
- : this.followingsRepository.existsBy({
- followeeId: note.userId,
- followerId: meId,
- }),
+ : this.cacheService.userFollowingsCache.fetch(meId).then(ids => ids.has(note.userId)),
hint?.me !== undefined
? (hint.me?.host ?? null)
- : this.cacheService.userByIdCache.fetch(meId, () => this.usersRepository.findOneByOrFail({ id: meId }))
- .then(me => me.host),
+ : this.cacheService.findUserById(meId).then(me => me.host),
]);
if (blocked) return false;
@@ -420,7 +416,7 @@ export class NoteEntityService implements OnModuleInit {
packedFiles: Map<MiNote['fileIds'][number], Packed<'DriveFile'> | null>;
packedUsers: Map<MiUser['id'], Packed<'UserLite'>>;
mentionHandles: Record<string, string | undefined>;
- userFollowings: Map<string, Set<string>>;
+ userFollowings: Map<string, Map<string, { withReplies: boolean }>>;
userBlockers: Map<string, Set<string>>;
polls: Map<string, MiPoll>;
pollVotes: Map<string, Map<string, MiPollVote[]>>;