Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/hodadako step2 #10

Open
wants to merge 21 commits into
base: hodadako
Choose a base branch
from
Open

Feature/hodadako step2 #10

wants to merge 21 commits into from

Conversation

hodadako
Copy link
Collaborator

구현사항

  • 새로운 통계 테이블을 생성합니다.
  • 일 단위 당일 전체 송금 금액, 해당 날짜 까지의 누적 송금 금액 을 담도록 작성해 주세요.
  • 해당 테이블을 조회하는 API (시작 날짜와 종료 날짜를 받는) 도 개발이 필요합니다.
  • 일반적인 경우 새벽 4시 에 전날 통계 집계가 진행되며, 필요 시 API를 통해 특정 날짜의 통계를 강제로 집계할 수 있어야 합니다.

구현내용

  • Transaction에서 날짜 간 사이의 전체 송금 금액과 누적 송금 금액을 한번에 조회하도록 구현하였습니다.
  • schedule 뿐만 아니라 강제로 집계할 수 있는 API를 추가하였습니다.

수정사항

  • 기존 Entity들을 대용량 데이터 w / Backend에 맞게끔 수정했습니다.
  • Transaction 테이블이 존재하는걸 뒤늦게 알게되어 그에 맞추어 수정하였습니다.

- EmailRecordRequest 내부에 있던 Save DTO를 단독 레코드로 변경
- 동시에 모든 데이터를 메모리에 로딩하지 않도록 ``@Query``와 ``Stream``을 사용하였음
- DTO를 조회할 시 fetch join 사용 불가하므로 join을 사용하도록 변경
- 개발을 위해 ddl-auto를 update로 두어 스키마를 자동으로 업데이트 하게 두었음
- 날짜에 시간이 필요 없는걸 고려하여 LocalDate로 변경
- 통계 집계에 이전까지의 누적금액 합산을 위해 조회 기능 추가
- 새벽 4시 마다 통계를 집계할 수 있도록 스케쥴된 통계 집계 함수 추가
- 특정 날짜 강제로 집계할 수 있는 기능 추가
- 통계 집계 시 통계 생성 로직을 TransferStatistics 에서 하도록 구현

- DTO 내부에 유효성 검증 추가 - 빈 값이거나 현재 혹은 과거에 해당 하는 날짜인지 검증, 거래 특성상 미래에 대한 기록이 존재하지 않을 것이라 생각하여 추가
- 시작 날짜가 종료 날짜를 넘지 않도록 검증 추가
- 오늘 이전의 날짜만 입력 값으로 받을 수 있도록 검증 추가
- Get 대신 Aggregate이라는 이름으로 바꾸어 집계라는 의미를 추가
- 맞지 않는 컬럼들 삭제 및 수정
- 맞지 않는 컬럼들 삭제 및 수정
@hodadako hodadako requested review from VSFe and nyh365 November 11, 2024 20:40
@hodadako hodadako self-assigned this Nov 11, 2024
today.toLocalDate());
var transferStatistics = transferStatisticsReader.findByUnitDate(yesterday.toLocalDate());
Long dailyTotal = allTransfersByDate.map(TransferStatistics::getDailyTotalAmount).reduce(0L, Long::sum);
Long cumulativeTotal = transferStatistics.getCumulativeTotalAmount() + allTransfersByDate.map(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

현재 로직은 어떻게든 이전 데이터가 존재해야 끼워넣을 수 있는 구조로 보이는데요.

  • 처음 해당 통계 도입 시, 기본 데이터를 강제로 삽입해서 동작할 계획이실까요?
  • 징검다리 연휴에 순간적인 네트워크 에러가 발생하여 데이터 삽입이 실패했다면, 그 기간동안 쭉 에러가 발생하지 않을까요?

ORDER BY ts.unitDate DESC
""")
@QueryHints(value = {
@QueryHint(name = HINT_FETCH_SIZE, value = "" + Integer.MAX_VALUE),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

String.valueOf(Integer.MAX_VALUE) 가 좀 더 자연스럽지 않을까요?


public interface TransactionRepository extends JpaRepository<Transaction, Long> {
@Query(
"""
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

혹시 해당 쿼리의 실행계획을 확인하셨을까요?
(해당 테이블의 데이터가 많은 것 같지만, 실제로는 그렇게 많은 것도 아닙니다.)

import jakarta.validation.constraints.PastOrPresent;

public record AggregateTransferStatisticsRequest(
@NotBlank
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@NotNull 을 원하신건가요?
@NotBlank 는 문자열에서 사용되는 어노테이션입니다.


@PostMapping("/v1/transfer-statistics")
public ResponseEntity<TransferStatistics> aggregateTransferStatistics(
@RequestBody AggregateTransferStatisticsRequest request
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Request 객체에 Validation 어노테이션을 박았지만, 막상 여기서 @Valid를 안 씌우셔서 검증이 안 이뤄질 것 같네요.

@@ -0,0 +1,40 @@
package org.c4marathon.assignment.domain.transfer_statistics.presentation;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

일반적으로 패키지명에 underscore를 삽입하는 것은 매우 권장되지 않습니다.

(ex1. https://google.github.io/styleguide/javaguide.html#s5.2.1-package-names)
(ex2. https://naver.github.io/hackday-conventions-java/#package-lowercase)

private LocalDateTime transactionDate;

@Override
public boolean equals(Object o) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

전반적으로 equalshashCode 를 정의하고 있는데요. 혹시 해당 데이터가 HashMap 에 들어갈 것을 상정하셔서 그런걸까요?

@@ -15,6 +15,9 @@ spring:
mail.smtp.ssl.enable: true
mail.smtp.ssl.trust: ${SMTP_HOST}
mail.smtp.starttls.enable: true
jpa:
hibernate:
ddl-auto: update
Copy link
Member

@VSFe VSFe Nov 14, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

데이터가 들어있는 테이블에선, 절대 create/create-drop/update 를 사용하지 말아주세요. (지금도 당장 수천만개의 데이터가 들어있는 transaction 테이블을 바라보고 있기 때문에, 다소 위험한 상황이 발생할 뻔 했네요.)


@Transactional(readOnly = true)
public List<TransferStatistics> findAllByUnitDateBetween(GetAllTransferStatisticsRequest request) {
return transferStatisticsReader.findAllByUnitDateBetween(request.startDate(), request.endDate())
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

처음부터 Stream 이 아닌 List를 반환하도록 하면 되지 않나요?

@Column(name = "unit_date", columnDefinition = "datetime")
private LocalDateTime unitDate;

public TransferStatistics(Long dailyTotalAmount, Long cumulativeTotalAmount, LocalDateTime unitDate) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@NoArgConstructor는 Lombok 으로 작성하셨는데, 정작 이건 Lombok을 안 쓰셨네요.
스타일은 통일해 주세요.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants