Skip to content

Conversation

kilhyeonjun
Copy link
Contributor

요구사항

  • 비즈니스 Usecase 개발
  • 통합 테스트 작성

작업 내용

  • 예약 가능한 날짜 조회 usecase 작성 및 통합테스트
  • 예약 가능한 좌석 조회 usecase 작성 및 통합테스트
  • 좌석예약 usecase 작성 및 통합테스트 (동시성 포함)
  • 예약 내역 결재 usecase 작성 및 통합테스트 (동시성 포함)
  • 임시 예약 만료 usecase 작성 및 통합테스트
  • 잔액 충전 usecase 작성 및 통합테스트 (동시성 포함)
  • 지갑 조회 usecase 작성 및 통합테스트
  • 대기열 토큰 발급 usecase 작성 및 통합테스트 (동시성 포함)
  • 대기열 토큰 검증 usecase 작성 및 통합테스트
  • 대기열 활성 usecase 작성 및 통합테스트 (동시성 포함)
  • 대기열 만료 usecase 작성 및 통합테스트

리뷰포인트

  • 궁금한 사항은 코멘트 남겨놨습니다. 확인 부탁드립니다!
  • 리뷰어님들이 생각했을 때 더 좋은 패턴이 보일 경우 공유해주시면 좋을 것 같습니다.
  • 테스트 코드의 추가로 있으면 좋을 부분 또는 불 필요해 보이는 부분도 확인 부탁드립니다.

Copy link
Contributor Author

@kilhyeonjun kilhyeonjun left a comment

Choose a reason for hiding this comment

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

usecase별로 PR을 분리했으면 좋았을 것 같은데 시간상의 이유로 하나의 PR에 커밋단위로 분리했습니다. 🥲

query command 객체의 validation에 대한 테스트를 작성해주는 게 맞을지 의문이에요.
생각보다 생산성이 많이 떨어지는 것 같습니다.

public class HhplusConcertApplication {

public static void main(String[] args) {
TimeZone.setDefault(TimeZone.getTimeZone("UTC"));
Copy link
Contributor Author

Choose a reason for hiding this comment

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

DB와 application의 타임존을 맞춰졌습니다.


private final PaymentCommandService paymentCommandService;

@Transactional(readOnly = true)
Copy link
Contributor Author

Choose a reason for hiding this comment

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

파사드 계층에도 Transactional 이 필요할지 의문이네요.
롤백이 필요한 경우를 제외하고는 안쓰는 게 좋을까요?
롤백을 안쓴다면 영속성 컨텍스트로 인해 캐싱되는 부분의 이점을 가져가면 가는걸까요?

Comment on lines +33 to +35
@Modifying(clearAutomatically = true)
@Query("UPDATE WaitingQueue wq SET wq.status = 'EXPIRED' WHERE wq.status = 'PROCESSING' AND wq.expiredAt <= CURRENT_TIMESTAMP")
void expireWaitingQueues();
Copy link
Contributor Author

Choose a reason for hiding this comment

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

단순 쿼리로 해결 가능해보여서 작성했는데 객체지향에 맞게 도메인 레이어에서 작업하는게 좋았을까요?

Comment on lines +52 to +84
@Transactional(readOnly = true)
public void validateWaitingQueueProcessingAndConcertId(String waitingQueueUuid, Long concertId) {
WaitingQueue waitingQueue = waitingQueueQueryService.getWaitingQueue(
new GetWaitingQueueByUuid(waitingQueueUuid));

waitingQueue.validateProcessing();
waitingQueue.validateConcertId(concertId);
}

@Transactional(readOnly = true)
public void validateWaitingQueueProcessingAndScheduleId(String waitingQueueUuid,
Long scheduleId) {
WaitingQueue waitingQueue = waitingQueueQueryService.getWaitingQueue(
new GetWaitingQueueByUuid(waitingQueueUuid));
waitingQueue.validateProcessing();

ConcertSchedule concertSchedule = concertQueryService.getConcertSchedule(
new GetConcertScheduleByIdQuery(scheduleId));
waitingQueue.validateConcertId(concertSchedule.getConcertId());
}

@Transactional(readOnly = true)
public void validateWaitingQueueProcessingAndSeatId(String waitingQueueUuid, Long seatId) {
WaitingQueue waitingQueue = waitingQueueQueryService.getWaitingQueue(
new GetWaitingQueueByUuid(waitingQueueUuid));
waitingQueue.validateProcessing();

ConcertSeat concertSeat = concertQueryService.getConcertSeat(
new GetConcertSeatByIdQuery(seatId));
ConcertSchedule concertSchedule = concertQueryService.getConcertSchedule(
new GetConcertScheduleByIdQuery(concertSeat.getConcertScheduleId()));
waitingQueue.validateConcertId(concertSchedule.getConcertId());
}
Copy link
Contributor Author

Choose a reason for hiding this comment

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

흠 url 구조로인데 비슷한 로직이 3개가 되어버렸는데 더 좋은 방안이 있을지 의문이네요.
제출전 새벽에 짠거라... 다음에 더 고려해보겠숨다.
혹시 좋은 의견있으면 공유 부탁드림다.

@@ -9,6 +9,10 @@ public record GetConcertByIdParam(Long id) {

}

public record GetConcertByIdWithLockParam(Long id) {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Param 객체를 이용해서 오버로딩을 사용했습니다.
repository 메소드 네이밍은 간결해졌으나 Param객체 자체의 네이밍이 길여져서 고민이네요.

Comment on lines +4 to +11
config:
activate:
on-profile: local
datasource:
url: jdbc:mysql://${DB_HOST}/${DB_NAME}?characterEncoding=UTF-8&serverTimezone=UTC
username: ${DB_USERNAME}
password: ${DB_PASSWORD}
driver-class-name: com.mysql.cj.jdbc.Driver
Copy link
Contributor Author

Choose a reason for hiding this comment

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

env파일로 환경변수를 관리하였고 테스트 환경은 h2만 써도 괜찮을 것 같아서 분리하였습니다.

@kilhyeonjun kilhyeonjun merged commit 68dbf49 into master Oct 17, 2024
@kilhyeonjun kilhyeonjun deleted the feature/step8-16-usecase branch October 17, 2024 17:18
@@ -25,7 +26,7 @@ public class UserFacade {
public Wallet chargeUserWalletAmount(Long userId, Long walletId, Integer amount) {
var user = userQueryService.getUser(new GetUserByIdQuery(userId));

var wallet = userQueryService.getWallet(new GetUserWalletByUserIdQuery(user.getId()));
var wallet = userQueryService.getWallet(new GetUserWalletByUserIdWithLockQuery(user.getId()));
Copy link
Contributor Author

Choose a reason for hiding this comment

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

해당 파사드 메소드에 @transactional을 다니까 영속성 컨텍스트가 관리되면서 lost update가 일어나는 것 같더라구요. (1차 캐시에서 데이터를 가져와서 그런지..)
이부분더 깊게 공부해봐야할 것 같은데 금요일날찾아보겠숨다... (혹시 아시면 힌트 부탁드림다.)

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

Successfully merging this pull request may close these issues.

비즈니스 Usecase 개발 및 통합 테스트 작성
1 participant