요청된 지 오래된 주문이나, 완료된 지 오래된 주문에 대해서도 주문을 수락하고 리뷰가 작성 가능한 구조가 마음에 들지 않았다.
이럴 때 db를 주기적으로 업데이트하도록 해주는 로직을 짤 필요가 있었고 그것은 spring scheduler가 해줄 수 있다.
Spring scheduler란?
특정 작업을 주기적으로 실행하거나, 예약된 시간에 실행할 수 있도록 도와주는 도구다.
기본적으로 포함된 기능이라 의존성 추가가 필요없으며 @EnableScheduling으로 기능을 활성화해주기만 하면 된다.
@Scheduled 어노테이션으로 간단하게 구현 가능하며 @EnableAsync를 통해 비동기 처리도 가능하다.
스케줄링 실패에 대한 예외처리가 필요하며 작업량이 클 경우 스레드 풀을 구성하거나 비동기 작업으로 처리해야 한다.
또한 같은 작업이 중복 실행되지 않도록 주의해야 한다.
@Component
@RequiredArgsConstructor
public class OrderScheduler {
private final OrderRepository orderRepository;
private final WebSocketService webSocketService;
// 1분에 한번 10분넘은 주문 자동거절
@Scheduled(fixedRate = 60000)
@Transactional
public void expirePendingOrders() {
List<Order> expiredOrders = orderRepository.findAllByStatusAndCreatedAtBefore(
Order.Status.PENDING,
LocalDateTime.now().minusMinutes(10)
);
//유저 id 추출
List<Long> userIds = expiredOrders.stream()
.map(order -> order.getUser().getId())
.distinct() //중복 제거
.toList();
//알림
String message = "주문이 자동 취소되었습니다.";
webSocketService.sendNotificationToUser(userIds, message);
orderRepository.deleteAll(expiredOrders);
}
}
fixedRate = 60000은 1분에 한번이다. 대용량 데이터를 처리할 경우 fixedDelay로 하는 것이 더 좋지만 나는 소박하니까 rate로 처리했다.
order status가 pending인 건에 대하여 조사하고, pending인지 10분이 넘은 경우(createdAt이 10분 넘은 경우) 주문이 자동취소(삭제)된다. 그리고 해당 건에 대해 websocket으로 고객에게 알림 메세지를 보낸다.
리뷰 작성권한은 주문이 생성된 지 7일이 넘는 항목 && COMPLETED인 항목에 대해서 사라지도록 했고, 이 과정에서 불리언 형 컬럼을 추가했다.
구현이 매우 간편해서 자주 애용할 것 같다. 다음엔 더 복잡한 기능을 결합해서 해보자 ~
'팀 프로젝트 > 심화 프로젝트' 카테고리의 다른 글
심화 프로젝트 KPT 회고 (0) | 2025.01.13 |
---|---|
리팩토링 일기: SRP 최대한 준수해보자 (0) | 2025.01.13 |
WebSocket+AOP로 알림 기능 구현하기 (0) | 2025.01.09 |