summaryrefslogtreecommitdiff
path: root/packages/backend/src/core/FeaturedService.ts
diff options
context:
space:
mode:
authorsyuilo <Syuilotan@yahoo.co.jp>2023-10-06 16:58:38 +0900
committersyuilo <Syuilotan@yahoo.co.jp>2023-10-06 16:58:38 +0900
commit0bdbdba9f8617ee268005a941087cbe8af6b2ee3 (patch)
tree261ec0fbe764b44fed04ff5b4e5c4a22fbcd3e55 /packages/backend/src/core/FeaturedService.ts
parentrefactor (diff)
downloadsharkey-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.ts86
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);
}
}