복붙노트

[SPRING] 스프링 업데이트 스케줄러

SPRING

스프링 업데이트 스케줄러

나는 봄에 예정된 직업을 가지고 있는데, 나는 내 데이터베이스에서 그 cron을 얻는다. 실행될 때마다 다음 실행 시간이 업데이트됩니다. 따라서 매 10 분마다 실행되도록 구성하면 데이터베이스에 값을 변경하여 매 15 분마다 해당 작업을 예약 할 수 있습니다.

문제는 업데이트 된 cron을 얻기 위해 실행을 기다려야한다는 것입니다. 작업이 15 분마다 스케줄되고 2 분마다이 값을 변경하려면 다음 실행 (최대 15 분)을 기다려야합니다. 분) 2 분 마다이 일을해야합니다.

데이터베이스를 업데이트 한 후이 작업을 다시 스케줄 할 수있는 방법이 있습니까?

나는이 빈을 파괴하고 새로 고침 할 생각을했으나 작동하지 않습니다 (어쩌면 불가능하거나 뭔가 잘못되었습니다). 어쩌면 이벤트를 트리거하여 configureTask 메소드를 실행하는 방법이있을 수 있습니다.

여기 내 예정된 일의 미리보기.

@EnableScheduling
@Component
public class MyClass implements SchedulingConfigurer {

    private static final String JOB = "My personal task";

    @Autowired
    JobRepository jobRepository;

    @Override
    public void configureTasks(ScheduledTaskRegistrar scheduledTaskRegistrar) {
        scheduledTaskRegistrar.addTriggerTask(new Runnable() {
            @Override
            public void run() {
                System.out.println("Hello World!");
            }
        }, new Trigger() {
            @Override
            public Date nextExecutionTime(TriggerContext triggerContext) {
                JobScheduled byJobNameIgnoreCase = jobRepository.findByJobNameIgnoreCase(JOB); // read from database 
                String cron = byJobNameIgnoreCase.getCrontab();
                CronTrigger trigger = new CronTrigger(cron);
                return trigger.nextExecutionTime(triggerContext);
            }
        });
    }

}

해결법

  1. ==============================

    1.이를 관리하기 위해 필자는 작업을 관리하는 SchedulerOrchestrator를 만들었습니다. 작업에는 SchedulerFuture가 포함됩니다.

    이를 관리하기 위해 필자는 작업을 관리하는 SchedulerOrchestrator를 만들었습니다. 작업에는 SchedulerFuture가 포함됩니다.

    여기에 내가 희망하는 코드는 다른 사람을 도울 수 있습니다.

    내 작업에서 구현할 인터페이스로 시작해 보겠습니다.

    public interface SchedulerObjectInterface {    
        void start();
        void stop();
    }
    

    모든 작업은 중지하기 위해 ScheduledFuture를 필요로하며 TaskScheduler를 스케줄링하기 위해 autowire해야합니다. 다음은 한 가지 작업 샘플입니다 (원하는만큼 만들 수 있음).

    @Component
    public class MyFirstJob implements SchedulerObjectInterface {
    
        private static final Logger log = LoggerFactory.getLogger(MyFirstJob.class);
    
        public static final String JOB = "MyFirstJob";
    
        @Autowired
        JobRepository jobRepository;
    
        private ScheduledFuture future;
    
        @Autowired
        private TaskScheduler scheduler;
    
    
        @Override
        public void start() {
            future = scheduler.schedule(new Runnable() {
                @Override
                public void run() {
                    System.out.println(JOB + "  Hello World! " + new Date());
                }
            }, new Trigger() {
                @Override
                public Date nextExecutionTime(TriggerContext triggerContext) {
                    String cron = cronConfig();
                    System.out.println(cron);
                    CronTrigger trigger = new CronTrigger(cron);
                    return trigger.nextExecutionTime(triggerContext);
                }
            });
    
        }
    
        @Override
        public void stop() {
            future.cancel(false);
        }
    
        // retrieve cron from database
        private String cronConfig() {
            JobScheduled byJobNameIgnoreCase = jobRepository.findByJobNameIgnoreCase(JOB);
            return byJobNameIgnoreCase.getCrontab();
        }
    
    }
    

    마지막으로 작업을 오케 스트레이터에 추가 할 수 있습니다.

    @Configuration
    public class SchedulerOrchestrator {
    
        private static final Logger log = LoggerFactory.getLogger(SchedulerOrchestrator.class);
    
        private static Map<String, SchedulerObjectInterface> schduledJobsMap = new HashMap<>();
    
        @Autowired
        JobRepository jobRepository;
    
        @Autowired
        MyFirstJob myFirstJob;
    
        @Autowired
        MySecondJob mySecondJob;
    
        @Autowired
        TaskScheduler scheduler;
    
        @PostConstruct
        public void initScheduler() {
            schduledJobsMap.put(MyFirstJob.JOB, myFirstJob);
            schduledJobsMap.put(MySecondJob.JOB, mySecondJob);
    
            startAll();
        }
    
        public void restart(String job) {
            stop(job);
            start(job);
        }
    
        public void stop(String job) {
            schduledJobsMap.get(job).stop();
        }
    
        public void start(String job) {
            schduledJobsMap.get(job).start();
        }
    
        public void startAll() {
            for (SchedulerObjectInterface schedulerObjectInterface : schduledJobsMap.values()) {
                schedulerObjectInterface.start();
            }
        }
    
        @Bean
        public TaskScheduler scheduler() {
            return new ThreadPoolTaskScheduler();
        }
    }
    
  2. ==============================

    2.이 방법을 고려하십시오. 예약 된 작업을 추가 및 삭제하는 대신 실제 순간을 매분 (또는 다른 정밀도로) 점검하여 필요한 작업을 즉시 실행할 수 있습니다. 이것은 더 쉬울 것이다. Quartz Scheduler를 확인하면 CronExpression에 isSatisfiedBy (Date date) 메소드가 있습니다.

    이 방법을 고려하십시오. 예약 된 작업을 추가 및 삭제하는 대신 실제 순간을 매분 (또는 다른 정밀도로) 점검하여 필요한 작업을 즉시 실행할 수 있습니다. 이것은 더 쉬울 것이다. Quartz Scheduler를 확인하면 CronExpression에 isSatisfiedBy (Date date) 메소드가 있습니다.

    @Scheduled(cron = "5 * * * * *) // do not set seconds to zero, cause it may fit xx:yy:59
    public void runTasks() {
         LocalTime now = LocalTime.now(); // or Date now = new Date();
        // check and run
    }
    
  3. from https://stackoverflow.com/questions/41186633/spring-update-scheduler by cc-by-sa and MIT license