简体   繁体   English

下次调用之前的中断弹出调度程序任务

[英]Interrupt spring scheduler task before next invocation

I have a Spring-Boot application which is going to be an orchestration service for several other processes we want to trigger. 我有一个Spring-Boot应用程序,它将成为我们想要触发的其他几个进程的编排服务。 I have it currently set up using Spring Scheduling pulling crons dynamically from a database. 我目前使用Spring Scheduling设置动态从数据库中提取crons。 I threw in a rest method to trigger the process to pull new cron information from the database. 我抛出了一个rest方法来触发从数据库中提取新的cron信息的过程。 This logic all works correctly. 这个逻辑都正常工作。 The only "issue" is that it doesn't use the new cron information until the next scheduled run which gets to the real question. 唯一的“问题”是它不会使用新的cron信息,直到下一次计划运行才能得到真正的问题。 Is there a way to interrupt the current Trigger and schedule one again using the updated cron information. 有没有办法中断当前触发器并使用更新的cron信息再次安排一个触发器。 Here is the application for reference: 以下是申请参考:

package com.bts.poc;

import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.Trigger;
import org.springframework.scheduling.TriggerContext;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.SchedulingConfigurer;
import org.springframework.scheduling.config.ScheduledTaskRegistrar;
import org.springframework.scheduling.support.CronTrigger;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import java.util.Date;

@SpringBootApplication
@EnableScheduling
@RestController
@RequestMapping("/APSCommon/Scheduling")
public class Application implements SchedulingConfigurer {

    @Autowired
    private DynamicCron dynamicCron;
    @Autowired
    PropertyManager propertyManager;

    public static void main(String[] args) throws Exception {
        SpringApplication.run(Application.class);
    }

    private String cronConfig() {
        String cronTabExpression = propertyManager.getProperty("COMPANY", "JOB_NAME","CRON_EXPRESSION");
        return cronTabExpression;
    }

    @Override
    public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
        taskRegistrar.addTriggerTask(new Runnable() {
            @Override
            public void run() {
                dynamicCron.runJob();
            }
        }, new Trigger() {
            @Override
            public Date nextExecutionTime(TriggerContext triggerContext) {
                String cron = cronConfig();
                CronTrigger trigger = new CronTrigger(cron);
                Date nextExec = trigger.nextExecutionTime(triggerContext);
                DynamicCron.cronExpression = cron;
                return nextExec;
            }
        });
    }

    @RequestMapping(value = "/reloadScheduling", method = RequestMethod.GET)
    public String reloadScheduling() {
        PropertyManager.setResetProperties(true);
        return "schedules will be altered next run";
    }
}

So using SchedulingConfigurer->configureTasks you can't get access to the ScheduledFuture(s) in the Spring version I am using (4.2.7.RELEASE). 因此,使用SchedulingConfigurer-> configureTasks,您无法访问我正在使用的Spring版本中的ScheduledFuture(4.2.7.RELEASE)。 From several posts I have read it has been mentioned as possible functionality for the future. 从我读过的几篇文章中可以看出它是未来可能的功能。 I got around this by doing the following: 我通过以下方式解决了这个问题:

package com.bts.poc;

import com.bts.poc.service.DynamicCron;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.MessageSourceAutoConfiguration;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.context.web.SpringBootServletInitializer;
import org.springframework.context.annotation.Bean;
import org.springframework.scheduling.TaskScheduler;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
import org.springframework.scheduling.support.CronTrigger;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.ArrayList;
import java.util.List;
import java.util.TimeZone;
import java.util.concurrent.ScheduledFuture;

@SpringBootApplication(exclude = MessageSourceAutoConfiguration.class)
@EnableScheduling
@RestController
public class Application extends SpringBootServletInitializer {

    @Autowired
    private DynamicCron dynamicCron;
    @Autowired
    private PropertyManager propertyManager;
    private static List<ScheduledFuture> scheduledFutures = new ArrayList<>();
    private static final Logger LOGGER = LoggerFactory.getLogger(Application.class);
    private static TaskScheduler scheduler;

    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
        return application.sources(Application.class);
    }

    private String cronConfig() {
        return propertyManager.getProperty("COMPANY", "JOB_NAME", "CRON_EXPRESSION");
    }

    @RequestMapping(value = {"scheduling/start"}, method = RequestMethod.GET)
    public @ResponseBody String startScheduling() {
        scheduleAll();

        LOGGER.info("Scheduling of jobs has been started.");
        return "Scheduling of jobs has been started.";
    }

    @RequestMapping(value = {"scheduling/cancel"}, method = RequestMethod.GET)
    public @ResponseBody String cancelScheduling() {
        cancelAll();

        LOGGER.info("Cancelling all scheduled jobs.");
        return "Cancelling all scheduled jobs.";
    }

    private void scheduleAll() {
        LOGGER.info("Scheduling all applications to run.");
        cancelAll();

        //eventually go through the database and load all jobs to be scheduled here.
        schedule(cronConfig());
    }

    /**
     * Cancel all the scheduled reports
     */
    private void cancelAll() {
        for (ScheduledFuture scheduledFuture : scheduledFutures) {
            scheduledFuture.cancel(true);
        }
        scheduledFutures.clear();
    }

    /**
     * Schedule the scheduled report with the given cron schedule information
     */
    private void schedule(String cronSchedule) {
        TimeZone tz = TimeZone.getDefault();
        LOGGER.info("Setting up application {} to execute with cron string: '{}'.", cronSchedule);
        CronTrigger trigger = new CronTrigger(cronSchedule, tz);

        scheduler = scheduler();
        if (scheduler == null) {
            LOGGER.error("Unable to schedule job as scheduler was not found");
            return;
        }

        ScheduledFuture<?> future = scheduler.schedule(new DynamicCron(), trigger);
        scheduledFutures.add(future);
    }

    @Bean
    public TaskScheduler scheduler() {
        if (scheduler == null) {
            ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler();
            scheduler.setPoolSize(10);
            scheduler.afterPropertiesSet();
        }
        return scheduler;
    }
}

This basically replicates the functionality the ScheduledTaskRegistrar provides allowing you manage the ScheduledFuture(s). 这基本上复制了ScheduledTaskRegistrar提供的功能,允许您管理ScheduledFuture。 Hopefully this can help someone else in the future. 希望这可以在将来帮助其他人。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM