#
vincentlu
2 天以前 971560de6386d87ee9e05be038fd4571865a1def
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
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.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 {
 
    private final GuaranteeService guaranteeService;
    private final GuaranteeRuntimeService guaranteeRuntimeService;
 
    @Value("${guarantee.scheduler.enabled:true}")
    private boolean enabled;
    @Value("${guarantee.scheduler.default-lead-minutes:60}")
    private int defaultLeadMinutes;
 
    public GuaranteeScheduler(GuaranteeService guaranteeService,
                              GuaranteeRuntimeService guaranteeRuntimeService) {
        this.guaranteeService = guaranteeService;
        this.guaranteeRuntimeService = guaranteeRuntimeService;
    }
 
    @Scheduled(cron = "0/15 * * * * ?")
    public void drive() {
        if (!enabled) {
            return;
        }
        List<Guarantee> plans = guaranteeService.list(new LambdaQueryWrapper<Guarantee>()
                .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());
    }
}