summaryrefslogtreecommitdiff
path: root/packages/backend/src/core/UserBlockingService.ts
diff options
context:
space:
mode:
authorsyuilo <Syuilotan@yahoo.co.jp>2023-04-05 10:21:10 +0900
committersyuilo <Syuilotan@yahoo.co.jp>2023-04-05 10:21:10 +0900
commitf44504097c360fc84179161abee47b79a936b455 (patch)
treeaec17f0837ccad89754fae24c044ba0b8d7e8def /packages/backend/src/core/UserBlockingService.ts
parentenhance(backend): チャンネルの既読管理を削除 (diff)
downloadsharkey-f44504097c360fc84179161abee47b79a936b455.tar.gz
sharkey-f44504097c360fc84179161abee47b79a936b455.tar.bz2
sharkey-f44504097c360fc84179161abee47b79a936b455.zip
enhance(backend): improve cache
Diffstat (limited to 'packages/backend/src/core/UserBlockingService.ts')
-rw-r--r--packages/backend/src/core/UserBlockingService.ts130
1 files changed, 16 insertions, 114 deletions
diff --git a/packages/backend/src/core/UserBlockingService.ts b/packages/backend/src/core/UserBlockingService.ts
index 040b6de2ef..6eaef8f68a 100644
--- a/packages/backend/src/core/UserBlockingService.ts
+++ b/packages/backend/src/core/UserBlockingService.ts
@@ -1,40 +1,26 @@
-import { Inject, Injectable, OnApplicationShutdown } from '@nestjs/common';
-import Redis from 'ioredis';
+import { Inject, Injectable } from '@nestjs/common';
import { IdService } from '@/core/IdService.js';
import type { User } from '@/models/entities/User.js';
import type { Blocking } from '@/models/entities/Blocking.js';
import { QueueService } from '@/core/QueueService.js';
import { GlobalEventService } from '@/core/GlobalEventService.js';
-import PerUserFollowingChart from '@/core/chart/charts/per-user-following.js';
import { DI } from '@/di-symbols.js';
-import type { UsersRepository, FollowingsRepository, FollowRequestsRepository, BlockingsRepository, UserListsRepository, UserListJoiningsRepository } from '@/models/index.js';
+import type { FollowRequestsRepository, BlockingsRepository, UserListsRepository, UserListJoiningsRepository } from '@/models/index.js';
import Logger from '@/logger.js';
import { UserEntityService } from '@/core/entities/UserEntityService.js';
import { ApRendererService } from '@/core/activitypub/ApRendererService.js';
import { LoggerService } from '@/core/LoggerService.js';
import { WebhookService } from '@/core/WebhookService.js';
import { bindThis } from '@/decorators.js';
-import { MemoryKVCache } from '@/misc/cache.js';
-import { StreamMessages } from '@/server/api/stream/types.js';
+import { CacheService } from '@/core/CacheService.js';
+import { UserFollowingService } from '@/core/UserFollowingService.js';
@Injectable()
-export class UserBlockingService implements OnApplicationShutdown {
+export class UserBlockingService {
private logger: Logger;
- // キーがユーザーIDで、値がそのユーザーがブロックしているユーザーのIDのリストなキャッシュ
- private blockingsByUserIdCache: MemoryKVCache<User['id'][]>;
-
constructor(
- @Inject(DI.redisSubscriber)
- private redisSubscriber: Redis.Redis,
-
- @Inject(DI.usersRepository)
- private usersRepository: UsersRepository,
-
- @Inject(DI.followingsRepository)
- private followingsRepository: FollowingsRepository,
-
@Inject(DI.followRequestsRepository)
private followRequestsRepository: FollowRequestsRepository,
@@ -47,47 +33,17 @@ export class UserBlockingService implements OnApplicationShutdown {
@Inject(DI.userListJoiningsRepository)
private userListJoiningsRepository: UserListJoiningsRepository,
+ private cacheService: CacheService,
+ private userFollowingService: UserFollowingService,
private userEntityService: UserEntityService,
private idService: IdService,
private queueService: QueueService,
private globalEventService: GlobalEventService,
private webhookService: WebhookService,
private apRendererService: ApRendererService,
- private perUserFollowingChart: PerUserFollowingChart,
private loggerService: LoggerService,
) {
this.logger = this.loggerService.getLogger('user-block');
-
- this.blockingsByUserIdCache = new MemoryKVCache<User['id'][]>(Infinity);
-
- this.redisSubscriber.on('message', this.onMessage);
- }
-
- @bindThis
- private async onMessage(_: string, data: string): Promise<void> {
- const obj = JSON.parse(data);
-
- if (obj.channel === 'internal') {
- const { type, body } = obj.message as StreamMessages['internal']['payload'];
- switch (type) {
- case 'blockingCreated': {
- const cached = this.blockingsByUserIdCache.get(body.blockerId);
- if (cached) {
- this.blockingsByUserIdCache.set(body.blockerId, [...cached, ...[body.blockeeId]]);
- }
- break;
- }
- case 'blockingDeleted': {
- const cached = this.blockingsByUserIdCache.get(body.blockerId);
- if (cached) {
- this.blockingsByUserIdCache.set(body.blockerId, cached.filter(x => x !== body.blockeeId));
- }
- break;
- }
- default:
- break;
- }
- }
}
@bindThis
@@ -95,8 +51,8 @@ export class UserBlockingService implements OnApplicationShutdown {
await Promise.all([
this.cancelRequest(blocker, blockee),
this.cancelRequest(blockee, blocker),
- this.unFollow(blocker, blockee),
- this.unFollow(blockee, blocker),
+ this.userFollowingService.unfollow(blocker, blockee),
+ this.userFollowingService.unfollow(blockee, blocker),
this.removeFromList(blockee, blocker),
]);
@@ -111,6 +67,9 @@ export class UserBlockingService implements OnApplicationShutdown {
await this.blockingsRepository.insert(blocking);
+ this.cacheService.userBlockingCache.refresh(blocker.id);
+ this.cacheService.userBlockedCache.refresh(blockee.id);
+
this.globalEventService.publishInternalEvent('blockingCreated', {
blockerId: blocker.id,
blockeeId: blockee.id,
@@ -148,7 +107,6 @@ export class UserBlockingService implements OnApplicationShutdown {
this.userEntityService.pack(followee, follower, {
detail: true,
}).then(async packed => {
- this.globalEventService.publishUserEvent(follower.id, 'unfollow', packed);
this.globalEventService.publishMainStream(follower.id, 'unfollow', packed);
const webhooks = (await this.webhookService.getActiveWebhooks()).filter(x => x.userId === follower.id && x.on.includes('unfollow'));
@@ -174,54 +132,6 @@ export class UserBlockingService implements OnApplicationShutdown {
}
@bindThis
- private async unFollow(follower: User, followee: User) {
- const following = await this.followingsRepository.findOneBy({
- followerId: follower.id,
- followeeId: followee.id,
- });
-
- if (following == null) {
- return;
- }
-
- await Promise.all([
- this.followingsRepository.delete(following.id),
- this.usersRepository.decrement({ id: follower.id }, 'followingCount', 1),
- this.usersRepository.decrement({ id: followee.id }, 'followersCount', 1),
- this.perUserFollowingChart.update(follower, followee, false),
- ]);
-
- // Publish unfollow event
- if (this.userEntityService.isLocalUser(follower)) {
- this.userEntityService.pack(followee, follower, {
- detail: true,
- }).then(async packed => {
- this.globalEventService.publishUserEvent(follower.id, 'unfollow', packed);
- this.globalEventService.publishMainStream(follower.id, 'unfollow', packed);
-
- const webhooks = (await this.webhookService.getActiveWebhooks()).filter(x => x.userId === follower.id && x.on.includes('unfollow'));
- for (const webhook of webhooks) {
- this.queueService.webhookDeliver(webhook, 'unfollow', {
- user: packed,
- });
- }
- });
- }
-
- // リモートにフォローをしていたらUndoFollow送信
- if (this.userEntityService.isLocalUser(follower) && this.userEntityService.isRemoteUser(followee)) {
- const content = this.apRendererService.addContext(this.apRendererService.renderUndo(this.apRendererService.renderFollow(follower, followee), follower));
- this.queueService.deliver(follower, content, followee.inbox, false);
- }
-
- // リモートからフォローをされていたらRejectFollow送信
- if (this.userEntityService.isLocalUser(followee) && this.userEntityService.isRemoteUser(follower)) {
- const content = this.apRendererService.addContext(this.apRendererService.renderReject(this.apRendererService.renderFollow(follower, followee), followee));
- this.queueService.deliver(followee, content, follower.inbox, false);
- }
- }
-
- @bindThis
private async removeFromList(listOwner: User, user: User) {
const userLists = await this.userListsRepository.findBy({
userId: listOwner.id,
@@ -254,6 +164,9 @@ export class UserBlockingService implements OnApplicationShutdown {
await this.blockingsRepository.delete(blocking.id);
+ this.cacheService.userBlockingCache.refresh(blocker.id);
+ this.cacheService.userBlockedCache.refresh(blockee.id);
+
this.globalEventService.publishInternalEvent('blockingDeleted', {
blockerId: blocker.id,
blockeeId: blockee.id,
@@ -268,17 +181,6 @@ export class UserBlockingService implements OnApplicationShutdown {
@bindThis
public async checkBlocked(blockerId: User['id'], blockeeId: User['id']): Promise<boolean> {
- const blockedUserIds = await this.blockingsByUserIdCache.fetch(blockerId, () => this.blockingsRepository.find({
- where: {
- blockerId,
- },
- select: ['blockeeId'],
- }).then(records => records.map(record => record.blockeeId)));
- return blockedUserIds.includes(blockeeId);
- }
-
- @bindThis
- public onApplicationShutdown(signal?: string | undefined) {
- this.redisSubscriber.off('message', this.onMessage);
+ return (await this.cacheService.userBlockingCache.fetch(blockerId)).has(blockeeId);
}
}