2 분 소요

Quartz 테스트 코드와 매커니즘

  • 아래 코드는 매주 월요일 오전 10시에 실행되도록 설정된 Quartz 테스트 코드이다.
  • 매주 월요일 실행되는지 테스트하기 위해 Window의 시스템 시간을 변경하여 테스트하였다.
  • 테스트 중 특정 날짜에 실행되지 않는 현상이 발생하게 되어 원인을 찾아보았다.


  • 원인 : 어플리케이션을 실행하는 시간(Job과 Trigger가 등록된 시간) 보다 Trigger 실행 시간이 이전일 수 없다.
  • 이해를 돕기 위해 예를 들어보자.
    • Trigger의 실행 규칙을 0 0 10 ? * MON 이렇다. 매주 월요일 오전 10시
    • 현재 시스템 시간을 24/6/10 오전 10시10분으로 설정했다고 해보자.
      (실제 날짜는 24/6/4 이었는데, 여러번의 테스트로 인해 변경되어 있던 상황)
    • 이 상태에서 어플리케이션을 실행하면 Job과 Trigger24/6/10 오전 10시10분로 설정된다.
    • 그리고 테스트를 위해 시스템 날짜를 24/6/10 오전 9시59분으로 맞췄다. 그럼 1분 후 Quartz가 실행될 것이다.
    • 그런데 실행되지 않았다. 24/6/17 오전 9시59분 으로 설정 하고 했더니 실행되었다.
    • 이해가 되는가?
    • 어플리케이션이 실행되면서 Job과 Trigger24/6/10 오전 10시10분로 설정되었기 때문에 이전 날짜에는 Trigge가 작동하지 않는다.
@Component        // spring bean 등록
@Profile("demo")  // 지정한 profile에서만 실행하도록 설정. 즉 demo가 active 된 경우에만 실행되는 class로 지정한 것.
public class SchedulerLocalMangement {
	private SchedulerFactory schedulerFactory;  // 스케줄러 생성 객체
  private Scheduler scheduler;                // 스케줄 작업 관리 객체
    
  @PostConstruct  // Spring 컨텍스트가 초기화 된 후에 호출한다.
  public void start() throws SchedulerException{
  
    schedulerFactory = new StdSchedulerFactory();   // StdSchedulerFactory 인스턴스 생성한다.
    scheduler = schedulerFactory.getScheduler();    // scheduler 인스턴스를 가져온다.
    /**
     * 스케줄러 시작
     * 스케줄러를 실행 준비 상태로 만든다.
     * 이후 등록 된(또는 등록 될) job과 trigger의 실행 시간을 기다린다.
     * 여기서 job과 trigger의 등록 시점은 중요하지 않다. start() 이전 이어도 되고 이후 이어도 된다.
     */
    scheduler.start();
      
    /**
     * Job 정의
     */
    JobDetail jobDetail = JobBuilder.newJob(SmsQuartzJob.class).withIdentity("SmsQuartzJob").build();
  
    /**
     * Trigger 등록
     * cron : 초 분 시 일 월 요일
     */
    // 
    Trigger trigger = TriggerBuilder.newTrigger().
        withSchedule(CronScheduleBuilder.cronSchedule("0 0 10 ? * MON")).build();
    
    /**
     * JobDetail과 Trigger를 스케줄러에 등록한다.
     * Job과 Trigger가 등록되는 시간 보다 trigger의 시작시간이 이후여야 한다.
     */ 
    scheduler.scheduleJob(jobDetail, trigger);
  }
}



Quartz Cron 격주 설정 예제

@Component  // spring bean 등록
@Profile("demo")  // 지정한 profile에서만 실행
public class SchedulerLocalMangement {
	private SchedulerFactory schedulerFactory;
  private Scheduler scheduler;
    
  @PostConstruct
  public void start() throws SchedulerException{
    
    JobDetail receiptDelayLongSmsQuartzJob = JobBuilder.newJob(SmsQuartzJob.class)
      .withIdentity("smsQuartzJob")
      .build();
  
    /**
     * 시간 설정
     * - 월요일 오전 10시로 시작 시간 설정
     */ 
    Calendar startTime = Calendar.getInstance();
    startTime.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY);
    startTime.set(Calendar.HOUR_OF_DAY, 10);
    startTime.set(Calendar.MINUTE, 0);
    startTime.set(Calendar.SECOND, 0);
    startTime.set(Calendar.MILLISECOND, 0);

    // 설정한 시간이 현재시간 보다 이전일 경우 시작 시간을 다음주로 설정
    if (startTime.getTime().before(new Date())) {
        startTime.add(Calendar.WEEK_OF_YEAR, 1);
    }
    
    
    /**
     * Trigger 등록
     * 초 분 시 일 월 요일
     */ 
    Trigger triggerReceiptDelayLongSms = TriggerBuilder.newTrigger()
        .startAt(startTime.getTime())
        .withSchedule(CalendarIntervalScheduleBuilder.calendarIntervalSchedule()
            .withIntervalInWeeks(2)).build();
//				withSchedule(CronScheduleBuilder.cronSchedule("0 10 10 ? * 1#2, 1#4")).build();
    
    scheduler.scheduleJob(receiptDelayLongSmsQuartzJob, triggerReceiptDelayLongSms);
    
  }
}

댓글남기기