사용자 좌석 결제 시간 이후 30분 이내에 입실 시간을 등록하지 않을 경우 좌석 자동 취소 하는 기능 구현

@Service
@RequiredArgsConstructor
@Slf4j
public class PaymentService {

    private final ScheduledExecutorService scheduler;
    
    @Transactional
    public KakaoApproveResponseDto kakaoPayApprove(String pgToken,Long userId,Long paymentId){
        printInfo();
        Payment payment = paymentRepository.findByPaymentId(paymentId).orElseThrow(()->new CatchStudyException(ErrorCode.PAYMENT_NOT_FOUND));
        Booking booking = payment.getBooking();
        Map<String,String> parameters = new HashMap<>();

        parameters.put("cid",KakaoPayProperties.cid);
        parameters.put("tid",payment.getTid());
        parameters.put("partner_order_id", String.valueOf(paymentId));
        parameters.put("partner_user_id", String.valueOf(userId));
        parameters.put("pg_token", pgToken);

        HttpEntity<Map<String,String>> requestEntity = new HttpEntity<>(parameters,this.getHeaders());

        RestTemplate restTemplate = new RestTemplate();

        KakaoApproveResponseDto kakaoApprove = restTemplate.postForObject(
                KakaoPayProperties.approveUrl,
                requestEntity,
                KakaoApproveResponseDto.class
        );

        //좌석,room 사용중으로 변경,  booking 테이블 변경 (상태,code), payment 테이블 변경 (amount,승인시간,status)
        String code = makeCode();
        booking.completeBooking(BookingStatus.beforeEnteringRoom,makeCode());
        payment.approvePayment(kakaoApprove.getApproved_at(), PaymentStatus.approve,kakaoApprove.getAmount().getTotal());
        if(booking.getBookedRoomInfo() == null){
            booking.getSeat().updateSeatStatus(false);
        }

        scheduleStatusCheck(booking.getBookingId(),payment); //30 분 후 상태 확인 작업 스케줄링

        return kakaoApprove;

    }
  

    @Transactional
    public void checkAndCancelBooking(Long bookingId) { //예약된 좌석이 결제 30분 후 아직 '입실 전' 상태 일 때 좌석 취소 시킴
        System.out.println("checkAndCancelBooking");
        printInfo();
        Booking booking = bookingRepository.findByBookingId(bookingId);
        if (booking != null && booking.getSeat() != null && booking.getStatus().equals(BookingStatus.beforeEnteringRoom)) {
            booking.cancelBeforeEnteringSeat();
            booking.getSeat().updateSeatStatus(true); // 좌석 사용 가능으로 변경
        }
    }

 
    public void scheduleStatusCheck(Long bookingId, Payment payment) {
        System.out.println("scheduleStatus Check");
        printInfo();
        LocalDateTime paymentTime = payment.getPaymentTime();
        long delay = Duration.between(LocalDateTime.now(), paymentTime.plusMinutes(1)).toMillis();
        if(delay>0){
            scheduler.schedule(() -> checkAndCancelBooking(bookingId), delay, TimeUnit.MILLISECONDS);
        }
    }
}
if (booking != null && booking.getSeat() != null && booking.getStatus().equals(BookingStatus.beforeEnteringRoom)) {
    booking.cancelBeforeEnteringSeat();
    booking.getSeat().updateSeatStatus(true); // 좌석 사용 가능으로 변경
}
-> booking 테이블의 변경감지가 동작하지 않아 DB 에 업데이트 되지 않음
private void printInfo(){
    boolean txActive = TransactionSynchronizationManager.isActualTransactionActive();
    log.info("tx active={}",txActive );
}

→ 트랜잭션이 설정된 상태인지 확인해봄

Untitled

Untitled

→ scheduleStatusCheck() 메서드는 트랜잭션이 설정 되었지만 checkAndCancelBooking() 메서드는 트랜잭션이 설정되지 않음