基于spring scheduling的动态job

重点是动态,cron规则保存在数据库,通过定时job去刷新数据库,获取到变更后的规则后重新刷新job,不废话,用到的人肯定知道做什么的,主要代码如下:

@Component
@EnableScheduling
@Slf4j
public class DynamicCronScheduler implements SchedulingConfigurer {

    @Autowired
    EventSubRuleFactory eventSubRuleFactory;

    @Autowired
    CronJobEventSubscriber eventSubscriber;

    @Autowired
    EventSubRuleMapper eventSubRuleMapper;

    private ScheduledTaskRegistrar taskRegistrar;

    @Autowired
    RedissonClient redisClient;

    private String md5;

    @Autowired
    ThreadPoolTaskScheduler threadPoolTaskScheduler;

    @Override
    public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
        this.taskRegistrar = taskRegistrar;
        taskRegistrar.setScheduler(threadPoolTaskScheduler);
        if (CollectionUtils.isEmpty(taskRegistrar.getTriggerTaskList())) {
            fetchCronJobs();
        }
    }

    /**
     * 定时刷新动态调度器job
     * 每小时执行一次
     */
    @Scheduled(cron = "0 0 */1 * * ?")
    public void fetchCronJobs() {
        List<EventSubRule> cornJobEventSubRules = eventSubRuleFactory.getAllCornJobEventSubRule();
        Optional<String> result = cornJobEventSubRules.stream().sorted((o1, o2) -> (int) (o1.getId() - o2.getId())).map(EventSubRule::getTopic)
                .reduce((a, b) -> a + b);
        String newMd5 = DigestUtils.md5Hex(result.orElse(""));
        if (newMd5.equals(md5)) {
            return;
        }
        if (this.taskRegistrar == null) {
            return;
        }
        // 定时触发,先清空,取消已经在执行的task
        if (CollectionUtils.isNotEmpty(taskRegistrar.getTriggerTaskList())) {
            Set<ScheduledTask> tasks = taskRegistrar.getScheduledTasks();
            for (ScheduledTask task : tasks) {
                task.cancel();
            }
            try {
                Field field = ScheduledTaskRegistrar.class.getDeclaredField("scheduledTasks");
                field.setAccessible(true);
                Set<ScheduledTask> scheduledTasks = (Set<ScheduledTask>) field.get(taskRegistrar);
                scheduledTasks.clear();
            } catch (Exception e) {
                log.error("scheduledTasks.clear failed ", e);
                return;
            }
            log.info("cron job flush start ");
        } else {
            log.info("cron job firstly fetch ");
        }
        try {
            // 查询所有的job任务
            List<TriggerTask> triggerTasks = new ArrayList<>();
            for (EventSubRule eventSubRule : cornJobEventSubRules) {
                AtomicBoolean hasError = new AtomicBoolean(false);
                Trigger trigger = triggerContext -> {
                    try {
                        String cron = eventSubRule.getTopic();
                        log.info("cron job triggered subject:{}, expression:{}", eventSubRule.getSubject(), cron);
                        CronTrigger cronTrigger = new CronTrigger(cron);
                        return cronTrigger.nextExecutionTime(triggerContext);
                    } catch (Exception e) {
                        log.info("cron job is not valid expression:{}", eventSubRule.getTopic());
                        hasError.set(true);
                        return null;
                    }
                };
                if (hasError.get()) {
                    continue;
                }
                Runnable task = () -> {
                    RLock redissonLock = redisClient.getLock(KeyUtil.buildLockKey("DynamicCronScheduler-" + eventSubRule.getId()));
                    try {
                        if (!redissonLock.tryLock(0, 5, TimeUnit.SECONDS)) {
                            return;
                        }
                    } catch (InterruptedException e) {
                        return;
                    }
                    Event cronJobEvent = new Event();
                    Map<String, Object> context = new HashMap<>();
                    Date now = new Date();
                    context.put("hour", DateUtil.hourOf(now));
                    context.put("day", DateUtil.day(now));
                    context.put("minute", DateUtil.minute(now));
                    context.put("second", DateUtil.second(now));
                    context.put("dateTimeSec", DateUtil.dateTimeSec(now));
                    context.put("dateTime", DateUtil.dateTime(now));
                    cronJobEvent.setMsgBody(context);
                    cronJobEvent.setEventId(IdUtil.simpleUUID());
                    cronJobEvent.setSubject(eventSubRule.getSubject());
                    cronJobEvent.setTimestamp(now.getTime());
                    try {
                        eventSubscriber.consume(cronJobEvent);
                    } catch (Exception e) {
                        log.error("DynamicCronSchedule run task failed,", e);
                    }
                };
                triggerTasks.add(new TriggerTask(task, trigger));
            }
            this.taskRegistrar.setTriggerTasksList(triggerTasks);
            if (StringUtils.isNotEmpty(md5)) {
                // 第一次启动不需要调用afterPropertiesSet
                taskRegistrar.afterPropertiesSet();
            }
            md5 = newMd5;
            log.info("dynamic trigger list size is {}", taskRegistrar.getTriggerTaskList().size());
        } catch (Exception e) {
            log.error("configure DynamicCronScheduleTasks failed,", e);
        }
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值