Skip to content

Commit 562845b

Browse files
committed
refactor: 리더보드의 시간 관련 연산 모두 변경
1 parent 31b6ea5 commit 562845b

File tree

4 files changed

+27
-14
lines changed

4 files changed

+27
-14
lines changed

src/modules/slack/slack.notifier.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ dotenv.config();
88
if (!process.env.SLACK_WEBHOOK_URL) {
99
throw new Error('SLACK_WEBHOOK_URL is not defined in environment variables.');
1010
}
11+
12+
// eslint-disable-next-line @typescript-eslint/naming-convention
1113
const SLACK_WEBHOOK_URL: string = process.env.SLACK_WEBHOOK_URL;
1214

1315
interface SlackPayload {
@@ -20,8 +22,7 @@ interface SlackPayload {
2022
*/
2123
export async function sendSlackMessage(message: string): Promise<void> {
2224
const payload: SlackPayload = { text: message };
23-
const response = await axios.post(SLACK_WEBHOOK_URL, payload, {
25+
await axios.post(SLACK_WEBHOOK_URL, payload, {
2426
headers: { 'Content-Type': 'application/json' },
2527
});
26-
console.log(response);
2728
}

src/repositories/__test__/leaderboard.repo.integration.test.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
/**
2+
* 주의: 이 통합 테스트는 현재 시간에 의존적입니다.
3+
* getCurrentKSTDateString과 getKSTDateStringWithOffset 함수는 실제 시간을 기준으로
4+
* 날짜 문자열을 생성하므로, 테스트 실행 시간에 따라 결과가 달라질 수 있습니다.
5+
*/
6+
17
import logger from '@/configs/logger.config';
28
import dotenv from 'dotenv';
39
import pg from 'pg';

src/repositories/__test__/leaderboard.repo.test.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ describe('LeaderboardRepository', () => {
9393
await repo.getUserLeaderboard('viewCount', mockDateRange, 10);
9494

9595
expect(mockPool.query).toHaveBeenCalledWith(
96-
expect.stringContaining('make_interval(days := $1::int)'),
96+
expect.stringContaining('WHERE date >='), // pastDateKST를 사용하는 부분 확인
9797
expect.arrayContaining([mockDateRange, expect.anything()]),
9898
);
9999
});
@@ -168,7 +168,7 @@ describe('LeaderboardRepository', () => {
168168
await repo.getPostLeaderboard('viewCount', mockDateRange, 10);
169169

170170
expect(mockPool.query).toHaveBeenCalledWith(
171-
expect.stringContaining('make_interval(days := $1::int)'),
171+
expect.stringContaining('WHERE date >='), // pastDateKST를 사용하는 부분 확인
172172
expect.arrayContaining([mockDateRange, expect.anything()]),
173173
);
174174
});

src/repositories/leaderboard.repository.ts

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,15 @@ import logger from '@/configs/logger.config';
22
import { Pool } from 'pg';
33
import { DBError } from '@/exception';
44
import { UserLeaderboardSortType, PostLeaderboardSortType } from '@/types/index';
5+
import { getCurrentKSTDateString, getKSTDateStringWithOffset } from '@/utils/date.util';
56

67
export class LeaderboardRepository {
78
constructor(private pool: Pool) {}
89

910
async getUserLeaderboard(sort: UserLeaderboardSortType, dateRange: number, limit: number) {
1011
try {
11-
const cteQuery = this.buildLeaderboardCteQuery();
12+
const pastDateKST = getKSTDateStringWithOffset(-dateRange * 24 * 60);
13+
const cteQuery = this.buildLeaderboardCteQuery(dateRange);
1214

1315
const query = `
1416
${cteQuery}
@@ -20,17 +22,17 @@ export class LeaderboardRepository {
2022
COUNT(DISTINCT CASE WHEN p.is_active = true THEN p.id END) AS total_posts,
2123
SUM(COALESCE(ts.today_view, 0) - COALESCE(ss.start_view, COALESCE(ts.today_view, 0))) AS view_diff,
2224
SUM(COALESCE(ts.today_like, 0) - COALESCE(ss.start_like, COALESCE(ts.today_like, 0))) AS like_diff,
23-
COUNT(DISTINCT CASE WHEN p.released_at >= CURRENT_DATE - make_interval(days := $1::int) AND p.is_active = true THEN p.id END) AS post_diff
25+
COUNT(DISTINCT CASE WHEN p.released_at >= '${pastDateKST}' AND p.is_active = true THEN p.id END) AS post_diff
2426
FROM users_user u
2527
LEFT JOIN posts_post p ON p.user_id = u.id
2628
LEFT JOIN today_stats ts ON ts.post_id = p.id
2729
LEFT JOIN start_stats ss ON ss.post_id = p.id
2830
WHERE u.email IS NOT NULL
2931
GROUP BY u.id, u.email
3032
ORDER BY ${this.SORT_COL_MAPPING[sort]} DESC, u.id
31-
LIMIT $2;
33+
LIMIT $1;
3234
`;
33-
const result = await this.pool.query(query, [dateRange, limit]);
35+
const result = await this.pool.query(query, [limit]);
3436

3537
return result.rows;
3638
} catch (error) {
@@ -41,7 +43,7 @@ export class LeaderboardRepository {
4143

4244
async getPostLeaderboard(sort: PostLeaderboardSortType, dateRange: number, limit: number) {
4345
try {
44-
const cteQuery = this.buildLeaderboardCteQuery();
46+
const cteQuery = this.buildLeaderboardCteQuery(dateRange);
4547

4648
const query = `
4749
${cteQuery}
@@ -59,9 +61,9 @@ export class LeaderboardRepository {
5961
LEFT JOIN start_stats ss ON ss.post_id = p.id
6062
WHERE p.is_active = true
6163
ORDER BY ${this.SORT_COL_MAPPING[sort]} DESC, p.id
62-
LIMIT $2;
64+
LIMIT $1;
6365
`;
64-
const result = await this.pool.query(query, [dateRange, limit]);
66+
const result = await this.pool.query(query, [limit]);
6567

6668
return result.rows;
6769
} catch (error) {
@@ -71,7 +73,11 @@ export class LeaderboardRepository {
7173
}
7274

7375
// 오늘 날짜와 기준 날짜의 통계를 가져오는 CTE(임시 결과 집합) 쿼리 빌드
74-
private buildLeaderboardCteQuery() {
76+
private buildLeaderboardCteQuery(dateRange: number) {
77+
const nowDateKST = getCurrentKSTDateString();
78+
// 과거 날짜 계산 (dateRange일 전)
79+
const pastDateKST = getKSTDateStringWithOffset(-dateRange * 24 * 60);
80+
7581
return `
7682
WITH
7783
today_stats AS (
@@ -80,7 +86,7 @@ export class LeaderboardRepository {
8086
daily_view_count AS today_view,
8187
daily_like_count AS today_like
8288
FROM posts_postdailystatistics
83-
WHERE (date AT TIME ZONE 'Asia/Seoul' AT TIME ZONE 'UTC')::date <= (NOW() AT TIME ZONE 'UTC')::date
89+
WHERE date <= '${nowDateKST}'
8490
ORDER BY post_id, date DESC
8591
),
8692
start_stats AS (
@@ -89,7 +95,7 @@ export class LeaderboardRepository {
8995
daily_view_count AS start_view,
9096
daily_like_count AS start_like
9197
FROM posts_postdailystatistics
92-
WHERE (date AT TIME ZONE 'Asia/Seoul' AT TIME ZONE 'UTC')::date >= ((NOW() AT TIME ZONE 'UTC')::date - make_interval(days := $1::int))
98+
WHERE date >= '${pastDateKST}'
9399
ORDER BY post_id, date ASC
94100
)
95101
`;

0 commit comments

Comments
 (0)