Skip to content

Commit

Permalink
feat: ✨ blackholed user record last 증가
Browse files Browse the repository at this point in the history
  • Loading branch information
jpham005 committed Nov 14, 2023
1 parent f01f2f9 commit ed9d4f7
Show file tree
Hide file tree
Showing 4 changed files with 81 additions and 50 deletions.
37 changes: 31 additions & 6 deletions app/src/page/home/user/home.user.resolver.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
import { UseFilters, UseGuards } from '@nestjs/common';
import { Args, Query, ResolveField, Resolver } from '@nestjs/graphql';
import { StatAuthGuard } from 'src/auth/statAuthGuard';
import { CacheUtilService } from 'src/cache/cache.util.service';
import { Rate } from 'src/common/models/common.rate.model';
import { UserRank } from 'src/common/models/common.user.model';
import { IntRecord } from 'src/common/models/common.valueRecord.model';
import { DateWrapper } from 'src/dateWrapper/dateWrapper';
import { HttpExceptionFilter } from 'src/http-exception.filter';
import { HomeUserService } from './home.user.service';
import {
GetHomeUserBlackholedCountRecordsArgs,
HomeUser,
IntPerCircle,
UserCountPerLevel,
Expand All @@ -16,7 +19,10 @@ import {
@UseGuards(StatAuthGuard)
@Resolver((_of: unknown) => HomeUser)
export class HomeUserResolver {
constructor(private readonly homeUserService: HomeUserService) {}
constructor(
private readonly homeUserService: HomeUserService,
private readonly cacheUtilService: CacheUtilService,
) {}

@Query((_of) => HomeUser)
async getHomeUser() {
Expand All @@ -43,13 +49,32 @@ export class HomeUserResolver {
return await this.homeUserService.blackholedRate();
}

@ResolveField((_returns) => [IntRecord], { description: '1 ~ 24 개월' })
@ResolveField((_returns) => [IntRecord], {
description: '1 ~ 120 개월',
})
async blackholedCountRecords(
@Args('last') last: number,
@Args() { last }: GetHomeUserBlackholedCountRecordsArgs,
): Promise<IntRecord[]> {
return await this.homeUserService.blackholedCountRecords(
Math.max(1, Math.min(last, 24)),
);
const nextMonth = DateWrapper.nextMonth().toDate();
const start = DateWrapper.currMonth()
.moveMonth(1 - last)
.toDate();

const cacheKey = `homeUserBlackholedCountRecords:${start.getTime()}:${nextMonth.getTime()}`;

const cached = await this.cacheUtilService.get<IntRecord[]>(cacheKey);
if (cached) {
return cached;
}

const result = await this.homeUserService.blackholedCountRecords({
start,
end: nextMonth,
});

await this.cacheUtilService.set(cacheKey, result);

return result;
}

@ResolveField((_returns) => [IntPerCircle])
Expand Down
79 changes: 37 additions & 42 deletions app/src/page/home/user/home.user.service.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { Injectable } from '@nestjs/common';
import { Inject, Injectable } from '@nestjs/common';
import type { ConfigType } from '@nestjs/config';
import {
CursusUserCacheService,
USER_CORRECTION_POINT_RANKING,
Expand All @@ -16,7 +17,7 @@ import { assertExist } from 'src/common/assertExist';
import type { Rate } from 'src/common/models/common.rate.model';
import type { UserRank } from 'src/common/models/common.user.model';
import type { IntRecord } from 'src/common/models/common.valueRecord.model';
import { DateRangeService } from 'src/dateRange/dateRange.service';
import { RUNTIME_CONFIG } from 'src/config/runtime';
import type { DateRange } from 'src/dateRange/dtos/dateRange.dto';
import { DateWrapper } from 'src/dateWrapper/dateWrapper';
import type { IntPerCircle, UserCountPerLevel } from './models/home.user.model';
Expand All @@ -27,7 +28,8 @@ export class HomeUserService {
private readonly cursusUserService: CursusUserService,
private readonly cursusUserCacheService: CursusUserCacheService,
private readonly questsUserService: QuestsUserService,
private readonly dateRangeService: DateRangeService,
@Inject(RUNTIME_CONFIG.KEY)
private readonly runtimeConfig: ConfigType<typeof RUNTIME_CONFIG>,
) {}

@CacheOnReturn()
Expand Down Expand Up @@ -90,46 +92,39 @@ export class HomeUserService {
};
}

@CacheOnReturn()
async blackholedCountRecords(last: number): Promise<IntRecord[]> {
const startDate = new DateWrapper()
.startOfMonth()
.moveMonth(1 - last)
.toDate();

const blackholeds: { blackholedAt?: Date }[] =
await this.cursusUserService.findAllAndLean({
filter: blackholedUserFilterByDateRange({
start: startDate,
end: new Date(),
}),
select: { blackholedAt: 1 },
async blackholedCountRecords({
start,
end,
}: DateRange): Promise<IntRecord[]> {
return await this.cursusUserService
.aggregate<IntRecord>()
.match(blackholedUserFilterByDateRange({ start, end }))
.group({
_id: {
$dateFromParts: {
year: {
$year: {
date: '$blackholedAt',
timezone: this.runtimeConfig.TIMEZONE,
},
},
month: {
$month: {
date: '$blackholedAt',
timezone: this.runtimeConfig.TIMEZONE,
},
},
timezone: this.runtimeConfig.TIMEZONE,
},
},
count: { $count: {} },
})
.sort({ _id: 1 })
.project({
_id: 0,
at: '$_id',
value: '$count',
});

const res = blackholeds.reduce((acc, { blackholedAt }) => {
assertExist(blackholedAt);

const date = new DateWrapper(blackholedAt)
.startOfMonth()
.toDate()
.getTime();

const prev = acc.get(date);

acc.set(date, (prev ?? 0) + 1);

return acc;
}, new Map() as Map<number, number>);

const records: IntRecord[] = [];

for (let i = 0; i < last; i++) {
const currDate = new DateWrapper(startDate).moveMonth(i).toDate();

records.push({ at: currDate, value: res.get(currDate.getTime()) ?? 0 });
}

return records;
}

@CacheOnReturn()
Expand Down
13 changes: 11 additions & 2 deletions app/src/page/home/user/models/home.user.model.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { Field, ObjectType } from '@nestjs/graphql';
import { ArgsType, Field, ObjectType } from '@nestjs/graphql';
import { Max, Min } from 'class-validator';
import { Rate } from 'src/common/models/common.rate.model';
import { UserRank } from 'src/common/models/common.user.model';
import { IntRecord } from 'src/common/models/common.valueRecord.model';
Expand Down Expand Up @@ -35,7 +36,7 @@ export class HomeUser {
@Field()
blackholedRate: Rate;

@Field((_type) => [IntRecord])
@Field((_type) => [IntRecord], { description: '1 ~ 120 개월' })
blackholedCountRecords: IntRecord[];

@Field((_type) => [IntPerCircle])
Expand All @@ -50,3 +51,11 @@ export class HomeUser {
@Field((_type) => [IntPerCircle])
averageDurationPerCircle: IntPerCircle[];
}

@ArgsType()
export class GetHomeUserBlackholedCountRecordsArgs {
@Min(1)
@Max(120)
@Field()
last: number;
}
2 changes: 2 additions & 0 deletions app/src/schema.gql
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,8 @@ type HomeUser {
userCountPerLevel: [UserCountPerLevel!]!
memberRate: Rate!
blackholedRate: Rate!

"""1 ~ 120 개월"""
blackholedCountRecords(last: Int!): [IntRecord!]!
blackholedCountPerCircle: [IntPerCircle!]!
walletRanking(limit: Int! = 5): [UserRank!]!
Expand Down

0 comments on commit ed9d4f7

Please sign in to comment.