Планировщик весенних обновлений

У меня есть запланированная работа в 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);
            }
        });
    }

}

person Daniele Bizzozero    schedule 16.12.2016    source источник
comment
Я нашел эту ссылку, но она не работает.. [stackoverflow.com/questions/39152599/   -  person Daniele Bizzozero    schedule 17.12.2016


Ответы (2)


Для этого я создал SchedulerOrchestrator, который управляет моими заданиями. Задания содержат SchedulerFuture.

Вот код, который, я надеюсь, может помочь кому-то еще.

Начнем с интерфейса, который будет реализован моими заданиями:

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

Каждое задание нуждается в ScheduledFuture для остановки и должно автоматически связать TaskScheduler для планирования. Вот пример одной работы (вы можете создать сколько угодно):

@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();
    }
}
person Daniele Bizzozero    schedule 19.12.2016

Рассмотрим этот подход. Вместо того, чтобы добавлять и удалять запланированные задачи, вы можете сверять каждую минуту (или с другой точностью) актуальный момент с вашими представлениями и немедленно запускать необходимые задачи. Это будет проще. Проверьте 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
}
person Andriy Slobodyanyk    schedule 13.11.2017