puzhibing
2026-04-24 929332664363a6e496fa0367b08aa2c3689ad8fe
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
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
package com.xiaopeng.map.schedule;
 
import com.xiaopeng.api.model.operation.XpElectronicFence;
import com.xiaopeng.map.service.XpElectronicFenceService;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
 
import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
 
/**
 * 电子围栏失效补偿定时任务
 */
@Slf4j
@Component
public class ElectronicFenceFailureCompensationTask {
 
    private static final String LOCK_KEY = "MAP:ELECTRONIC_FENCE:FAILURE_COMPENSATE";
    private static final String LOCK_KEY_ENABLE = "MAP:ELECTRONIC_FENCE:ENABLE_COMPENSATE";
    private static final int LOCK_WAIT_SECONDS = 0;
    private static final int LOCK_LEASE_SECONDS = 15;
 
    @Resource
    private XpElectronicFenceService xpElectronicFenceService;
 
    @Resource
    private RedissonClient redissonClient;
 
 
    /**
     * 定时任务 围栏失效补偿定时任务
     */
    @Scheduled(fixedDelay = 10 * 1000L)
    public void compensateExpiredFence() {
        RLock lock = redissonClient.getLock(LOCK_KEY);
        boolean locked = false;
        try {
            locked = lock.tryLock(LOCK_WAIT_SECONDS, LOCK_LEASE_SECONDS, TimeUnit.SECONDS);
            if (!locked) {
                return;
            }
 
            LocalDateTime now = LocalDateTime.now();
            List<XpElectronicFence> expiredFenceList = xpElectronicFenceService.lambdaQuery()
                    .eq(XpElectronicFence::getFailureType, 2)
                    .le(XpElectronicFence::getFailureTime, now)
                    .in(XpElectronicFence::getStatus, 1, 2)
                    .list();
            if (expiredFenceList == null || expiredFenceList.isEmpty()) {
                return;
            }
 
            List<Long> electronicIds = expiredFenceList.stream()
                    .map(XpElectronicFence::getId)
                    .collect(Collectors.toList());
            log.info("电子围栏失效补偿开始, count={}, ids={}", electronicIds.size(), electronicIds);
            for (Long electronicId : electronicIds) {
                try {
                    xpElectronicFenceService.expireFence(electronicId);
                } catch (Exception e) {
                    log.error("电子围栏失效补偿单条处理异常, electronicId={}", electronicId, e);
                }
            }
            log.info("电子围栏失效补偿完成, count={}, ids={}", electronicIds.size(), electronicIds);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            log.warn("电子围栏失效补偿任务获取锁被中断", e);
        } catch (Exception e) {
            log.error("电子围栏失效补偿任务执行异常", e);
        } finally {
            try {
                if (locked && lock.isHeldByCurrentThread()) {
                    lock.unlock();
                }
            } catch (Exception e) {
                log.warn("释放电子围栏失效补偿锁失败 lockKey={}", LOCK_KEY, e);
            }
        }
    }
 
    /**
     * 围栏启动偿定时任务
     */
    @Scheduled(fixedDelay = 10 * 1000L)
    public void compensateEnableFence() {
        RLock lock = redissonClient.getLock(LOCK_KEY_ENABLE);
        boolean locked = false;
        try {
            locked = lock.tryLock(LOCK_WAIT_SECONDS, LOCK_LEASE_SECONDS, TimeUnit.SECONDS);
            if (!locked) {
                return;
            }
            List<XpElectronicFence> expiredFenceList = xpElectronicFenceService.lambdaQuery()
                    .eq(XpElectronicFence::getDeleted, 0)
                    .eq(XpElectronicFence::getStatus, 1)//围栏状态 0=草稿 1=待启用 2=启用中 3=已停用
                    .ge(XpElectronicFence::getFailureTime, LocalDateTime.now())//当前时间小于生效时间
                    .list();
            if (expiredFenceList == null || expiredFenceList.isEmpty()) {
                return;
            }
            List<Long> electronicIds = expiredFenceList.stream()
                    .map(XpElectronicFence::getId)
                    .collect(Collectors.toList());
            log.info("电子围栏失效补偿开始, count={}, ids={}", electronicIds.size(), electronicIds);
            for (Long electronicId : electronicIds) {
                try {
                    xpElectronicFenceService.enableFence(electronicId);
                } catch (Exception e) {
                    log.error("电子围栏失效补偿单条处理异常, electronicId={}", electronicId, e);
                }
            }
            log.info("电子围栏失效补偿完成, count={}, ids={}", electronicIds.size(), electronicIds);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            log.warn("电子围栏失效补偿任务获取锁被中断", e);
        } catch (Exception e) {
            log.error("电子围栏失效补偿任务执行异常", e);
        } finally {
            try {
                if (locked && lock.isHeldByCurrentThread()) {
                    lock.unlock();
                }
            } catch (Exception e) {
                log.warn("释放电子围栏失效补偿锁失败 lockKey={}", LOCK_KEY, e);
            }
        }
    }
}