From f8ae02769cde2e35c3b4d7acda4d17bb5f718e19 Mon Sep 17 00:00:00 2001 From: jaham Date: Sun, 29 Oct 2023 23:38:55 +0900 Subject: [PATCH 1/3] =?UTF-8?q?refactor:=20:recycle:=20coalition=20model?= =?UTF-8?q?=20=EA=B0=9C=ED=8E=B8,=20=EA=B4=80=EB=A0=A8=20=ED=95=A8?= =?UTF-8?q?=EC=88=98=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - imageUrl => imgUrl 로 변경, 사용하지 않는 field 들 deprecate - page/common/ 으로 이동 - 수정 중 scoreService 의 winCountPerCoalition 이 slow query 임을 발견하고 수정 - #378 --- app/src/api/coalition/coalition.service.ts | 4 +- .../api/coalition/models/coalition.model.ts | 28 ---------- app/src/api/score/score.cache.service.ts | 7 +++ app/src/api/score/score.service.ts | 52 ++++++++++++------- app/src/common/userFullProfile.ts | 2 +- app/src/lambda/lambda.service.ts | 12 +++++ app/src/page/common/models/coalition.model.ts | 34 ++++++++++++ .../home/coalition/home.coalition.service.ts | 14 ++--- .../coalition/models/home.coalition.model.ts | 2 +- .../personal.general.character.pokemon.ts | 2 +- .../personal.general.userProfile.model.ts | 2 +- app/src/schema.gql | 9 ++-- 12 files changed, 101 insertions(+), 67 deletions(-) delete mode 100644 app/src/api/coalition/models/coalition.model.ts create mode 100644 app/src/page/common/models/coalition.model.ts diff --git a/app/src/api/coalition/coalition.service.ts b/app/src/api/coalition/coalition.service.ts index 4d88bbc4..c8a3b548 100644 --- a/app/src/api/coalition/coalition.service.ts +++ b/app/src/api/coalition/coalition.service.ts @@ -4,8 +4,8 @@ import { InjectModel } from '@nestjs/mongoose'; import type { Aggregate, Model } from 'mongoose'; import { API_CONFIG } from 'src/config/api'; import { CDN_CONFIG } from 'src/config/cdn'; +import type { Coalition } from '../../page/common/models/coalition.model'; import { coalition } from './db/coalition.database.schema'; -import type { Coalition } from './models/coalition.model'; @Injectable() export class CoalitionService { @@ -26,7 +26,9 @@ export class CoalitionService { return { ...dao, coverUrl: this.coverUrlById(dao.id), + // todo: deprecated at v0.9.0 imageUrl: this.imageUrlById(dao.id), + imgUrl: this.imageUrlById(dao.id), color: dao.color ?? '#161616', }; } diff --git a/app/src/api/coalition/models/coalition.model.ts b/app/src/api/coalition/models/coalition.model.ts deleted file mode 100644 index ece8954a..00000000 --- a/app/src/api/coalition/models/coalition.model.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { Field, ObjectType } from '@nestjs/graphql'; - -@ObjectType() -export class Coalition { - @Field() - id: number; - - @Field() - name: string; - - @Field() - slug: string; - - @Field() - imageUrl: string; - - @Field() - coverUrl: string; - - @Field() - color: string; - - @Field() - score: number; - - @Field({ description: '코알리숑 마스터의 user id 입니다.' }) - userId: number; -} diff --git a/app/src/api/score/score.cache.service.ts b/app/src/api/score/score.cache.service.ts index c6256625..7b8760e6 100644 --- a/app/src/api/score/score.cache.service.ts +++ b/app/src/api/score/score.cache.service.ts @@ -11,6 +11,7 @@ import { ScoreService } from './score.service'; export const SCORE_RANKING = 'scoreRanking'; export const TOTAL_SCORES_BY_COALITION = 'totalScoresByCoalition'; export const SCORE_RECORDS = 'scoreRecords'; +export const WIN_COUNT_PER_COALITION = 'winCountPerCoalition'; export type ScoreRankingSupportedDateTemplate = Extract< RankingSupportedDateTemplate, @@ -63,4 +64,10 @@ export class ScoreCacheService { > { return await this.cacheUtilService.getWithoutDate(SCORE_RECORDS); } + + async getWinCountPerCoalition(): Promise< + ReturnType | undefined + > { + return await this.cacheUtilService.getWithoutDate(WIN_COUNT_PER_COALITION); + } } diff --git a/app/src/api/score/score.service.ts b/app/src/api/score/score.service.ts index 24494d69..c6011bba 100644 --- a/app/src/api/score/score.service.ts +++ b/app/src/api/score/score.service.ts @@ -4,6 +4,7 @@ import { InjectModel } from '@nestjs/mongoose'; import type { FilterQuery, Model } from 'mongoose'; import { RUNTIME_CONFIG } from 'src/config/runtime'; import { addRank } from 'src/database/mongoose/database.mongoose.aggregation'; +import { DateWrapper } from 'src/dateWrapper/dateWrapper'; import type { IntPerCoalition, ScoreRecordPerCoalition, @@ -75,9 +76,11 @@ export class ScoreService { const targetCoalitionIds = args?.targetCoalitionIds ?? this.coalitionService.getSeoulCoalitionIds(); - const aggregate = this.scoreModel.aggregate(); + const aggregate = this.scoreModel.aggregate< + Omit & { coalition: coalition } + >(); - return await aggregate + const scoresPerCoalitionDao = await aggregate .match({ coalitionsUserId: { $ne: null }, coalitionId: { $in: targetCoalitionIds }, @@ -93,6 +96,11 @@ export class ScoreService { coalition: { $first: '$coalitions' }, value: 1, }); + + return scoresPerCoalitionDao.map(({ value, coalition }) => ({ + coalition: this.coalitionService.daoToDto(coalition), + value, + })); } async scoreRecordsPerCoalition(args?: { @@ -102,10 +110,11 @@ export class ScoreService { const targetCoalitionIds = args?.targetCoalitionIds ?? this.coalitionService.getSeoulCoalitionIds(); - const aggregate = - this.coalitionService.aggregate(); + const aggregate = this.coalitionService.aggregate< + Omit & { coalition: coalition } + >(); - return await aggregate + const scoreRecordsPerCoalitionDao = await aggregate .match({ id: { $in: targetCoalitionIds }, }) @@ -160,6 +169,11 @@ export class ScoreService { }, }, }); + + return scoreRecordsPerCoalitionDao.map(({ coalition, records }) => ({ + coalition: this.coalitionService.daoToDto(coalition), + records, + })); } async tigCountPerCoalition(args?: { @@ -202,20 +216,17 @@ export class ScoreService { ); } - async winCountPerCoalition(args?: { - targetCoalitionIds?: readonly number[]; - filter?: FilterQuery; - }): Promise { - const targetCoalitionIds = - args?.targetCoalitionIds ?? this.coalitionService.getSeoulCoalitionIds(); + async winCountPerCoalition(): Promise { + const endDate = new DateWrapper().startOfMonth().toDate(); - const aggregate = this.scoreModel.aggregate(); + const aggregate = this.scoreModel.aggregate< + Omit & { coalition: coalition } + >(); - return await aggregate + const winCountPerCoalitionDao = await aggregate .match({ - ...args?.filter, + createdAt: { $lt: endDate }, coalitionsUserId: { $ne: null }, - coalitionId: { $in: targetCoalitionIds }, }) .group({ _id: { @@ -242,16 +253,17 @@ export class ScoreService { _id: '$winCoalition._id.coalitionId', value: { $count: {} }, }) + .sort({ _id: 1 }) .append(lookupCoalition('_id', 'id')) .project({ _id: 0, coalition: { $first: '$coalitions' }, value: 1, - }) - .then((winCountPerCoalition) => { - return winCountPerCoalition.sort( - (a, b) => a.coalition.id - b.coalition.id, - ); }); + + return winCountPerCoalitionDao.map(({ coalition, value }) => ({ + coalition: this.coalitionService.daoToDto(coalition), + value, + })); } } diff --git a/app/src/common/userFullProfile.ts b/app/src/common/userFullProfile.ts index da34ceed..b8b197f1 100644 --- a/app/src/common/userFullProfile.ts +++ b/app/src/common/userFullProfile.ts @@ -1,4 +1,4 @@ -import type { Coalition } from 'src/api/coalition/models/coalition.model'; +import type { Coalition } from 'src/page/common/models/coalition.model'; import type { cursus_user } from 'src/api/cursusUser/db/cursusUser.database.schema'; import type { title } from 'src/api/title/db/title.database.schema'; import type { titles_user } from 'src/api/titlesUser/db/titlesUser.database.schema'; diff --git a/app/src/lambda/lambda.service.ts b/app/src/lambda/lambda.service.ts index 5022f698..a7a1dbba 100644 --- a/app/src/lambda/lambda.service.ts +++ b/app/src/lambda/lambda.service.ts @@ -26,6 +26,7 @@ import { SCORE_RANKING, SCORE_RECORDS, TOTAL_SCORES_BY_COALITION, + WIN_COUNT_PER_COALITION, } from 'src/api/score/score.cache.service'; import { ScoreService } from 'src/api/score/score.service'; import { CacheUtilRankingService } from 'src/cache/cache.util.ranking.service'; @@ -177,6 +178,7 @@ export class LambdaService { await this.updateTotalScoresPerCoalition(updatedAt); await this.updateScoreRecords(updatedAt); + await this.updateWinCountPerCoalition(updatedAt); const currMonthExp = await this.experienceUserService.increamentRanking( expIncreamentDateFilter(currMonth), @@ -301,4 +303,14 @@ export class LambdaService { updatedAt, ); } + + private async updateWinCountPerCoalition(updatedAt: Date): Promise { + const winCountPerCoalition = await this.scoreService.winCountPerCoalition(); + + await this.cacheUtilService.setWithDate( + WIN_COUNT_PER_COALITION, + winCountPerCoalition, + updatedAt, + ); + } } diff --git a/app/src/page/common/models/coalition.model.ts b/app/src/page/common/models/coalition.model.ts new file mode 100644 index 00000000..4f5fe691 --- /dev/null +++ b/app/src/page/common/models/coalition.model.ts @@ -0,0 +1,34 @@ +import { Field, ObjectType } from '@nestjs/graphql'; + +@ObjectType() +export class Coalition { + @Field() + id: number; + + @Field() + name: string; + + @Field({ deprecationReason: 'deprecated at v0.9.0' }) + slug: string; + + @Field({ deprecationReason: 'deprecated at v0.9.0, imgUrl 을 사용하세요.' }) + imageUrl: string; + + @Field() + imgUrl: string; + + @Field() + coverUrl: string; + + @Field() + color: string; + + @Field({ deprecationReason: 'deprecated at v0.9.0' }) + score: number; + + @Field({ + description: '코알리숑 마스터의 user id 입니다.', + deprecationReason: 'deprecated at v0.9.0', + }) + userId: number; +} diff --git a/app/src/page/home/coalition/home.coalition.service.ts b/app/src/page/home/coalition/home.coalition.service.ts index 2ac22563..4c61fe0b 100644 --- a/app/src/page/home/coalition/home.coalition.service.ts +++ b/app/src/page/home/coalition/home.coalition.service.ts @@ -3,6 +3,7 @@ import { scoreDateRangeFilter } from 'src/api/score/db/score.database.aggregate' import { ScoreCacheService } from 'src/api/score/score.cache.service'; import { ScoreService } from 'src/api/score/score.service'; import { CacheOnReturn } from 'src/cache/decrators/onReturn/cache.decorator.onReturn.symbol'; +import { assertExist } from 'src/common/assertExist'; import type { IntRecord } from 'src/common/models/common.valueRecord.model'; import { DateRangeService } from 'src/dateRange/dateRange.service'; import { DateRange, DateTemplate } from 'src/dateRange/dtos/dateRange.dto'; @@ -86,17 +87,10 @@ export class HomeCoalitionService { return this.dateRangeService.toDateRanged(tigCountPerCoalition, dateRange); } - @CacheOnReturn() async winCountPerCoalition(): Promise { - const currmonth = new DateWrapper().startOfMonth(); - - const dateRange: DateRange = { - ...this.dateRangeService.dateRangeFromTemplate(DateTemplate.TOTAL), - end: currmonth.toDate(), - }; + const cached = await this.scoreCacheService.getWinCountPerCoalition(); + assertExist(cached); - return await this.scoreService.winCountPerCoalition({ - filter: scoreDateRangeFilter(dateRange), - }); + return cached; } } diff --git a/app/src/page/home/coalition/models/home.coalition.model.ts b/app/src/page/home/coalition/models/home.coalition.model.ts index 2c095beb..c43fc18f 100644 --- a/app/src/page/home/coalition/models/home.coalition.model.ts +++ b/app/src/page/home/coalition/models/home.coalition.model.ts @@ -1,5 +1,5 @@ import { Field, ObjectType } from '@nestjs/graphql'; -import { Coalition } from 'src/api/coalition/models/coalition.model'; +import { Coalition } from 'src/page/common/models/coalition.model'; import { IntRecord } from 'src/common/models/common.valueRecord.model'; import { ArrayDateRanged } from 'src/dateRange/models/dateRange.model'; diff --git a/app/src/page/personal/general/character/personal.general.character.pokemon.ts b/app/src/page/personal/general/character/personal.general.character.pokemon.ts index fa76ca88..b83262c4 100644 --- a/app/src/page/personal/general/character/personal.general.character.pokemon.ts +++ b/app/src/page/personal/general/character/personal.general.character.pokemon.ts @@ -1,5 +1,5 @@ import { InternalServerErrorException } from '@nestjs/common'; -import type { Coalition } from 'src/api/coalition/models/coalition.model'; +import type { Coalition } from 'src/page/common/models/coalition.model'; export type PokemonType = { readonly name: string; diff --git a/app/src/page/personal/general/models/personal.general.userProfile.model.ts b/app/src/page/personal/general/models/personal.general.userProfile.model.ts index 5fd3b138..1c4d7bc5 100644 --- a/app/src/page/personal/general/models/personal.general.userProfile.model.ts +++ b/app/src/page/personal/general/models/personal.general.userProfile.model.ts @@ -1,5 +1,5 @@ import { Field, Float, ObjectType } from '@nestjs/graphql'; -import { Coalition } from 'src/api/coalition/models/coalition.model'; +import { Coalition } from 'src/page/common/models/coalition.model'; @ObjectType() export class UserTitle { diff --git a/app/src/schema.gql b/app/src/schema.gql index 08480350..9d24f43d 100644 --- a/app/src/schema.gql +++ b/app/src/schema.gql @@ -43,14 +43,15 @@ type ProjectPreview { type Coalition { id: Int! name: String! - slug: String! - imageUrl: String! + slug: String! @deprecated(reason: "deprecated at v0.9.0") + imageUrl: String! @deprecated(reason: "deprecated at v0.9.0, imgUrl 을 사용하세요.") + imgUrl: String! coverUrl: String! color: String! - score: Int! + score: Int! @deprecated(reason: "deprecated at v0.9.0") """코알리숑 마스터의 user id 입니다.""" - userId: Int! + userId: Int! @deprecated(reason: "deprecated at v0.9.0") } type UserTitle { From fffe3318b0c32e9d91489ba8a77c943b8bd6846e Mon Sep 17 00:00:00 2001 From: jaham Date: Sun, 29 Oct 2023 23:42:11 +0900 Subject: [PATCH 2/3] =?UTF-8?q?feat:=20:sparkles:=20leaderboard=20metadata?= =?UTF-8?q?=20=EC=97=90=20coalitionList=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - #378 --- app/src/api/coalition/coalition.service.ts | 11 +++++++++++ .../leaderboard/common/models/leaderboard.model.ts | 3 +-- .../metadata/leaderboard.metadata.module.ts | 5 +++-- .../metadata/leaderboard.metadata.resolver.ts | 8 +++++++- .../metadata/leaderboard.metadata.service.ts | 11 ++++++++++- .../metadata/models/leaderboard.metadata.model.ts | 4 ++++ app/src/schema.gql | 1 + 7 files changed, 37 insertions(+), 6 deletions(-) diff --git a/app/src/api/coalition/coalition.service.ts b/app/src/api/coalition/coalition.service.ts index c8a3b548..44d19d55 100644 --- a/app/src/api/coalition/coalition.service.ts +++ b/app/src/api/coalition/coalition.service.ts @@ -4,6 +4,7 @@ import { InjectModel } from '@nestjs/mongoose'; import type { Aggregate, Model } from 'mongoose'; import { API_CONFIG } from 'src/config/api'; import { CDN_CONFIG } from 'src/config/cdn'; +import { findAllAndLean } from 'src/database/mongoose/database.mongoose.query'; import type { Coalition } from '../../page/common/models/coalition.model'; import { coalition } from './db/coalition.database.schema'; @@ -59,4 +60,14 @@ export class CoalitionService { getSeoulCoalitionIds(): readonly number[] { return this.apiConfig.SEOUL_COALITION_ID; } + + async getSeoulCoalitions(): Promise { + const coalitions = await findAllAndLean(this.coalitionModel, { + filter: { + id: { $in: this.getSeoulCoalitionIds() }, + }, + }); + + return coalitions.map((coalition) => this.daoToDto(coalition)); + } } diff --git a/app/src/page/leaderboard/common/models/leaderboard.model.ts b/app/src/page/leaderboard/common/models/leaderboard.model.ts index cf04a359..51b1f08d 100644 --- a/app/src/page/leaderboard/common/models/leaderboard.model.ts +++ b/app/src/page/leaderboard/common/models/leaderboard.model.ts @@ -1,10 +1,9 @@ -import { Field, InterfaceType, ObjectType } from '@nestjs/graphql'; +import { Field, ObjectType } from '@nestjs/graphql'; import { UserRank, UserRankingIndexPaginated, } from 'src/common/models/common.user.model'; import { DateRanged } from 'src/dateRange/models/dateRange.model'; -import { Promo } from 'src/page/common/models/promo.model'; @ObjectType() export class LeaderboardElement { diff --git a/app/src/page/leaderboard/metadata/leaderboard.metadata.module.ts b/app/src/page/leaderboard/metadata/leaderboard.metadata.module.ts index 4771d837..a48e43a3 100644 --- a/app/src/page/leaderboard/metadata/leaderboard.metadata.module.ts +++ b/app/src/page/leaderboard/metadata/leaderboard.metadata.module.ts @@ -1,10 +1,11 @@ import { Module } from '@nestjs/common'; +import { CoalitionModule } from 'src/api/coalition/coalition.module'; import { PromoModule } from 'src/api/promo/promo.module'; -import { LeaderboardMetadataService } from './leaderboard.metadata.service'; import { LeaderboardMetadataResolver } from './leaderboard.metadata.resolver'; +import { LeaderboardMetadataService } from './leaderboard.metadata.service'; @Module({ - imports: [PromoModule], + imports: [PromoModule, CoalitionModule], providers: [LeaderboardMetadataService, LeaderboardMetadataResolver], }) // eslint-disable-next-line @typescript-eslint/no-extraneous-class diff --git a/app/src/page/leaderboard/metadata/leaderboard.metadata.resolver.ts b/app/src/page/leaderboard/metadata/leaderboard.metadata.resolver.ts index 928f7dec..8e6c2fad 100644 --- a/app/src/page/leaderboard/metadata/leaderboard.metadata.resolver.ts +++ b/app/src/page/leaderboard/metadata/leaderboard.metadata.resolver.ts @@ -2,6 +2,7 @@ import { Query, ResolveField, Resolver } from '@nestjs/graphql'; import { LeaderboardMetadata } from './models/leaderboard.metadata.model'; import { LeaderboardMetadataService } from './leaderboard.metadata.service'; import { Promo } from 'src/page/common/models/promo.model'; +import { Coalition } from 'src/page/common/models/coalition.model'; @Resolver((_of: unknown) => LeaderboardMetadata) export class LeaderboardMetadataResolver { @@ -11,7 +12,7 @@ export class LeaderboardMetadataResolver { @Query((_returns) => LeaderboardMetadata) async getLeaderboardMetadata(): Promise< - Omit + Omit > { return {}; } @@ -20,4 +21,9 @@ export class LeaderboardMetadataResolver { async promoList(): Promise { return await this.leaderboardMetadataService.promoList(); } + + @ResolveField((_returns) => [Coalition]) + async coalitionList(): Promise { + return await this.leaderboardMetadataService.coalitionList(); + } } diff --git a/app/src/page/leaderboard/metadata/leaderboard.metadata.service.ts b/app/src/page/leaderboard/metadata/leaderboard.metadata.service.ts index 6d3151fd..1bf51cfc 100644 --- a/app/src/page/leaderboard/metadata/leaderboard.metadata.service.ts +++ b/app/src/page/leaderboard/metadata/leaderboard.metadata.service.ts @@ -1,12 +1,21 @@ import { Injectable } from '@nestjs/common'; +import { CoalitionService } from 'src/api/coalition/coalition.service'; import { PromoService } from 'src/api/promo/promo.service'; +import type { Coalition } from 'src/page/common/models/coalition.model'; import type { Promo } from 'src/page/common/models/promo.model'; @Injectable() export class LeaderboardMetadataService { - constructor(private readonly promoService: PromoService) {} + constructor( + private readonly promoService: PromoService, + private readonly coalitionService: CoalitionService, + ) {} async promoList(): Promise { return await this.promoService.promoList(); } + + async coalitionList(): Promise { + return await this.coalitionService.getSeoulCoalitions(); + } } diff --git a/app/src/page/leaderboard/metadata/models/leaderboard.metadata.model.ts b/app/src/page/leaderboard/metadata/models/leaderboard.metadata.model.ts index 87214c88..68972095 100644 --- a/app/src/page/leaderboard/metadata/models/leaderboard.metadata.model.ts +++ b/app/src/page/leaderboard/metadata/models/leaderboard.metadata.model.ts @@ -1,8 +1,12 @@ import { Field, ObjectType } from '@nestjs/graphql'; +import { Coalition } from 'src/page/common/models/coalition.model'; import { Promo } from 'src/page/common/models/promo.model'; @ObjectType() export class LeaderboardMetadata { @Field((_type) => [Promo]) promoList: Promo[]; + + @Field((_type) => [Coalition]) + coalitionList: Coalition[]; } diff --git a/app/src/schema.gql b/app/src/schema.gql index 9d24f43d..b9c1a8e6 100644 --- a/app/src/schema.gql +++ b/app/src/schema.gql @@ -300,6 +300,7 @@ type Promo { type LeaderboardMetadata { promoList: [Promo!]! + coalitionList: [Coalition!]! } type LeaderboardScore { From 86cb3c70ccf245b16f3ed565035d29f4d04b1633 Mon Sep 17 00:00:00 2001 From: jaham Date: Mon, 30 Oct 2023 02:37:10 +0900 Subject: [PATCH 3/3] =?UTF-8?q?feat:=20:sparkles:=20leaderboard=20?= =?UTF-8?q?=EC=97=90=20coalitionId=20filter=20=EA=B8=B0=EB=8A=A5=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - close #378 --- .../cursusUser/cursusUser.cache.service.ts | 16 ++--- .../experienceUser.cache.service.ts | 16 ++--- .../api/scaleTeam/scaleTeam.cache.service.ts | 32 +++------ app/src/api/score/score.cache.service.ts | 16 ++--- app/src/cache/cache.util.ranking.service.ts | 29 ++++++-- app/src/page/home/user/home.user.service.ts | 12 ++-- .../comment/leaderboard.comment.resolver.ts | 22 +++--- .../comment/leaderboard.comment.service.ts | 11 +-- ...derboard.dto.getLeaderboardElemenetArgs.ts | 6 ++ .../leaderboard.rankingByDateTemplateArgs.ts | 1 + .../eval/leaderboard.eval.resolver.ts | 22 +++--- .../eval/leaderboard.eval.service.ts | 24 ++----- .../exp/leaderboard.exp.resolver.ts | 26 +++---- .../exp/leaderboard.exp.service.ts | 20 ++---- .../level/leaderboard.level.resovler.ts | 22 +++--- .../level/leaderboard.level.service.ts | 30 ++++---- .../score/leaderboard.score.resolver.ts | 22 +++--- .../score/leaderboard.score.service.ts | 24 ++----- .../util/leaderboard.util.service.ts | 24 ++++++- app/src/page/myInfo/myInfo.service.ts | 18 ++--- .../personal.general.character.service.ts | 6 +- .../general/personal.general.service.ts | 8 +-- .../versus/personal.versus.service.ts | 70 ++++++++++--------- app/src/schema.gql | 10 +-- 24 files changed, 245 insertions(+), 242 deletions(-) diff --git a/app/src/api/cursusUser/cursusUser.cache.service.ts b/app/src/api/cursusUser/cursusUser.cache.service.ts index ef34a293..295e4acf 100644 --- a/app/src/api/cursusUser/cursusUser.cache.service.ts +++ b/app/src/api/cursusUser/cursusUser.cache.service.ts @@ -1,6 +1,8 @@ import { Injectable } from '@nestjs/common'; import { CacheUtilRankingService, + type GetRankArgs, + type GetRankingArgs, type RankCache, } from 'src/cache/cache.util.ranking.service'; import { @@ -41,26 +43,20 @@ export class CursusUserCacheService { } async getUserRank( - keyBase: UserRankingKey, - userId: number, - promo?: number, + cacheArgs: Omit, ): Promise { return await this.cacheUtilRankingService.getRawRank({ - keyBase, - userId, dateTemplate: DateTemplate.TOTAL, - promo, + ...cacheArgs, }); } async getUserRanking( - keyBase: UserRankingKey, - promo?: number, + cacheArgs: Omit, ): Promise { return await this.cacheUtilRankingService.getRawRanking({ - keyBase, dateTemplate: DateTemplate.TOTAL, - promo, + ...cacheArgs, }); } } diff --git a/app/src/api/experienceUser/experienceUser.cache.service.ts b/app/src/api/experienceUser/experienceUser.cache.service.ts index 18c601de..49b598e2 100644 --- a/app/src/api/experienceUser/experienceUser.cache.service.ts +++ b/app/src/api/experienceUser/experienceUser.cache.service.ts @@ -1,6 +1,8 @@ import { Injectable } from '@nestjs/common'; import { CacheUtilRankingService, + type GetRankArgs, + type GetRankingArgs, type RankCache, type RankingSupportedDateTemplate, } from 'src/cache/cache.util.ranking.service'; @@ -20,26 +22,20 @@ export class ExperienceUserCacheService { ) {} async getExpIncreamentRank( - dateTemplate: ExpIncreamentRankingCacheSupportedDateTemplate, - userId: number, - promo?: number, + cacheArgs: Omit, ): Promise { return await this.cacheUtilRankingService.getRank({ keyBase: EXP_INCREAMENT_RANKING, - dateTemplate, - userId, - promo, + ...cacheArgs, }); } async getExpIncreamentRanking( - dateTemplate: ExpIncreamentRankingCacheSupportedDateTemplate, - promo?: number, + cacheArgs: Omit, ): Promise { return await this.cacheUtilRankingService.getRanking({ keyBase: EXP_INCREAMENT_RANKING, - dateTemplate, - promo, + ...cacheArgs, }); } } diff --git a/app/src/api/scaleTeam/scaleTeam.cache.service.ts b/app/src/api/scaleTeam/scaleTeam.cache.service.ts index e3895f62..b18fdb8d 100644 --- a/app/src/api/scaleTeam/scaleTeam.cache.service.ts +++ b/app/src/api/scaleTeam/scaleTeam.cache.service.ts @@ -43,18 +43,14 @@ export class ScaleTeamCacheService { ) {} async getEvalCountRank( - dateTemplate: EvalCountRankingSupportedDateTemplate, - userId: number, - promo?: number, + cacheArgs: Omit, ): Promise { const args: GetRankArgs = { keyBase: EVAL_COUNT_RANKING, - userId, - dateTemplate, - promo, + ...cacheArgs, }; - if (dateTemplate === DateTemplate.TOTAL) { + if (cacheArgs.dateTemplate === DateTemplate.TOTAL) { return await this.cacheUtilRankingService.getRawRank(args); } @@ -62,16 +58,14 @@ export class ScaleTeamCacheService { } async getEvalCountRanking( - dateTemplate: EvalCountRankingSupportedDateTemplate, - promo?: number, + cacheArgs: Omit, ): Promise { const args: GetRankingArgs = { keyBase: EVAL_COUNT_RANKING, - dateTemplate, - promo, + ...cacheArgs, }; - if (dateTemplate === DateTemplate.TOTAL) { + if (cacheArgs.dateTemplate === DateTemplate.TOTAL) { return await this.cacheUtilRankingService.getRawRanking(args); } @@ -87,26 +81,20 @@ export class ScaleTeamCacheService { } async getCommentRank( - dateTemplate: AverageReviewLengthRankingSupportedDateTemplate, - userId: number, - promo?: number, + cacheArgs: Omit, ): Promise { return await this.cacheUtilRankingService.getRank({ keyBase: COMMENT_RANKING, - userId, - dateTemplate, - promo, + ...cacheArgs, }); } async getCommentRanking( - dateTemplate: AverageReviewLengthRankingSupportedDateTemplate, - promo?: number, + cacheArgs: Omit, ): Promise { return await this.cacheUtilRankingService.getRanking({ keyBase: COMMENT_RANKING, - dateTemplate, - promo, + ...cacheArgs, }); } } diff --git a/app/src/api/score/score.cache.service.ts b/app/src/api/score/score.cache.service.ts index 7b8760e6..5449388e 100644 --- a/app/src/api/score/score.cache.service.ts +++ b/app/src/api/score/score.cache.service.ts @@ -1,6 +1,8 @@ import { Injectable } from '@nestjs/common'; import { CacheUtilRankingService, + type GetRankArgs, + type GetRankingArgs, type RankCache, type RankingSupportedDateTemplate, } from 'src/cache/cache.util.ranking.service'; @@ -28,26 +30,20 @@ export class ScoreCacheService { ) {} async getScoreRank( - dateTemplate: ScoreRankingSupportedDateTemplate, - userId: number, - promo?: number, + cacheArgs: Omit, ): Promise { return await this.cacheUtilRankingService.getRank({ keyBase: SCORE_RANKING, - userId, - dateTemplate, - promo, + ...cacheArgs, }); } async getScoreRanking( - dateTemplate: ScoreRankingSupportedDateTemplate, - promo?: number, + cacheArgs: Omit, ): Promise { return await this.cacheUtilRankingService.getRanking({ keyBase: SCORE_RANKING, - dateTemplate, - promo, + ...cacheArgs, }); } diff --git a/app/src/cache/cache.util.ranking.service.ts b/app/src/cache/cache.util.ranking.service.ts index 1fd7b0ec..957aacf7 100644 --- a/app/src/cache/cache.util.ranking.service.ts +++ b/app/src/cache/cache.util.ranking.service.ts @@ -29,6 +29,7 @@ export type GetRankingArgs = { keyBase: string; dateTemplate: RankingSupportedDateTemplate; promo?: number; + coalitionId?: number; }; export type GetRankArgs = GetRankingArgs & { userId: number }; @@ -76,6 +77,7 @@ export class CacheUtilRankingService { userId, dateTemplate, promo, + coalitionId, }: GetRankArgs): Promise { const key = this.cacheUtilService.buildKey( keyBase, @@ -91,18 +93,22 @@ export class CacheUtilRankingService { return undefined; } - if (!isPromoMatch({ promo, rankCache })) { + if ( + !isPromoMatch({ promo, rankCache }) || + !isCoalitionMatch({ coalitionId, rankCache }) + ) { return { ...rankCache, rank: 0, }; } - if (promo) { + if (promo || coalitionId) { const rankingCache = await this.getRawRanking({ keyBase, dateTemplate, promo, + coalitionId, }); return rankingCache?.find( @@ -117,6 +123,7 @@ export class CacheUtilRankingService { keyBase, dateTemplate, promo, + coalitionId, }: GetRankingArgs): Promise { const key = this.cacheUtilService.buildKey( keyBase, @@ -131,9 +138,13 @@ export class CacheUtilRankingService { return undefined; } - if (promo) { + if (promo || coalitionId) { return rankingCache - .filter((rankCache) => isPromoMatch({ promo, rankCache })) + .filter( + (rankCache) => + isPromoMatch({ promo, rankCache }) && + isCoalitionMatch({ coalitionId, rankCache }), + ) .reduce( ({ filtered, prevRank, prevValue }, currRankCache, index) => { if (index === 0) { @@ -401,3 +412,13 @@ const isPromoMatch = ({ // todo: nullable schema type 에 대한 처리를 한 후 수정해야 합니다. return !promo || rankCache.promo === promo; }; + +const isCoalitionMatch = ({ + coalitionId, + rankCache, +}: { + coalitionId?: number; + rankCache: RankCache; +}): boolean => { + return !coalitionId || rankCache.coalition?.id === coalitionId; +}; diff --git a/app/src/page/home/user/home.user.service.ts b/app/src/page/home/user/home.user.service.ts index 26630d11..0f9be23c 100644 --- a/app/src/page/home/user/home.user.service.ts +++ b/app/src/page/home/user/home.user.service.ts @@ -140,9 +140,9 @@ export class HomeUserService { } async walletRanking(limit: number): Promise { - const cachedRanking = await this.cursusUserCacheService.getUserRanking( - USER_WALLET_RANKING, - ); + const cachedRanking = await this.cursusUserCacheService.getUserRanking({ + keyBase: USER_WALLET_RANKING, + }); const walletRanking = cachedRanking ? cachedRanking.slice(0, limit) @@ -155,9 +155,9 @@ export class HomeUserService { } async correctionPointRanking(limit: number): Promise { - const cachedRanking = await this.cursusUserCacheService.getUserRanking( - USER_CORRECTION_POINT_RANKING, - ); + const cachedRanking = await this.cursusUserCacheService.getUserRanking({ + keyBase: USER_CORRECTION_POINT_RANKING, + }); return cachedRanking ? cachedRanking.slice(0, limit) diff --git a/app/src/page/leaderboard/comment/leaderboard.comment.resolver.ts b/app/src/page/leaderboard/comment/leaderboard.comment.resolver.ts index 0ccfa470..930287aa 100644 --- a/app/src/page/leaderboard/comment/leaderboard.comment.resolver.ts +++ b/app/src/page/leaderboard/comment/leaderboard.comment.resolver.ts @@ -10,6 +10,7 @@ import { import { HttpExceptionFilter } from 'src/http-exception.filter'; import { GetLeaderboardElementArgs } from '../common/dtos/leaderboard.dto.getLeaderboardElemenetArgs'; import { LeaderboardElementDateRanged } from '../common/models/leaderboard.model'; +import { LeaderboardUtilService } from '../util/leaderboard.util.service'; import { LeaderboardCommentService } from './leaderboard.comment.service'; import { LeaderboardComment } from './models/leaderboard.comment.model'; @@ -19,6 +20,7 @@ import { LeaderboardComment } from './models/leaderboard.comment.model'; export class LeaderboardCommentResolver { constructor( private readonly leaderboardCommentService: LeaderboardCommentService, + private readonly leaderboardUtilService: LeaderboardUtilService, ) {} @Query((_returns) => LeaderboardComment) @@ -28,8 +30,8 @@ export class LeaderboardCommentResolver { @ResolveField((_returns) => LeaderboardElementDateRanged) async byDateTemplate( - @MyUserId() myUserId: number, - @Args() { pageNumber, pageSize, promo }: GetLeaderboardElementArgs, + @MyUserId() userId: number, + @Args() getLeaderboardElementArgs: GetLeaderboardElementArgs, @Args() { dateTemplate }: DateTemplateArgs, ): Promise { if ( @@ -42,14 +44,12 @@ export class LeaderboardCommentResolver { throw new UnsupportedDateTemplate(); } - return await this.leaderboardCommentService.rankingByDateTemplate({ - dateTemplate, - userId: myUserId, - paginationIndexArgs: { - pageNumber, - pageSize, - }, - promo, - }); + return await this.leaderboardCommentService.rankingByDateTemplate( + this.leaderboardUtilService.toLeaderboardServiceArgs({ + userId, + getLeaderboardElementArgs, + dateTemplate, + }), + ); } } diff --git a/app/src/page/leaderboard/comment/leaderboard.comment.service.ts b/app/src/page/leaderboard/comment/leaderboard.comment.service.ts index 6dde26d2..36e70f0d 100644 --- a/app/src/page/leaderboard/comment/leaderboard.comment.service.ts +++ b/app/src/page/leaderboard/comment/leaderboard.comment.service.ts @@ -20,17 +20,20 @@ export class LeaderboardCommentService { userId, paginationIndexArgs, promo, + coalitionId, }: RankingByDateTemplateArgs): Promise { - const rank = await this.scaleTeamCacheService.getCommentRank( + const rank = await this.scaleTeamCacheService.getCommentRank({ dateTemplate, userId, promo, - ); + coalitionId, + }); - const ranking = await this.scaleTeamCacheService.getCommentRanking( + const ranking = await this.scaleTeamCacheService.getCommentRanking({ dateTemplate, promo, - ); + coalitionId, + }); assertExist(ranking); diff --git a/app/src/page/leaderboard/common/dtos/leaderboard.dto.getLeaderboardElemenetArgs.ts b/app/src/page/leaderboard/common/dtos/leaderboard.dto.getLeaderboardElemenetArgs.ts index 35b1f21d..c44e8294 100644 --- a/app/src/page/leaderboard/common/dtos/leaderboard.dto.getLeaderboardElemenetArgs.ts +++ b/app/src/page/leaderboard/common/dtos/leaderboard.dto.getLeaderboardElemenetArgs.ts @@ -9,4 +9,10 @@ export class GetLeaderboardElementArgs extends PaginationIndexArgs { @IsOptional() @Field({ nullable: true }) promo?: number; + + @Min(1) + @Max(1000) + @IsOptional() + @Field({ nullable: true }) + coalitionId?: number; } diff --git a/app/src/page/leaderboard/common/types/leaderboard.rankingByDateTemplateArgs.ts b/app/src/page/leaderboard/common/types/leaderboard.rankingByDateTemplateArgs.ts index f4b398b6..fe0da764 100644 --- a/app/src/page/leaderboard/common/types/leaderboard.rankingByDateTemplateArgs.ts +++ b/app/src/page/leaderboard/common/types/leaderboard.rankingByDateTemplateArgs.ts @@ -7,6 +7,7 @@ export type RankingByDateTemplateArgs< > = { userId: number; promo?: number; + coalitionId?: number; paginationIndexArgs: PaginationIndexArgs; dateTemplate: SupportDateTemplate; }; diff --git a/app/src/page/leaderboard/eval/leaderboard.eval.resolver.ts b/app/src/page/leaderboard/eval/leaderboard.eval.resolver.ts index f85a2685..49a2c68c 100644 --- a/app/src/page/leaderboard/eval/leaderboard.eval.resolver.ts +++ b/app/src/page/leaderboard/eval/leaderboard.eval.resolver.ts @@ -10,6 +10,7 @@ import { import { HttpExceptionFilter } from 'src/http-exception.filter'; import { GetLeaderboardElementArgs } from '../common/dtos/leaderboard.dto.getLeaderboardElemenetArgs'; import { LeaderboardElementDateRanged } from '../common/models/leaderboard.model'; +import { LeaderboardUtilService } from '../util/leaderboard.util.service'; import { LeaderboardEvalService } from './leaderboard.eval.service'; import { LeaderboardEval } from './models/leaderboard.eval.model'; @@ -19,6 +20,7 @@ import { LeaderboardEval } from './models/leaderboard.eval.model'; export class LeaderboardEvalResolver { constructor( private readonly leaderboardEvalService: LeaderboardEvalService, + private readonly leaderboardUtilService: LeaderboardUtilService, ) {} @Query((_returns) => LeaderboardEval) @@ -28,8 +30,8 @@ export class LeaderboardEvalResolver { @ResolveField((_returns) => LeaderboardElementDateRanged) async byDateTemplate( - @MyUserId() myUserId: number, - @Args() { pageSize, pageNumber, promo }: GetLeaderboardElementArgs, + @MyUserId() userId: number, + @Args() getLeaderboardElementArgs: GetLeaderboardElementArgs, @Args() { dateTemplate }: DateTemplateArgs, ): Promise { if ( @@ -42,14 +44,12 @@ export class LeaderboardEvalResolver { throw new UnsupportedDateTemplate(); } - return await this.leaderboardEvalService.rankingByDateTemplate({ - dateTemplate, - userId: myUserId, - paginationIndexArgs: { - pageSize, - pageNumber, - }, - promo, - }); + return await this.leaderboardEvalService.rankingByDateTemplate( + this.leaderboardUtilService.toLeaderboardServiceArgs({ + userId, + getLeaderboardElementArgs, + dateTemplate, + }), + ); } } diff --git a/app/src/page/leaderboard/eval/leaderboard.eval.service.ts b/app/src/page/leaderboard/eval/leaderboard.eval.service.ts index 3e200d9c..e792a0b8 100644 --- a/app/src/page/leaderboard/eval/leaderboard.eval.service.ts +++ b/app/src/page/leaderboard/eval/leaderboard.eval.service.ts @@ -3,7 +3,6 @@ import { ScaleTeamCacheService, type EvalCountRankingSupportedDateTemplate, } from 'src/api/scaleTeam/scaleTeam.cache.service'; -import { ScaleTeamService } from 'src/api/scaleTeam/scaleTeam.service'; import { assertExist } from 'src/common/assertExist'; import type { LeaderboardElementDateRanged } from '../common/models/leaderboard.model'; import type { RankingByDateTemplateArgs } from '../common/types/leaderboard.rankingByDateTemplateArgs'; @@ -13,25 +12,16 @@ import { LeaderboardUtilService } from '../util/leaderboard.util.service'; export class LeaderboardEvalService { constructor( private readonly leaderboardUtilService: LeaderboardUtilService, - private readonly scaleTeamService: ScaleTeamService, private readonly scaleTeamCacheService: ScaleTeamCacheService, ) {} - async rankingByDateTemplate({ - dateTemplate, - userId, - paginationIndexArgs, - promo, - }: RankingByDateTemplateArgs): Promise { - const rank = await this.scaleTeamCacheService.getEvalCountRank( - dateTemplate, - userId, - promo, - ); + async rankingByDateTemplate( + rankingArgs: RankingByDateTemplateArgs, + ): Promise { + const rank = await this.scaleTeamCacheService.getEvalCountRank(rankingArgs); const ranking = await this.scaleTeamCacheService.getEvalCountRanking( - dateTemplate, - promo, + rankingArgs, ); assertExist(ranking); @@ -39,8 +29,8 @@ export class LeaderboardEvalService { return this.leaderboardUtilService.toLeaderboardElementDateRanged({ rank, ranking, - paginationIndexArgs, - dateTemplate, + paginationIndexArgs: rankingArgs.paginationIndexArgs, + dateTemplate: rankingArgs.dateTemplate, }); } } diff --git a/app/src/page/leaderboard/exp/leaderboard.exp.resolver.ts b/app/src/page/leaderboard/exp/leaderboard.exp.resolver.ts index fec0c38d..71bf3fe3 100644 --- a/app/src/page/leaderboard/exp/leaderboard.exp.resolver.ts +++ b/app/src/page/leaderboard/exp/leaderboard.exp.resolver.ts @@ -10,6 +10,7 @@ import { import { HttpExceptionFilter } from 'src/http-exception.filter'; import { GetLeaderboardElementArgs } from '../common/dtos/leaderboard.dto.getLeaderboardElemenetArgs'; import { LeaderboardElementDateRanged } from '../common/models/leaderboard.model'; +import { LeaderboardUtilService } from '../util/leaderboard.util.service'; import { LeaderboardExpService } from './leaderboard.exp.service'; import { LeaderboardExp } from './models/leaderboard.exp.model'; @@ -17,7 +18,10 @@ import { LeaderboardExp } from './models/leaderboard.exp.model'; @UseGuards(StatAuthGuard) @Resolver((_of: unknown) => LeaderboardExp) export class LeaderboardExpResolver { - constructor(private readonly leaderboardExpService: LeaderboardExpService) {} + constructor( + private readonly leaderboardExpService: LeaderboardExpService, + private readonly leaderboardUtilService: LeaderboardUtilService, + ) {} @Query((_returns) => LeaderboardExp) async getLeaderboardExpIncrement() { @@ -26,8 +30,8 @@ export class LeaderboardExpResolver { @ResolveField((_returns) => LeaderboardElementDateRanged) async byDateTemplate( - @MyUserId() myUserId: number, - @Args() { pageNumber, pageSize, promo }: GetLeaderboardElementArgs, + @MyUserId() userId: number, + @Args() getLeaderboardElementArgs: GetLeaderboardElementArgs, @Args() { dateTemplate }: DateTemplateArgs, ): Promise { if ( @@ -39,14 +43,12 @@ export class LeaderboardExpResolver { throw new UnsupportedDateTemplate(); } - return await this.leaderboardExpService.rankingByDateTemplate({ - dateTemplate, - userId: myUserId, - paginationIndexArgs: { - pageNumber, - pageSize, - }, - promo, - }); + return await this.leaderboardExpService.rankingByDateTemplate( + this.leaderboardUtilService.toLeaderboardServiceArgs({ + userId, + getLeaderboardElementArgs, + dateTemplate, + }), + ); } } diff --git a/app/src/page/leaderboard/exp/leaderboard.exp.service.ts b/app/src/page/leaderboard/exp/leaderboard.exp.service.ts index 18801aa9..74175274 100644 --- a/app/src/page/leaderboard/exp/leaderboard.exp.service.ts +++ b/app/src/page/leaderboard/exp/leaderboard.exp.service.ts @@ -15,22 +15,16 @@ export class LeaderboardExpService { private readonly experienceUserCacheService: ExperienceUserCacheService, ) {} - async rankingByDateTemplate({ - dateTemplate, - userId, - paginationIndexArgs, - promo, - }: RankingByDateTemplateArgs): Promise { + async rankingByDateTemplate( + rankingArgs: RankingByDateTemplateArgs, + ): Promise { const rank = await this.experienceUserCacheService.getExpIncreamentRank( - dateTemplate, - userId, - promo, + rankingArgs, ); const ranking = await this.experienceUserCacheService.getExpIncreamentRanking( - dateTemplate, - promo, + rankingArgs, ); assertExist(ranking); @@ -38,8 +32,8 @@ export class LeaderboardExpService { return this.leaderboardUtilService.toLeaderboardElementDateRanged({ rank, ranking, - paginationIndexArgs, - dateTemplate, + paginationIndexArgs: rankingArgs.paginationIndexArgs, + dateTemplate: rankingArgs.dateTemplate, }); } } diff --git a/app/src/page/leaderboard/level/leaderboard.level.resovler.ts b/app/src/page/leaderboard/level/leaderboard.level.resovler.ts index bdbafd7c..38672198 100644 --- a/app/src/page/leaderboard/level/leaderboard.level.resovler.ts +++ b/app/src/page/leaderboard/level/leaderboard.level.resovler.ts @@ -10,6 +10,7 @@ import { import { HttpExceptionFilter } from 'src/http-exception.filter'; import { GetLeaderboardElementArgs } from '../common/dtos/leaderboard.dto.getLeaderboardElemenetArgs'; import { LeaderboardElementDateRanged } from '../common/models/leaderboard.model'; +import { LeaderboardUtilService } from '../util/leaderboard.util.service'; import { LeaderboardLevelService } from './leaderboard.level.service'; import { LeaderboardLevel } from './models/leaderboard.level.model'; @@ -19,6 +20,7 @@ import { LeaderboardLevel } from './models/leaderboard.level.model'; export class LeaderboardLevelResolver { constructor( private readonly leaderboardLevelService: LeaderboardLevelService, + private readonly leaderboardUtilService: LeaderboardUtilService, ) {} @Query((_returns) => LeaderboardLevel) @@ -28,22 +30,20 @@ export class LeaderboardLevelResolver { @ResolveField((_returns) => LeaderboardElementDateRanged) async byDateTemplate( - @MyUserId() myUserId: number, - @Args() { pageSize, pageNumber, promo }: GetLeaderboardElementArgs, + @MyUserId() userId: number, + @Args() getLeaderboardElementArgs: GetLeaderboardElementArgs, @Args() { dateTemplate }: DateTemplateArgs, ): Promise { if (dateTemplate !== DateTemplate.TOTAL) { throw new UnsupportedDateTemplate(); } - return await this.leaderboardLevelService.rankingByDateTemplate({ - dateTemplate, - userId: myUserId, - paginationIndexArgs: { - pageSize, - pageNumber, - }, - promo, - }); + return await this.leaderboardLevelService.rankingByDateTemplate( + this.leaderboardUtilService.toLeaderboardServiceArgs({ + userId, + getLeaderboardElementArgs, + dateTemplate, + }), + ); } } diff --git a/app/src/page/leaderboard/level/leaderboard.level.service.ts b/app/src/page/leaderboard/level/leaderboard.level.service.ts index f0c943b6..e9dc81a2 100644 --- a/app/src/page/leaderboard/level/leaderboard.level.service.ts +++ b/app/src/page/leaderboard/level/leaderboard.level.service.ts @@ -16,30 +16,26 @@ export class LeaderboardLevelService { private readonly cursusUserCacheService: CursusUserCacheService, ) {} - async rankingByDateTemplate({ - dateTemplate, - userId, - paginationIndexArgs, - promo, - }: RankingByDateTemplateArgs): Promise { - const rank = await this.cursusUserCacheService.getUserRank( - USER_LEVEL_RANKING, - userId, - promo, - ); + async rankingByDateTemplate( + rankingArgs: RankingByDateTemplateArgs, + ): Promise { + const rank = await this.cursusUserCacheService.getUserRank({ + keyBase: USER_LEVEL_RANKING, + ...rankingArgs, + }); - const ranking = await this.cursusUserCacheService.getUserRanking( - USER_LEVEL_RANKING, - promo, - ); + const ranking = await this.cursusUserCacheService.getUserRanking({ + keyBase: USER_LEVEL_RANKING, + ...rankingArgs, + }); assertExist(ranking); return this.leaderboardUtilService.toLeaderboardElementDateRanged({ rank, ranking, - paginationIndexArgs, - dateTemplate, + paginationIndexArgs: rankingArgs.paginationIndexArgs, + dateTemplate: rankingArgs.dateTemplate, }); } } diff --git a/app/src/page/leaderboard/score/leaderboard.score.resolver.ts b/app/src/page/leaderboard/score/leaderboard.score.resolver.ts index 448fcc57..449ae013 100644 --- a/app/src/page/leaderboard/score/leaderboard.score.resolver.ts +++ b/app/src/page/leaderboard/score/leaderboard.score.resolver.ts @@ -10,6 +10,7 @@ import { import { HttpExceptionFilter } from 'src/http-exception.filter'; import { GetLeaderboardElementArgs } from '../common/dtos/leaderboard.dto.getLeaderboardElemenetArgs'; import { LeaderboardElementDateRanged } from '../common/models/leaderboard.model'; +import { LeaderboardUtilService } from '../util/leaderboard.util.service'; import { LeaderboardScoreService } from './leaderboard.score.service'; import { LeaderboardScore } from './models/leaderboard.score.model'; @@ -19,6 +20,7 @@ import { LeaderboardScore } from './models/leaderboard.score.model'; export class LeaderboardScoreResolver { constructor( private readonly leaderboardScoreService: LeaderboardScoreService, + private readonly leaderboardUtilService: LeaderboardUtilService, ) {} @Query((_returns) => LeaderboardScore) @@ -28,8 +30,8 @@ export class LeaderboardScoreResolver { @ResolveField((_returns) => LeaderboardElementDateRanged) async byDateTemplate( - @MyUserId() myUserId: number, - @Args() { pageSize, pageNumber, promo }: GetLeaderboardElementArgs, + @MyUserId() userId: number, + @Args() getLeaderboardElementArgs: GetLeaderboardElementArgs, @Args() { dateTemplate }: DateTemplateArgs, ): Promise { if ( @@ -42,14 +44,12 @@ export class LeaderboardScoreResolver { throw new UnsupportedDateTemplate(); } - return await this.leaderboardScoreService.rankingByDateTemplate({ - dateTemplate, - userId: myUserId, - paginationIndexArgs: { - pageSize, - pageNumber, - }, - promo, - }); + return await this.leaderboardScoreService.rankingByDateTemplate( + this.leaderboardUtilService.toLeaderboardServiceArgs({ + userId, + getLeaderboardElementArgs, + dateTemplate, + }), + ); } } diff --git a/app/src/page/leaderboard/score/leaderboard.score.service.ts b/app/src/page/leaderboard/score/leaderboard.score.service.ts index 9389aa6c..5ac60a06 100644 --- a/app/src/page/leaderboard/score/leaderboard.score.service.ts +++ b/app/src/page/leaderboard/score/leaderboard.score.service.ts @@ -15,30 +15,20 @@ export class LeaderboardScoreService { private readonly scoreCacheService: ScoreCacheService, ) {} - async rankingByDateTemplate({ - dateTemplate, - userId, - paginationIndexArgs, - promo, - }: RankingByDateTemplateArgs): Promise { - const rank = await this.scoreCacheService.getScoreRank( - dateTemplate, - userId, - promo, - ); + async rankingByDateTemplate( + rankingArgs: RankingByDateTemplateArgs, + ): Promise { + const rank = await this.scoreCacheService.getScoreRank(rankingArgs); - const ranking = await this.scoreCacheService.getScoreRanking( - dateTemplate, - promo, - ); + const ranking = await this.scoreCacheService.getScoreRanking(rankingArgs); assertExist(ranking); return this.leaderboardUtilService.toLeaderboardElementDateRanged({ rank, ranking, - paginationIndexArgs, - dateTemplate, + paginationIndexArgs: rankingArgs.paginationIndexArgs, + dateTemplate: rankingArgs.dateTemplate, }); } } diff --git a/app/src/page/leaderboard/util/leaderboard.util.service.ts b/app/src/page/leaderboard/util/leaderboard.util.service.ts index e7a79d47..24c64b5d 100644 --- a/app/src/page/leaderboard/util/leaderboard.util.service.ts +++ b/app/src/page/leaderboard/util/leaderboard.util.service.ts @@ -4,8 +4,9 @@ import type { RankingSupportedDateTemplate, } from 'src/cache/cache.util.ranking.service'; import { DateRangeService } from 'src/dateRange/dateRange.service'; -import { DateTemplate } from 'src/dateRange/dtos/dateRange.dto'; +import type { DateTemplate } from 'src/dateRange/dtos/dateRange.dto'; import { PaginationIndexService } from 'src/pagination/index/pagination.index.service'; +import type { GetLeaderboardElementArgs } from '../common/dtos/leaderboard.dto.getLeaderboardElemenetArgs'; import type { LeaderboardElement, LeaderboardElementDateRanged, @@ -57,4 +58,25 @@ export class LeaderboardUtilService { return this.dateRangeService.toDateRanged(leaderboardElement, dateRange); } + + toLeaderboardServiceArgs({ + userId, + getLeaderboardElementArgs, + dateTemplate, + }: { + userId: number; + getLeaderboardElementArgs: GetLeaderboardElementArgs; + dateTemplate: T; + }): RankingByDateTemplateArgs { + return { + dateTemplate, + userId, + paginationIndexArgs: { + pageSize: getLeaderboardElementArgs.pageSize, + pageNumber: getLeaderboardElementArgs.pageNumber, + }, + promo: getLeaderboardElementArgs.promo, + coalitionId: getLeaderboardElementArgs.coalitionId, + }; + } } diff --git a/app/src/page/myInfo/myInfo.service.ts b/app/src/page/myInfo/myInfo.service.ts index f1e1e92a..622ae502 100644 --- a/app/src/page/myInfo/myInfo.service.ts +++ b/app/src/page/myInfo/myInfo.service.ts @@ -170,28 +170,28 @@ export class MyInfoService { async experienceRank(userId: number): Promise { const cachedRank = - await this.experienceUserCacheService.getExpIncreamentRank( - DateTemplate.CURR_WEEK, + await this.experienceUserCacheService.getExpIncreamentRank({ + dateTemplate: DateTemplate.CURR_WEEK, userId, - ); + }); return cachedRank?.rank; } async scoreRank(userId: number): Promise { - const cachedRank = await this.scoreCacheService.getScoreRank( - DateTemplate.CURR_WEEK, + const cachedRank = await this.scoreCacheService.getScoreRank({ + dateTemplate: DateTemplate.CURR_WEEK, userId, - ); + }); return cachedRank?.rank; } async evalCountRank(userId: number): Promise { - const cachedRanking = await this.scaleTeamCacheService.getEvalCountRank( - DateTemplate.CURR_WEEK, + const cachedRanking = await this.scaleTeamCacheService.getEvalCountRank({ + dateTemplate: DateTemplate.CURR_WEEK, userId, - ); + }); return cachedRanking?.rank; } diff --git a/app/src/page/personal/general/character/personal.general.character.service.ts b/app/src/page/personal/general/character/personal.general.character.service.ts index 00f7344d..75776a00 100644 --- a/app/src/page/personal/general/character/personal.general.character.service.ts +++ b/app/src/page/personal/general/character/personal.general.character.service.ts @@ -155,10 +155,10 @@ export class PersonalGeneralCharacterService { (projectUser) => isExam(projectUser.project.id), ); - const evalCountRank = await this.scaleTeamCacheService.getEvalCountRank( - DateTemplate.TOTAL, + const evalCountRank = await this.scaleTeamCacheService.getEvalCountRank({ + dateTemplate: DateTemplate.TOTAL, userId, - ); + }); if (!evalCountRank) { return null; diff --git a/app/src/page/personal/general/personal.general.service.ts b/app/src/page/personal/general/personal.general.service.ts index b8ec8a3b..1f0946fd 100644 --- a/app/src/page/personal/general/personal.general.service.ts +++ b/app/src/page/personal/general/personal.general.service.ts @@ -82,9 +82,9 @@ export class PersonalGeneralService { async scoreInfo(userId: number): Promise { const dateTemplate = DateTemplate.CURR_MONTH; - const scoreRankingCache = await this.scoreCacheService.getScoreRanking( + const scoreRankingCache = await this.scoreCacheService.getScoreRanking({ dateTemplate, - ); + }); const dateRange = this.dateRangeService.dateRangeFromTemplate(dateTemplate); @@ -99,10 +99,10 @@ export class PersonalGeneralService { ); if (!me) { - const filtered = await this.scoreCacheService.getScoreRank( + const filtered = await this.scoreCacheService.getScoreRank({ dateTemplate, userId, - ); + }); if (!filtered) { throw new NotFoundException(); diff --git a/app/src/page/personal/versus/personal.versus.service.ts b/app/src/page/personal/versus/personal.versus.service.ts index ca9706d4..185f3303 100644 --- a/app/src/page/personal/versus/personal.versus.service.ts +++ b/app/src/page/personal/versus/personal.versus.service.ts @@ -23,64 +23,66 @@ export class PersonalVersusService { async personalVersus(userId: number): Promise { try { - const levelRanking = await this.cursusUserCacheService.getUserRanking( - USER_LEVEL_RANKING, - ); + const levelRanking = await this.cursusUserCacheService.getUserRanking({ + keyBase: USER_LEVEL_RANKING, + }); - const levelRank = await this.cursusUserCacheService.getUserRank( - USER_LEVEL_RANKING, + const levelRank = await this.cursusUserCacheService.getUserRank({ + keyBase: USER_LEVEL_RANKING, userId, - ); + }); - const totalScoreRanking = await this.scoreCacheService.getScoreRanking( - DateTemplate.TOTAL, - ); + const totalScoreRanking = await this.scoreCacheService.getScoreRanking({ + dateTemplate: DateTemplate.TOTAL, + }); - const totalScoreRank = await this.scoreCacheService.getScoreRank( - DateTemplate.TOTAL, + const totalScoreRank = await this.scoreCacheService.getScoreRank({ + dateTemplate: DateTemplate.TOTAL, userId, - ); + }); const totalEvalCountRanking = - await this.scaleTeamCacheService.getEvalCountRanking( - DateTemplate.TOTAL, - ); + await this.scaleTeamCacheService.getEvalCountRanking({ + dateTemplate: DateTemplate.TOTAL, + }); const totalEvalCountRank = - await this.scaleTeamCacheService.getEvalCountRank( - DateTemplate.TOTAL, + await this.scaleTeamCacheService.getEvalCountRank({ + dateTemplate: DateTemplate.TOTAL, userId, - ); + }); const currMonthExpIncreamentRanking = - await this.experienceUserCacheService.getExpIncreamentRanking( - DateTemplate.CURR_MONTH, - ); + await this.experienceUserCacheService.getExpIncreamentRanking({ + dateTemplate: DateTemplate.CURR_MONTH, + }); const currMonthExpIncreamentRank = - await this.experienceUserCacheService.getExpIncreamentRank( - DateTemplate.CURR_MONTH, + await this.experienceUserCacheService.getExpIncreamentRank({ + dateTemplate: DateTemplate.CURR_MONTH, userId, - ); + }); const currMonthScoreRanking = - await this.scoreCacheService.getScoreRanking(DateTemplate.CURR_MONTH); + await this.scoreCacheService.getScoreRanking({ + dateTemplate: DateTemplate.CURR_MONTH, + }); - const currMonthScoreRank = await this.scoreCacheService.getScoreRank( - DateTemplate.CURR_MONTH, + const currMonthScoreRank = await this.scoreCacheService.getScoreRank({ + dateTemplate: DateTemplate.CURR_MONTH, userId, - ); + }); const currMonthEvalCountRanking = - await this.scaleTeamCacheService.getEvalCountRanking( - DateTemplate.CURR_MONTH, - ); + await this.scaleTeamCacheService.getEvalCountRanking({ + dateTemplate: DateTemplate.CURR_MONTH, + }); const currMonthEvalCountRank = - await this.scaleTeamCacheService.getEvalCountRank( - DateTemplate.CURR_MONTH, + await this.scaleTeamCacheService.getEvalCountRank({ + dateTemplate: DateTemplate.CURR_MONTH, userId, - ); + }); const totalLogtimeRank = await this.locationCacheService.getLogtimeRank( DateTemplate.TOTAL, diff --git a/app/src/schema.gql b/app/src/schema.gql index b9c1a8e6..0a046e6a 100644 --- a/app/src/schema.gql +++ b/app/src/schema.gql @@ -274,22 +274,22 @@ type LeaderboardElementDateRanged { type LeaderboardComment { """TOTAL, CURR_MONTH, CURR_WEEK 만 가능합니다""" - byDateTemplate(pageSize: Int! = 10, pageNumber: Int! = 1, promo: Int, dateTemplate: DateTemplate!): LeaderboardElementDateRanged! + byDateTemplate(pageSize: Int! = 10, pageNumber: Int! = 1, promo: Int, coalitionId: Int, dateTemplate: DateTemplate!): LeaderboardElementDateRanged! } type LeaderboardEval { """TOTAL, CURR_MONTH, CURR_WEEK 만 가능합니다""" - byDateTemplate(pageSize: Int! = 10, pageNumber: Int! = 1, promo: Int, dateTemplate: DateTemplate!): LeaderboardElementDateRanged! + byDateTemplate(pageSize: Int! = 10, pageNumber: Int! = 1, promo: Int, coalitionId: Int, dateTemplate: DateTemplate!): LeaderboardElementDateRanged! } type LeaderboardExp { """CURR_MONTH, CURR_WEEK 만 가능합니다""" - byDateTemplate(pageSize: Int! = 10, pageNumber: Int! = 1, promo: Int, dateTemplate: DateTemplate!): LeaderboardElementDateRanged! + byDateTemplate(pageSize: Int! = 10, pageNumber: Int! = 1, promo: Int, coalitionId: Int, dateTemplate: DateTemplate!): LeaderboardElementDateRanged! } type LeaderboardLevel { """TOTAL 만 가능합니다""" - byDateTemplate(pageSize: Int! = 10, pageNumber: Int! = 1, promo: Int, dateTemplate: DateTemplate!): LeaderboardElementDateRanged! + byDateTemplate(pageSize: Int! = 10, pageNumber: Int! = 1, promo: Int, coalitionId: Int, dateTemplate: DateTemplate!): LeaderboardElementDateRanged! } type Promo { @@ -305,7 +305,7 @@ type LeaderboardMetadata { type LeaderboardScore { """TOTAL, CURR_WEEK, CURR_MONTH 만 가능합니다""" - byDateTemplate(pageSize: Int! = 10, pageNumber: Int! = 1, promo: Int, dateTemplate: DateTemplate!): LeaderboardElementDateRanged! + byDateTemplate(pageSize: Int! = 10, pageNumber: Int! = 1, promo: Int, coalitionId: Int, dateTemplate: DateTemplate!): LeaderboardElementDateRanged! } type CharacterType {