mitao
2024-07-20 1f3e9dc85399290910cde7149806323305544e0d
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
package com.ruoyi.auction.service.async;
 
import com.ruoyi.common.core.constant.SecurityConstants;
import com.ruoyi.common.core.utils.StringUtils;
import com.ruoyi.common.redis.service.RedisService;
import com.ruoyi.system.api.constants.DelayTaskEnum;
import com.ruoyi.system.api.domain.AuctionGoods;
import com.ruoyi.system.api.domain.DelayTask;
import com.ruoyi.system.api.feignClient.SysUserClient;
import java.time.Duration;
import java.time.LocalDateTime;
import java.util.List;
import java.util.concurrent.TimeUnit;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
 
/**
 * @author mitao
 * @date 2024/5/24
 */
@Service
@Slf4j
@RequiredArgsConstructor
public class AuctionAsyncMethodService {
 
    private final RedisService redisService;
    private final SysUserClient sysUserClient;
 
    @Async
    @Transactional(rollbackFor = Exception.class)
    public void auctionGoodsScheduleTask(List<AuctionGoods> auctionGoodsList) {
        log.info("开始执行定时任务");
        for (AuctionGoods auctionGoods : auctionGoodsList) {
            LocalDateTime startTime = auctionGoods.getStartTime();
            LocalDateTime endTime = auctionGoods.getEndTime();
            // 普通拍品在一小时内开始
            if (isWithinOneHour(startTime)) {
                Long id = auctionGoods.getId();
                // 普通拍品已经开始,三秒后执行
                if (LocalDateTime.now().isAfter(startTime)) {
                    handleStartDelayTask(id, DelayTaskEnum.AUCTION_GOODS_START_TASK, startTime, 3L);
                } else {
                    Duration duration = Duration.between(LocalDateTime.now(), startTime);
                    handleStartDelayTask(id, DelayTaskEnum.AUCTION_GOODS_START_TASK, startTime,
                            duration.getSeconds());
                }
                // 普通拍品结束延时任务
                handleEndDelayTask(id, DelayTaskEnum.AUCTION_GOODS_END_TASK, endTime);
            }
        }
    }
 
    private boolean isWithinOneHour(LocalDateTime startTime) {
        LocalDateTime checkTime = LocalDateTime.now().plusMinutes(61);
        return checkTime.isAfter(startTime);
    }
 
    private void handleEndDelayTask(Long id, DelayTaskEnum delayTaskEnum, LocalDateTime endTime) {
        String endTaskKey = delayTaskEnum.getCode() + "-" + id;
        DelayTask endDelayTask = sysUserClient.getDelayTask(
                endTaskKey, SecurityConstants.INNER).getData();
        // 如果延时任务为空,创建延时任务控制活动定时开始和结束
        Duration duration = Duration.between(LocalDateTime.now(), endTime);
        if (StringUtils.isNull(endDelayTask)) {
            createEndDelayTask(endTime, endTaskKey, duration);
        } else {
            if (!endDelayTask.getExecuteTime().isEqual(endTime)) {
                sysUserClient.deleteDelayTask(endTaskKey,
                        SecurityConstants.INNER);
                redisService.deleteObject(endTaskKey);
                createEndDelayTask(endTime, endTaskKey, duration);
            }
        }
        log.info(">>>>>>>>>>>>>>>>>>>>延时任务{}执行了<<<<<<<<<<<<<<<<<<<<", endTaskKey);
    }
 
    private void createEndDelayTask(LocalDateTime endTime, String seckillEndTaskKey,
            Duration duration) {
        DelayTask endDelayTask;
        redisService.setCacheObject(
                seckillEndTaskKey,
                endTime, duration.getSeconds(), TimeUnit.SECONDS);
        endDelayTask = new DelayTask();
        endDelayTask.setDelFlag(0);
        endDelayTask.setCreateTime(LocalDateTime.now());
        endDelayTask.setExecuteTime(endTime);
        endDelayTask.setRedisKey(seckillEndTaskKey);
        sysUserClient.addDelayTask(endDelayTask, SecurityConstants.INNER);
    }
 
    private void handleStartDelayTask(Long id, DelayTaskEnum delayTaskEnum, LocalDateTime startTime,
            Long timeout) {
        String startTaskKey = delayTaskEnum.getCode() + "-" + id;
        // 查询延时任务
        DelayTask startDelayTask = sysUserClient.getDelayTask(
                startTaskKey, SecurityConstants.INNER).getData();
        if (StringUtils.isNull(startDelayTask)) {
            startDelayTask = new DelayTask();
            startDelayTask.setDelFlag(0);
            startDelayTask.setCreateTime(LocalDateTime.now());
            startDelayTask.setExecuteTime(LocalDateTime.now().plusSeconds(timeout));
            startDelayTask.setRedisKey(
                    startTaskKey);
            sysUserClient.addDelayTask(startDelayTask, SecurityConstants.INNER);
        } else {
            if (!startDelayTask.getExecuteTime().isEqual(startTime)) {
                sysUserClient.deleteDelayTask(startTaskKey, SecurityConstants.INNER);
                redisService.deleteObject(startTaskKey);
                startDelayTask.setDelFlag(0);
                startDelayTask.setCreateTime(LocalDateTime.now());
                startDelayTask.setExecuteTime(LocalDateTime.now().plusSeconds(timeout));
                startDelayTask.setRedisKey(
                        startTaskKey);
                sysUserClient.addDelayTask(startDelayTask, SecurityConstants.INNER);
            }
        }
        redisService.setCacheObject(startTaskKey, startTime, timeout, TimeUnit.SECONDS);
        log.info(">>>>>>>>>>>>>>>>>>>>延时任务{}执行了<<<<<<<<<<<<<<<<<<<<", startTaskKey);
    }
}