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

feat : 예매대기 처리 스케줄러 구현 #43

Merged
merged 14 commits into from
Dec 28, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,12 +1,20 @@
package dev.hooon.waitingbooking.domain.repository;

import java.util.List;
import java.util.Optional;

import dev.hooon.waitingbooking.domain.entity.WaitingBooking;

public interface WaitingBookingRepository {

void save(WaitingBooking waitingBooking);

Optional<WaitingBooking> findById(Long id);

List<WaitingBooking> findAll();

// WaitingStatus 가 WAITING 인 데이터를 최신순으로 조회하는 쿼리
List<WaitingBooking> findByStatusIsWaiting();

void updateToActiveById(Long id);
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
package dev.hooon.waitingbooking.infrastructure.adaptor;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Optional;

import org.springframework.stereotype.Repository;

import dev.hooon.waitingbooking.domain.entity.WaitingBooking;
import dev.hooon.waitingbooking.domain.entity.WaitingStatus;
import dev.hooon.waitingbooking.domain.repository.WaitingBookingRepository;
import dev.hooon.waitingbooking.infrastructure.repository.WaitingBookingJpaRepository;
import lombok.RequiredArgsConstructor;
Expand All @@ -20,9 +23,27 @@ public void save(WaitingBooking waitingBooking) {
waitingBookingJpaRepository.save(waitingBooking);
}

@Override
public Optional<WaitingBooking> findById(Long id) {
return waitingBookingJpaRepository.findById(id);
}

@Override
public List<WaitingBooking> findAll() {
return waitingBookingJpaRepository.findAll();
}

@Override
public List<WaitingBooking> findByStatusIsWaiting() {
return waitingBookingJpaRepository.findByStatusOrderByIdDesc(WaitingStatus.WAITING);
Copy link
Contributor

Choose a reason for hiding this comment

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

네이밍 굿굿 한번에 바로 파악했네요

}

@Override
public void updateToActiveById(Long id) {
Copy link
Contributor

Choose a reason for hiding this comment

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

updateStatusToActiveById 는 어떨까요?! (이것도 사소해~)

Copy link
Member Author

Choose a reason for hiding this comment

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

이 쿼리가 어댑터쪽 코드보면 상태변경도있는데 expireAt 도 6시간 뒤로 설정해주는 쿼리라서 이렇게 네이밍했어요!

waitingBookingJpaRepository.updateStatusAndExpireAt(
id,
WaitingStatus.ACTIVATION,
LocalDateTime.now().plusHours(6)
);
}
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,26 @@
package dev.hooon.waitingbooking.infrastructure.repository;

import java.time.LocalDateTime;
import java.util.List;

import org.springframework.data.jpa.repository.EntityGraph;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;

import dev.hooon.waitingbooking.domain.entity.WaitingBooking;
import dev.hooon.waitingbooking.domain.entity.WaitingStatus;

public interface WaitingBookingJpaRepository extends JpaRepository<WaitingBooking, Long> {

@EntityGraph(attributePaths = {"user", "waitingBookingSeats"})
Copy link
Contributor

Choose a reason for hiding this comment

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

이거 fetch join으로 한번에 다 가져오는게 맞나용??

Copy link
Member Author

Choose a reason for hiding this comment

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

넵 맞아요 user 는 이메일 보낼때 사용될거같아서 넣었고 waitingBookingSeats 는 예약대기 처리하는 로직에서 사용돼서 같이 패칭했습니다

List<WaitingBooking> findByStatusOrderByIdDesc(WaitingStatus status);

@Modifying
@Query("update WaitingBooking w SET w.status = :status, w.expireAt = :expireAt where w.id = :id")
void updateStatusAndExpireAt(
@Param("id") Long id,
@Param("status") WaitingStatus status,
@Param("expireAt") LocalDateTime expireAt);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
package dev.hooon.waitingbooking.domain.repository;

import static org.assertj.core.api.Assertions.*;

import java.time.LocalDateTime;
import java.util.List;

import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.util.ReflectionTestUtils;

import dev.hooon.common.fixture.WaitingBookingFixture;
import dev.hooon.common.support.DataJpaTestSupport;
import dev.hooon.user.domain.entity.User;
import dev.hooon.user.domain.entity.UserRole;
import dev.hooon.user.domain.repository.UserRepository;
import dev.hooon.waitingbooking.domain.entity.WaitingBooking;
import dev.hooon.waitingbooking.domain.entity.WaitingStatus;
import jakarta.persistence.EntityManager;
import jakarta.persistence.PersistenceContext;

@DisplayName("[WaitingBookingRepository 테스트]")
class WaitingBookingRepositoryTest extends DataJpaTestSupport {

@Autowired
private WaitingBookingRepository waitingBookingRepository;
@Autowired
private UserRepository userRepository;
@PersistenceContext
private EntityManager entityManager;

private final User user = new User("hello123@naver.com", "name", UserRole.BUYER);

@Test
@DisplayName("[WAITING 상태인 데이터를 최신순으로 조회한다]")
void findByStatusIsWaitingTest() {
//given
userRepository.save(user);

List<WaitingBooking> waitingBookings = List.of(
WaitingBookingFixture.getWaitingBooking(user),
WaitingBookingFixture.getWaitingBooking(user),
WaitingBookingFixture.getWaitingBooking(user)
);
// 0번 데이터만 상태를 ACTIVATION 으로 변경
ReflectionTestUtils.setField(waitingBookings.get(0), "status", WaitingStatus.ACTIVATION);

waitingBookings.forEach(waitingBooking -> waitingBookingRepository.save(waitingBooking));

//when
List<WaitingBooking> result = waitingBookingRepository.findByStatusIsWaiting();

//then
assertThat(result)
.hasSize(2)
.containsExactly(waitingBookings.get(2), waitingBookings.get(1));
}

@Test
@DisplayName("[id 에 해당하는 데이터의 status 를 ACTIVATION 으로 변경하고 expireAt 을 6시간뒤로 설정한다]")
void updateToActiveByIdTest() {
//given
userRepository.save(user);

WaitingBooking waitingBooking = WaitingBookingFixture.getWaitingBooking(user);
waitingBookingRepository.save(waitingBooking);

//when
waitingBookingRepository.updateToActiveById(waitingBooking.getId());
entityManager.flush();
entityManager.clear();

//then
WaitingBooking actual = waitingBookingRepository.findById(waitingBooking.getId()).orElseThrow();
assertThat(actual.getStatus()).isEqualTo(WaitingStatus.ACTIVATION);
assertThat(actual.getExpireAt()).isEqualToIgnoringSeconds(LocalDateTime.now().plusHours(6));
}
}