From 4d3cace0f57a85b46b89207c1381027e5df4f0e4 Mon Sep 17 00:00:00 2001 From: osamu <46447427+sam-osamu@users.noreply.github.com> Date: Wed, 25 Oct 2023 22:12:45 +0900 Subject: [PATCH] =?UTF-8?q?=E3=83=81=E3=83=A3=E3=83=B3=E3=83=8D=E3=83=AB?= =?UTF-8?q?=E3=81=AE=E3=83=95=E3=82=A9=E3=83=AD=E3=83=BC=E3=83=BB=E3=82=A2?= =?UTF-8?q?=E3=83=B3=E3=83=95=E3=82=A9=E3=83=AD=E3=83=BC=E3=81=AE=E5=8F=8D?= =?UTF-8?q?=E6=98=A0=E9=80=9F=E5=BA=A6=E3=82=92=E6=94=B9=E5=96=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 1 + packages/backend/src/core/CacheService.ts | 8 +++ .../src/core/ChannelFollowingService.ts | 61 +++++++++++++++++++ packages/backend/src/core/CoreModule.ts | 6 ++ .../server/api/endpoints/channels/follow.ts | 16 ++--- .../server/api/endpoints/channels/unfollow.ts | 12 ++-- 6 files changed, 84 insertions(+), 20 deletions(-) create mode 100644 packages/backend/src/core/ChannelFollowingService.ts diff --git a/CHANGELOG.md b/CHANGELOG.md index 3decae2b9c..78716e5434 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -32,6 +32,7 @@ - Fix: 自分のフォローしているユーザーの自分のフォローしていないユーザーの visibility: followers な投稿への返信がストリーミングで流れてくる問題を修正 - Fix: RedisへのTLキャッシュが有効の場合にHTL/LTL/STLが空になることがある問題を修正 - Fix: STLでフォローしていないチャンネルが取得される問題を修正 +- Fix: フォローしているチャンネルをフォロー解除した時(またはその逆)、タイムラインに反映される間隔を改善 ## 2023.10.2 diff --git a/packages/backend/src/core/CacheService.ts b/packages/backend/src/core/CacheService.ts index 22c510cc37..f7d599f57e 100644 --- a/packages/backend/src/core/CacheService.ts +++ b/packages/backend/src/core/CacheService.ts @@ -197,6 +197,14 @@ export class CacheService implements OnApplicationShutdown { this.userFollowingsCache.delete(body.followerId); break; } + case 'followChannel': { + this.userFollowingChannelsCache.refresh(body.userId) + break; + } + case 'unfollowChannel': { + this.userFollowingChannelsCache.delete(body.userId) + break; + } default: break; } diff --git a/packages/backend/src/core/ChannelFollowingService.ts b/packages/backend/src/core/ChannelFollowingService.ts new file mode 100644 index 0000000000..4693177ae5 --- /dev/null +++ b/packages/backend/src/core/ChannelFollowingService.ts @@ -0,0 +1,61 @@ +import { Inject, Injectable, OnModuleInit } from '@nestjs/common'; +import { DI } from '@/di-symbols.js'; +import type { ChannelFollowingsRepository } from '@/models/_.js'; +import { MiChannel } from '@/models/_.js'; +import { IdService } from '@/core/IdService.js'; +import { CacheService } from '@/core/CacheService.js'; +import { GlobalEventService } from '@/core/GlobalEventService.js'; +import { bindThis } from '@/decorators.js'; +import type { MiLocalUser } from '@/models/User.js'; + +@Injectable() +export class ChannelFollowingService implements OnModuleInit { + constructor( + @Inject(DI.channelFollowingsRepository) + private channelFollowingsRepository: ChannelFollowingsRepository, + private idService: IdService, + private cacheService: CacheService, + private globalEventService: GlobalEventService, + ) { + } + + onModuleInit() { + } + + @bindThis + public async follow( + requestUser: MiLocalUser, + targetChannel: MiChannel, + ): Promise { + await this.channelFollowingsRepository.insert({ + id: this.idService.gen(), + followerId: requestUser.id, + followeeId: targetChannel.id, + }); + + this.cacheService.userFollowingsCache.refresh(requestUser.id); + + this.globalEventService.publishInternalEvent('followChannel', { + userId: requestUser.id, + channelId: targetChannel.id, + }); + } + + @bindThis + public async unfollow( + requestUser: MiLocalUser, + targetChannel: MiChannel, + ): Promise { + await this.channelFollowingsRepository.delete({ + followerId: requestUser.id, + followeeId: targetChannel.id, + }); + + this.cacheService.userFollowingsCache.refresh(requestUser.id); + + this.globalEventService.publishInternalEvent('unfollowChannel', { + userId: requestUser.id, + channelId: targetChannel.id, + }); + } +} diff --git a/packages/backend/src/core/CoreModule.ts b/packages/backend/src/core/CoreModule.ts index b46afb1909..c17ea9999a 100644 --- a/packages/backend/src/core/CoreModule.ts +++ b/packages/backend/src/core/CoreModule.ts @@ -63,6 +63,7 @@ import { SearchService } from './SearchService.js'; import { ClipService } from './ClipService.js'; import { FeaturedService } from './FeaturedService.js'; import { FunoutTimelineService } from './FunoutTimelineService.js'; +import { ChannelFollowingService } from './ChannelFollowingService.js'; import { ChartLoggerService } from './chart/ChartLoggerService.js'; import FederationChart from './chart/charts/federation.js'; import NotesChart from './chart/charts/notes.js'; @@ -193,6 +194,7 @@ const $SearchService: Provider = { provide: 'SearchService', useExisting: Search const $ClipService: Provider = { provide: 'ClipService', useExisting: ClipService }; const $FeaturedService: Provider = { provide: 'FeaturedService', useExisting: FeaturedService }; const $FunoutTimelineService: Provider = { provide: 'FunoutTimelineService', useExisting: FunoutTimelineService }; +const $ChannelFollowingService: Provider = { provide: 'ChannelFollowingService', useExisting: ChannelFollowingService }; const $ChartLoggerService: Provider = { provide: 'ChartLoggerService', useExisting: ChartLoggerService }; const $FederationChart: Provider = { provide: 'FederationChart', useExisting: FederationChart }; @@ -327,6 +329,7 @@ const $ApQuestionService: Provider = { provide: 'ApQuestionService', useExisting ClipService, FeaturedService, FunoutTimelineService, + ChannelFollowingService, ChartLoggerService, FederationChart, NotesChart, @@ -454,6 +457,7 @@ const $ApQuestionService: Provider = { provide: 'ApQuestionService', useExisting $ClipService, $FeaturedService, $FunoutTimelineService, + $ChannelFollowingService, $ChartLoggerService, $FederationChart, $NotesChart, @@ -582,6 +586,7 @@ const $ApQuestionService: Provider = { provide: 'ApQuestionService', useExisting ClipService, FeaturedService, FunoutTimelineService, + ChannelFollowingService, FederationChart, NotesChart, UsersChart, @@ -708,6 +713,7 @@ const $ApQuestionService: Provider = { provide: 'ApQuestionService', useExisting $ClipService, $FeaturedService, $FunoutTimelineService, + $ChannelFollowingService, $FederationChart, $NotesChart, $UsersChart, diff --git a/packages/backend/src/server/api/endpoints/channels/follow.ts b/packages/backend/src/server/api/endpoints/channels/follow.ts index 76ec6be805..bb5a477eb8 100644 --- a/packages/backend/src/server/api/endpoints/channels/follow.ts +++ b/packages/backend/src/server/api/endpoints/channels/follow.ts @@ -5,9 +5,9 @@ import { Inject, Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; -import type { ChannelFollowingsRepository, ChannelsRepository } from '@/models/_.js'; -import { IdService } from '@/core/IdService.js'; +import type { ChannelsRepository } from '@/models/_.js'; import { DI } from '@/di-symbols.js'; +import { ChannelFollowingService } from '@/core/ChannelFollowingService.js'; import { ApiError } from '../../error.js'; export const meta = { @@ -41,11 +41,7 @@ export default class extends Endpoint { // eslint- constructor( @Inject(DI.channelsRepository) private channelsRepository: ChannelsRepository, - - @Inject(DI.channelFollowingsRepository) - private channelFollowingsRepository: ChannelFollowingsRepository, - - private idService: IdService, + private channelFollowingService: ChannelFollowingService, ) { super(meta, paramDef, async (ps, me) => { const channel = await this.channelsRepository.findOneBy({ @@ -56,11 +52,7 @@ export default class extends Endpoint { // eslint- throw new ApiError(meta.errors.noSuchChannel); } - await this.channelFollowingsRepository.insert({ - id: this.idService.gen(), - followerId: me.id, - followeeId: channel.id, - }); + await this.channelFollowingService.follow(me, channel); }); } } diff --git a/packages/backend/src/server/api/endpoints/channels/unfollow.ts b/packages/backend/src/server/api/endpoints/channels/unfollow.ts index 46883dd548..c95332c7f8 100644 --- a/packages/backend/src/server/api/endpoints/channels/unfollow.ts +++ b/packages/backend/src/server/api/endpoints/channels/unfollow.ts @@ -5,8 +5,9 @@ import { Inject, Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; -import type { ChannelFollowingsRepository, ChannelsRepository } from '@/models/_.js'; +import type { ChannelsRepository } from '@/models/_.js'; import { DI } from '@/di-symbols.js'; +import { ChannelFollowingService } from '@/core/ChannelFollowingService.js'; import { ApiError } from '../../error.js'; export const meta = { @@ -40,9 +41,7 @@ export default class extends Endpoint { // eslint- constructor( @Inject(DI.channelsRepository) private channelsRepository: ChannelsRepository, - - @Inject(DI.channelFollowingsRepository) - private channelFollowingsRepository: ChannelFollowingsRepository, + private channelFollowingService: ChannelFollowingService, ) { super(meta, paramDef, async (ps, me) => { const channel = await this.channelsRepository.findOneBy({ @@ -53,10 +52,7 @@ export default class extends Endpoint { // eslint- throw new ApiError(meta.errors.noSuchChannel); } - await this.channelFollowingsRepository.delete({ - followerId: me.id, - followeeId: channel.id, - }); + await this.channelFollowingService.unfollow(me, channel); }); } }