web 개발/spring

spring scheduler 사용

잼추 2024. 7. 2. 01:40

간단히 spring schedular사용에 후기에 대해

작성해 보려고 한다.

 

spring scheduler

Spring Scheduler는 Spring Framework에서 제공하는 스케줄링 기능

,주기적으로 반복되는 작업을 쉽게 구성하고 실행할 수 있게 해줌

shceduler 방식

public class Scheculer() {

    @Scheduled(fixedDelay = 1000) // scheduler 끝나는 시간 기준으로 1000 간격으로 실행
    public void scheduleFixedDelayTask() {
        System.out.println(
        "Fixed delay task - " + System.currentTimeMillis() / 1000);
    }

    @Scheduled(fixedRate = 1000) // scheduler 시작하는 시간 기준으로 1000 간격으로 실행
    public void scheduleFixedRateTask() {
        System.out.println(
        "Fixed rate task - " + System.currentTimeMillis() / 1000);
    }

    @Scheduled(cron = "0 15 10 15 * ?") // cron에 따라 실행
    public void scheduleTaskUsingCronExpression() {
        long now = System.currentTimeMillis() / 1000;
        System.out.println(
        "schedule tasks using cron jobs - " + now);
    }

    @Scheduled(cron = "0 15 10 15 * ?", zone = "Europe/Paris") // cron에 TimeZone 설정 추가
}

 

목표 예시

결제가 완료되면

레디스의 await ship에 주문 id 추가

다음날 오후 4시에 이전 주문건 일괄 배송시작

다음날 오후 4시에 이전 배송 중건 일괄 배송완료

 

먼저 배송중인건 모두를 배송완료로 바꿔주고

SHIPPED를 비워준 후 

AWAITSHIP을 SHIPPED로 바꿔주기로 했다.

 

@Component
@RequiredArgsConstructor
public class OrderScheduler {
    private final RedisService redisService;
    private final OrderService orderService;


    // 매일 오후 4시 배송 중에서 배송완료로 변경
    @Scheduled(cron = OrderConstants.SHIP_COMPLETE_TIME)
    public void scheduleChangeStateToDelivered() {
        Set<String> set = redisService.getSetValues(OrderConstants.SHIPPED);
        LocalDateTime now = LocalDateTime.now().withHour(16).withMinute(0).withSecond(0).withNano(0);
        for (String o : set) {
            orderService.updateDeliverDateAndState(Long.parseLong( o), now);
        }
        redisService.deleteValues(OrderConstants.SHIPPED);
    }

    // 매일 오후 4시 결제 완료에서 배송중으로 변경
    @Scheduled(cron = OrderConstants.SHIP_START_TIME)
    public void scheduleChangeStateToShipped() {
        Set<String> set = redisService.getSetValues(OrderConstants.AWAIT_SHIP);
        for (String o : set) {
            orderService.updateOrderStateToShipped(Long.parseLong( o));
            redisService.addSetValue(OrderConstants.SHIPPED, o);
        }
        redisService.deleteValues(OrderConstants.AWAIT_SHIP);
    }

}

 

시간은 추후에 바뀔 수도 있고

휴먼에러의 여지도 높으니 constant로 따로 빼주었다.

public class OrderConstants {
    public static final String SHIP_START_TIME = "0 01 16 * * ?";
    public static final String SHIP_COMPLETE_TIME = "0 00 16 * * ?";
}

 

 

후기

다 작성해 놓고 맞왜틀!!!!! 이러고 있었는데

알고보니 component 등록을 안해줬더라 ㅎㅎㅎㅎ

@EnableScheduling

 

이것도 작성 해주어야 한다 (굳이 해주라는 거 모두 한번 씩 빼먹음 ㅎㅎㅎㅎㅎㅎ)

 

아무생각 없이 둘은 같은 시간에 두려다가

배송시작이 먼저 배송중으로 들어가버리면
데이터가 섞이지 않을까 하는 걱정이 들어

시간을 1분 차이로 두었다

 

같은 시간으로 하면 어떻게 될까 추후에 확인해 보아야겠다.