diff options
| author | syuilo <Syuilotan@yahoo.co.jp> | 2023-10-06 16:58:38 +0900 |
|---|---|---|
| committer | syuilo <Syuilotan@yahoo.co.jp> | 2023-10-06 16:58:38 +0900 |
| commit | 0bdbdba9f8617ee268005a941087cbe8af6b2ee3 (patch) | |
| tree | 261ec0fbe764b44fed04ff5b4e5c4a22fbcd3e55 /packages/backend/src/core/FeaturedService.ts | |
| parent | refactor (diff) | |
| download | sharkey-0bdbdba9f8617ee268005a941087cbe8af6b2ee3.tar.gz sharkey-0bdbdba9f8617ee268005a941087cbe8af6b2ee3.tar.bz2 sharkey-0bdbdba9f8617ee268005a941087cbe8af6b2ee3.zip | |
refactor
Diffstat (limited to 'packages/backend/src/core/FeaturedService.ts')
| -rw-r--r-- | packages/backend/src/core/FeaturedService.ts | 86 |
1 files changed, 29 insertions, 57 deletions
diff --git a/packages/backend/src/core/FeaturedService.ts b/packages/backend/src/core/FeaturedService.ts index 78309e42e5..5963b7fc39 100644 --- a/packages/backend/src/core/FeaturedService.ts +++ b/packages/backend/src/core/FeaturedService.ts @@ -15,7 +15,7 @@ const GLOBAL_NOTES_RANKING_WINDOW = 1000 * 60 * 60 * 24 * 3; // 3日ごと export class FeaturedService { constructor( @Inject(DI.redis) - private redisClient: Redis.Redis, + private redisClient: Redis.Redis, // TODO: 専用のRedisサーバーを設定できるようにする ) { } @@ -26,55 +26,39 @@ export class FeaturedService { } @bindThis - private getCurrentGlobalNotesRankingWindow(): number { + private getCurrentWindow(windowRange: number): number { const passed = new Date().getTime() - new Date(new Date().getFullYear(), 0, 1).getTime(); - return Math.floor(passed / GLOBAL_NOTES_RANKING_WINDOW); + return Math.floor(passed / windowRange); } @bindThis - public async updateGlobalNotesRanking(noteId: MiNote['id'], score = 1): Promise<void> { - // TODO: フォロワー数の多い人が常にランキング上位になるのを防ぎたい - const currentWindow = this.getCurrentGlobalNotesRankingWindow(); + private async updateRankingOf(name: string, windowRange: number, element: string, score = 1): Promise<void> { + const currentWindow = this.getCurrentWindow(windowRange); const redisTransaction = this.redisClient.multi(); redisTransaction.zincrby( - `featuredGlobalNotesRanking:${currentWindow}`, - score.toString(), - noteId); + `${name}:${currentWindow}`, + score, + element); redisTransaction.expire( - `featuredGlobalNotesRanking:${currentWindow}`, - (GLOBAL_NOTES_RANKING_WINDOW * 3) / 1000, + `${name}:${currentWindow}`, + (windowRange * 3) / 1000, 'NX'); // "NX -- Set expiry only when the key has no expiry" = 有効期限がないときだけ設定 await redisTransaction.exec(); } @bindThis - public async updateInChannelNotesRanking(noteId: MiNote['id'], channelId: MiNote['channelId'], score = 1): Promise<void> { - const currentWindow = this.getCurrentGlobalNotesRankingWindow(); - const redisTransaction = this.redisClient.multi(); - redisTransaction.zincrby( - `featuredInChannelNotesRanking:${channelId}:${currentWindow}`, - score.toString(), - noteId); - redisTransaction.expire( - `featuredInChannelNotesRanking:${channelId}:${currentWindow}`, - (GLOBAL_NOTES_RANKING_WINDOW * 3) / 1000, - 'NX'); // "NX -- Set expiry only when the key has no expiry" = 有効期限がないときだけ設定 - await redisTransaction.exec(); - } - - @bindThis - public async getGlobalNotesRanking(limit: number): Promise<MiNote['id'][]> { - const currentWindow = this.getCurrentGlobalNotesRankingWindow(); + private async getRankingOf(name: string, windowRange: number, limit: number): Promise<string[]> { + const currentWindow = this.getCurrentWindow(windowRange); const previousWindow = currentWindow - 1; const [currentRankingResult, previousRankingResult] = await Promise.all([ this.redisClient.zrange( - `featuredGlobalNotesRanking:${currentWindow}`, 0, limit, 'REV', 'WITHSCORES'), + `${name}:${currentWindow}`, 0, limit, 'REV', 'WITHSCORES'), this.redisClient.zrange( - `featuredGlobalNotesRanking:${previousWindow}`, 0, limit, 'REV', 'WITHSCORES'), + `${name}:${previousWindow}`, 0, limit, 'REV', 'WITHSCORES'), ]); - const ranking = new Map<MiNote['id'], number>(); + const ranking = new Map<string, number>(); for (let i = 0; i < currentRankingResult.length; i += 2) { const noteId = currentRankingResult[i]; const score = parseInt(currentRankingResult[i + 1], 10); @@ -95,34 +79,22 @@ export class FeaturedService { } @bindThis - public async getInChannelNotesRanking(channelId: MiNote['channelId'], limit: number): Promise<MiNote['id'][]> { - const currentWindow = this.getCurrentGlobalNotesRankingWindow(); - const previousWindow = currentWindow - 1; + public async updateGlobalNotesRanking(noteId: MiNote['id'], score = 1): Promise<void> { + return this.updateRankingOf('featuredGlobalNotesRanking', GLOBAL_NOTES_RANKING_WINDOW, noteId, score); + } - const [currentRankingResult, previousRankingResult] = await Promise.all([ - this.redisClient.zrange( - `featuredInChannelNotesRanking:${channelId}:${currentWindow}`, 0, limit, 'REV', 'WITHSCORES'), - this.redisClient.zrange( - `featuredInChannelNotesRanking:${channelId}:${previousWindow}`, 0, limit, 'REV', 'WITHSCORES'), - ]); + @bindThis + public async updateInChannelNotesRanking(noteId: MiNote['id'], channelId: MiNote['channelId'], score = 1): Promise<void> { + return this.updateRankingOf(`featuredInChannelNotesRanking:${channelId}`, GLOBAL_NOTES_RANKING_WINDOW, noteId, score); + } - const ranking = new Map<MiNote['id'], number>(); - for (let i = 0; i < currentRankingResult.length; i += 2) { - const noteId = currentRankingResult[i]; - const score = parseInt(currentRankingResult[i + 1], 10); - ranking.set(noteId, score); - } - for (let i = 0; i < previousRankingResult.length; i += 2) { - const noteId = previousRankingResult[i]; - const score = parseInt(previousRankingResult[i + 1], 10); - const exist = ranking.get(noteId); - if (exist != null) { - ranking.set(noteId, (exist + score) / 2); - } else { - ranking.set(noteId, score); - } - } + @bindThis + public async getGlobalNotesRanking(limit: number): Promise<MiNote['id'][]> { + return this.getRankingOf('featuredGlobalNotesRanking', GLOBAL_NOTES_RANKING_WINDOW, limit); + } - return Array.from(ranking.keys()); + @bindThis + public async getInChannelNotesRanking(channelId: MiNote['channelId'], limit: number): Promise<MiNote['id'][]> { + return this.getRankingOf(`featuredInChannelNotesRanking:${channelId}`, GLOBAL_NOTES_RANKING_WINDOW, limit); } } |