package com.zy.acs.manager.core.scheduler; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.zy.acs.manager.core.service.GuaranteeRuntimeService; import com.zy.acs.manager.manager.entity.Guarantee; import com.zy.acs.manager.manager.enums.StatusType; import com.zy.acs.manager.manager.service.GuaranteeService; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.scheduling.support.CronExpression; import org.springframework.stereotype.Component; import java.time.LocalDateTime; import java.util.List; @Slf4j @Component public class GuaranteeScheduler { @Autowired private GuaranteeService guaranteeService; @Autowired private GuaranteeRuntimeService guaranteeRuntimeService; @Value("${guarantee.scheduler.enabled:true}") private boolean enabled; @Value("${guarantee.scheduler.default-lead-minutes:60}") private int defaultLeadMinutes; @Scheduled(cron = "0/15 * * * * ?") public void drive() { if (!enabled) { return; } List plans = guaranteeService.list(new LambdaQueryWrapper() .eq(Guarantee::getDeleted, 0) .eq(Guarantee::getStatus, StatusType.ENABLE.val)); LocalDateTime now = LocalDateTime.now(); for (Guarantee plan : plans) { try { processPlan(plan, now); } catch (Exception ex) { log.error("GuaranteeScheduler failed for plan {}", plan.getName(), ex); } } } private void processPlan(Guarantee plan, LocalDateTime now) { LocalDateTime targetTime = resolveNextTarget(plan, now); if (targetTime == null) { return; } int leadMinutes = resolveLeadMinutes(plan); LocalDateTime prepareFrom = targetTime.minusMinutes(leadMinutes); if (now.isBefore(prepareFrom) || now.isAfter(targetTime)) { return; } guaranteeRuntimeService.prepare(plan, targetTime); } private LocalDateTime resolveNextTarget(Guarantee plan, LocalDateTime now) { String cronExpr = plan.getCronExpr(); if (cronExpr == null || cronExpr.trim().isEmpty()) { return null; } try { CronExpression cron = CronExpression.parse(cronExpr); return cron.next(now.minusSeconds(1)); // next(2026-02-27 08:15) => 2026-02-27 10:00:00 } catch (IllegalArgumentException ex) { log.error("Guarantee[{}] invalid cron {}", plan.getName(), cronExpr, ex); return null; } } private int resolveLeadMinutes(Guarantee plan) { return Math.max(1, plan.getLeadTime() == null ? defaultLeadMinutes : plan.getLeadTime()); } }