Skip to content

Commit

Permalink
Merge pull request #340 from benjaminuj/fix/#339
Browse files Browse the repository at this point in the history
좌석예약 동시성 처리 로직 수정
  • Loading branch information
benjaminuj authored Sep 17, 2024
2 parents dcc4da0 + c84d0f5 commit ad72917
Show file tree
Hide file tree
Showing 12 changed files with 408 additions and 34 deletions.
2 changes: 1 addition & 1 deletion src/main/java/project/seatsence/src/LockRepository.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

public interface LockRepository extends JpaRepository<Reservation, Long> {
@Query(value = "select get_lock(:key, 3000)", nativeQuery = true)
void getLock(String key);
Integer getLock(String key);

@Query(value = "select release_lock(:key)", nativeQuery = true)
void releaseLock(String key);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package project.seatsence.src.utilization.service.reservation;

import java.time.LocalDateTime;
import com.fasterxml.jackson.core.JsonProcessingException;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
Expand All @@ -9,7 +9,9 @@
import project.seatsence.global.exceptions.BaseException;
import project.seatsence.src.LockRepository;
import project.seatsence.src.store.domain.StoreChair;
import project.seatsence.src.user.domain.User;
import project.seatsence.src.utilization.domain.reservation.Reservation;
import project.seatsence.src.utilization.dto.request.ChairUtilizationRequest;

@Component
@RequiredArgsConstructor
Expand All @@ -21,21 +23,45 @@ public class NamedLockUserReservationFacade {
@Transactional
public long chairReservation(
StoreChair storeChair,
LocalDateTime startDateTime,
LocalDateTime endDateTime,
Reservation reservation) {
Reservation reservation,
ChairUtilizationRequest chairUtilizationRequest,
String userEmail,
User user)
throws JsonProcessingException {
long chairId = -1;

try {
lockRepository.getLock(storeChair.getId().toString());
// lockRepository.getLock(storeChair.getId().toString());

Integer lock = lockRepository.getLock(storeChair.getId().toString());
if (lock == 1) {
System.out.println("Lock acquired by: " + Thread.currentThread().getName());
} else if (lock == 0) {
System.out.println(
"Failed to acquire lock during timeout: "
+ Thread.currentThread().getName());
} else if (lock == null) {
System.out.println(
"Failed to acquire lock error!: " + Thread.currentThread().getName());
}

chairId =
reservationService.checkExistsReservationDateTimeAndSave(
storeChair, startDateTime, endDateTime, reservation);
storeChair, reservation, chairUtilizationRequest, userEmail, user);

if (chairId == -1) {
System.out.println("facade: 이미 예약이 존재!!!");
throw new BaseException(ResponseCode.RESERVATION_ALREADY_EXIST);
} else {
System.out.println("예약 성공! : " + Thread.currentThread().getName());
}
} catch (Exception e) {
System.out.println("exeption 발생!!! : " + Thread.currentThread().getName());
e.printStackTrace();

} finally {

System.out.println("finally!! " + Thread.currentThread().getName());
lockRepository.releaseLock(storeChair.getId().toString());

return chairId;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
import static project.seatsence.src.utilization.domain.reservation.ReservationStatus.APPROVED;
import static project.seatsence.src.utilization.domain.reservation.ReservationStatus.PENDING;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
Expand All @@ -14,18 +16,35 @@
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import project.seatsence.global.exceptions.BaseException;
import project.seatsence.src.store.domain.CustomUtilizationField;
import project.seatsence.src.store.domain.ReservationUnit;
import project.seatsence.src.store.domain.StoreChair;
import project.seatsence.src.store.service.StoreChairService;
import project.seatsence.src.store.service.StoreCustomService;
import project.seatsence.src.store.service.StoreService;
import project.seatsence.src.user.domain.User;
import project.seatsence.src.user.service.UserService;
import project.seatsence.src.utilization.dao.CustomUtilizationContentRepository;
import project.seatsence.src.utilization.dao.reservation.ReservationRepository;
import project.seatsence.src.utilization.domain.CustomUtilizationContent;
import project.seatsence.src.utilization.domain.reservation.Reservation;
import project.seatsence.src.utilization.domain.reservation.ReservationStatus;
import project.seatsence.src.utilization.dto.request.ChairUtilizationRequest;
import project.seatsence.src.utilization.dto.request.CustomUtilizationContentRequest;

@Service
@Transactional
@RequiredArgsConstructor
public class ReservationService {

private final ReservationRepository reservationRepository;
private final StoreCustomService storeCustomService;
private final CustomUtilizationContentRepository customUtilizationContentRepository;

// test
private final StoreChairService storeChairService;
private final UserService userService;
private final StoreService storeService;

public Reservation findByIdAndState(Long id) {
return reservationRepository
Expand Down Expand Up @@ -74,30 +93,80 @@ public ReservationUnit getUtilizationUnitOfReservation(Reservation reservation)
@Transactional(propagation = Propagation.REQUIRES_NEW)
public long checkExistsReservationDateTimeAndSave(
StoreChair storeChair,
LocalDateTime startDateTime,
LocalDateTime endDateTime,
Reservation reservation) {
Reservation reservation,
ChairUtilizationRequest chairUtilizationRequest,
String userEmail,
User user)
throws JsonProcessingException {
List<ReservationStatus> reservationStatuses = new ArrayList<>();
reservationStatuses.add(ReservationStatus.APPROVED);
reservationStatuses.add(ReservationStatus.PENDING);

System.out.println("겹치는 예약 데이터 조회 전 : " + Thread.currentThread().getName());
List<Reservation> reservationsBasedStartDateTime =
findAllByReservedStoreChairAndReservationStatusInAndStartScheduleIsBeforeAndEndScheduleIsAfterAndState(
storeChair, reservationStatuses, startDateTime, startDateTime);

storeChair,
reservationStatuses,
chairUtilizationRequest.getStartSchedule(),
chairUtilizationRequest.getStartSchedule());
System.out.println("겹치는 예약 데이터 조회 후 : " + Thread.currentThread().getName());
if (reservationsBasedStartDateTime.size() > 0) {
System.out.println("예약 시간 겹침 : " + Thread.currentThread().getName());
return -1;
}

List<Reservation> reservationsBasedEndDateTime =
findAllByReservedStoreChairAndReservationStatusInAndStartScheduleIsBeforeAndEndScheduleIsAfterAndState(
storeChair, reservationStatuses, endDateTime, endDateTime);
storeChair,
reservationStatuses,
chairUtilizationRequest.getEndSchedule(),
chairUtilizationRequest.getEndSchedule());

if (reservationsBasedEndDateTime.size() > 0) {
System.out.println("예약 시간 겹침 : " + Thread.currentThread().getName());
return -1;
}

return save(reservation).getId();
System.out.println("예약 가능 : " + Thread.currentThread().getName());

// StoreChair storeChair1 =
// storeChairService.findByIdAndState(1L);
// User user1 = userService.findByEmailAndState(userEmail);
// Store store1 = storeService.findByIdAndState(1L);
//
//
// Reservation reservation1 =
// Reservation.builder()
// .store(store1)
// .reservedStoreChair(storeChair1)
// .reservedStoreSpace(null)
// .user(user1)
// .startSchedule(startDateTime)
// .endSchedule(endDateTime)
// .build();

long reservationId = save(reservation).getId();
inputChairCustomUtilizationContent(user, reservation, chairUtilizationRequest);
return reservationId;
}

public void inputChairCustomUtilizationContent(
User user, Reservation reservation, ChairUtilizationRequest chairUtilizationRequest)
throws JsonProcessingException {

for (CustomUtilizationContentRequest request :
chairUtilizationRequest.getCustomUtilizationContents()) {

CustomUtilizationField customUtilizationField =
storeCustomService.findByIdAndState(request.getFieldId());

ObjectMapper objectMapper = new ObjectMapper();
String content = objectMapper.writeValueAsString(request.getContent());

CustomUtilizationContent newCustomUtilizationContent =
new CustomUtilizationContent(
user, customUtilizationField, reservation, null, content);
customUtilizationContentRepository.save(newCustomUtilizationContent);
}
}

public List<Reservation>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,6 @@
import org.springframework.data.domain.Slice;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import project.seatsence.global.code.ResponseCode;
import project.seatsence.global.exceptions.BaseException;
import project.seatsence.global.response.SliceResponse;
import project.seatsence.src.store.domain.CustomUtilizationField;
import project.seatsence.src.store.domain.Store;
Expand Down Expand Up @@ -372,6 +370,7 @@ public void inputSpaceCustomUtilizationContent(

public long chairReservation(String userEmail, ChairUtilizationRequest chairUtilizationRequest)
throws JsonProcessingException {

StoreChair storeChair =
storeChairService.findByIdAndState(chairUtilizationRequest.getStoreChairId());
Store store = storeService.findByIdAndState(storeChair.getStoreSpace().getStore().getId());
Expand All @@ -390,16 +389,14 @@ public long chairReservation(String userEmail, ChairUtilizationRequest chairUtil
// 동시성처리: 의자 예약 일정 겹치는지 검사 && 일정 겹치지 않으면 예약 DB에 저장
long savedId =
namedLockUserReservationFacade.chairReservation(
storeChair,
chairUtilizationRequest.getStartSchedule(),
chairUtilizationRequest.getEndSchedule(),
reservation);
storeChair, reservation, chairUtilizationRequest, userEmail, user);

if (savedId == -1) {
throw new BaseException(ResponseCode.RESERVATION_ALREADY_EXIST);
}
// if (savedId == -1) {
// System.out.println("service: 이미 예약이 존재!!!");
// throw new BaseException(ResponseCode.RESERVATION_ALREADY_EXIST);
// }

inputChairCustomUtilizationContent(user, reservation, chairUtilizationRequest);
// inputChairCustomUtilizationContent(user, reservation, chairUtilizationRequest);

return savedId;
}
Expand Down
Loading

0 comments on commit ad72917

Please sign in to comment.