“mitao”
2026-04-10 2b306afe79cd8096dd9394b0d8d04ff467b7e09c
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
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 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);
            }
        }
    }
}