피카소 경매 사이트는
사용자가 경매 항목을 올리면
관리자가 그 경매 항목에 대해
승인을 한 후 경매가 등록된다.
(위 사진에서는 관리자 승인 단계가 생략되어있다.)
승인을 받은 경매 작품은
사용자가 지정한 경매 시작 일자에 맞추어
경매 예정 -> 경매 진행중 과 같이 상태가 바뀐다.
이러한 작업을 관리자가 모두 전담하기엔
너무나도 공수가 컸고
DB 내의 Event Schedular를 이용하기에는
DB 서버의 무게가 무거워질 수 있다고 판단되어
서버 단의 스케쥴링을 이용하여
경매 작품들의 상태값을 변경하기로 결정했다.
스케쥴링의 방식에 대해서는
이후 작성할 스케쥴링 코드에서 자세히 서술할 것이다.
0) 사전 설정
@Slf4j
@EnableScheduling // Schedule사용을 위한 Annotation
@SpringBootApplication
@RequiredArgsConstructor
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
@EnableScheduling 어노테이션을 이용하여
스케쥴링이 가능하도록 어플리케이션을 정의하였다.
1) 스케쥴링 코드 작성
1-1) StartAuctionSchedular
@Slf4j
@Component
@RequiredArgsConstructor
public class StartAuctionScheduler {
private final PictureService pictureService;
private final SendMailService sendMailService;
// 관리자가 승인한 경매 작품에 대한 스케쥴러
@Transactional
@Scheduled(cron = "0 0 9 * * *", zone = DateStaticConstants.ZONE_SEOUL)
public void startApprovePictureToBiddingAuction() { // 승인되었으므로 bidding으로 변화
log.info("Start Todays Auctions Open Schedule Runtime : NowTime >>> {}", LocalDateTime.now());
pictureService
.changePictureStatusByPictureStatusAndBidStartDate(AFTER_APPROVE, BIDDING, LocalDate.now())
.forEach(sendMailService::startBiddingMail);
log.info("End Todays Auctions Open Schedule Runtime : NowTime >>> {}", LocalDateTime.now());
}
// 관리자가 승인하지 않은 경매 작품에 대한 스케쥴러
@Transactional
@Scheduled(cron = "0 0 9 * * *", zone = DateStaticConstants.ZONE_SEOUL)
public void startNotApprovePictureToRejectAuction() { // 승인되지 않았으므로 reject
log.info("Start Reject Picture Schedule Runtime : NowTime >>> {}", LocalDateTime.now());
pictureService
.changePictureStatusByPictureStatusAndBidStartDate(BEFORE_APPROVE, BIDDING, LocalDate.now())
.forEach(sendMailService::pictureRejectMailWithNotApproveAdmin);
log.info("End Todays Auctions Open Schedule Runtime : NowTime >>> {}", LocalDateTime.now());
}
}
피카소 서비스의 경우
매일 오전 9시마다 경매 작품의 시작을 스케쥴링한다.
예를 들어,
사용자가 만약 10/4에 경매 작품 A를 등록하였는데
이 작품의 경매 시작 일시가 10/5이고
관리자가 문제없이 승인하였다면
A는 스케쥴링 코드에 의해
10/5 오전 9시에 AFTER_APPROVE 상태에서
BIDDING으로 상태값의 변화가 있을 것이다.
각 메소드는 관리자의 승인 여부에 따라
경매 중 작품으로 등록이 될지 안될지를 결정한다.
메소드 내에서 상태값을 바꾼 후
메일까지 발송하기 때문에 @Transactional을 걸어
메일 발송 후 update 쿼리문을 날릴 수 있도록 하였다.
1-2) EndAuctionSchedular
@Slf4j
@Component
@RequiredArgsConstructor
public class EndAuctionScheduler {
private final PictureService pictureService;
private final SendMailService sendMailService;
@Transactional
@Scheduled(cron = "0 0 18 * * *", zone = DateStaticConstants.ZONE_SEOUL)
public void endAuction() {
log.info("Today End Auctions Schedule Start Time >>> {}", LocalDateTime.now());
List<Picture> todayEndPictursList = pictureService.findPictureStatusByStatusAndBidEndDate(BIDDING, LocalDate.now());
todayEndPictursList.forEach(
picture -> {
if (picture.getBidHistory().isEmpty()) { // 입찰 이력이 없다면 유찰(reject)
picture.setPictureStatus(REJECT);
sendMailService.pictureRejectMailWithFinishDate(picture);
} else { // 입찰 이력이 있다면 낙찰(success)
picture.setPictureStatus(SUCCESS_BID);
sendMailService.pictureSuccessBidMail(picture);
}
}
);
log.info("Today End Auctions Schedule End Time >>> {}", LocalDateTime.now());
}
}
피카소 서비스의 경우
매일 오전 18시마다 경매 작품 시간 만료를 스케쥴링한다.
경매 시간은 7일로 고정되어 있고
만약 작품에 대한 입찰 이력이 없다면 유찰로,
입찰 이력이 있다면 낙찰로 상태값을 변화시켜야 한다.
예를 들어,
사용자가 만약 10/4에 경매 작품 A를 등록하였다.
이 작품의 경매 만료 일자는 10/11이고
만약 이 작품에 입찰자가 있다면 낙찰로,
입찰자가 없다면 유찰로 상태값이 변화되어야 할 것이다.
startAuction 스케쥴러와 마찬가지로,
메소드 내에서 상태값을 바꾼 후
메일까지 발송하기 때문에 @Transactional을 걸어
메일 발송 후 update 쿼리문을 날릴 수 있도록 하였다.
2) 스케쥴링 테스트
위 테스트는 cron을 0 * * * * 으로 주어
매 분 마다(시 분 초에서 0초가 될 때 마다) 스케쥴링을 돌린 테스트 결과이다.
이렇게 스케쥴링을 하고 메일을 보낼 때
메일 발송 포스팅 마지막에 기술한 문제가 발생했다.
이 문제에 대해서는 다음 포스팅에서 해결 방법을 기술하려 한다.
'🌿 Spring' 카테고리의 다른 글
[Spring] 전략 패턴 사용하기 (0) | 2024.01.29 |
---|---|
메일 발송 - 스케쥴링 간 문제 해결 with Async (1) | 2023.10.03 |
사용자에게 메일 보내기 with JavaMailSender (0) | 2023.10.03 |
무한스크롤 API 구현하기 (1) | 2023.09.04 |