diff --git a/luoo_common/src/main/java/enums/PointEnums.java b/luoo_common/src/main/java/enums/PointEnums.java index 7267058..2f40359 100644 --- a/luoo_common/src/main/java/enums/PointEnums.java +++ b/luoo_common/src/main/java/enums/PointEnums.java @@ -30,6 +30,8 @@ public enum PointEnums { LOTTERY_STATUS_LOTTERY(2, "已抽奖"), LOTTERY_STATUS_STOP(3, "已停止"), + LOTTERY_STATUS_PUSH(1, "已推送"), + LOTTERY_WAY_AUTO(1, "自动抽奖"), LOTTERY_WAY_MANUAL(2, "手动抽奖"), diff --git a/luoo_user/src/main/java/com/luoo/user/Scheduler/SendLotteryResultScheduler.java b/luoo_user/src/main/java/com/luoo/user/Scheduler/SendLotteryResultScheduler.java new file mode 100644 index 0000000..46b37fc --- /dev/null +++ b/luoo_user/src/main/java/com/luoo/user/Scheduler/SendLotteryResultScheduler.java @@ -0,0 +1,117 @@ +package com.luoo.user.Scheduler; + +import com.luoo.user.pojo.Lottery; +import com.luoo.user.service.DrawLotteryService; +import com.luoo.user.service.SendLotteryService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler; +import org.springframework.stereotype.Component; + +import javax.annotation.PostConstruct; +import javax.annotation.PreDestroy; +import java.time.Instant; +import java.time.LocalDateTime; +import java.time.ZoneId; +import java.util.Date; +import java.util.List; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ScheduledFuture; + +/** + * @program: luoo_parent + * @description: 发送开奖结果 + * @author: yawei.huang + * @create: 2024-12-06 18:58 + **/ +@Slf4j +@Component +@Configuration +public class SendLotteryResultScheduler { + + private static final String TASK_NAME_PREFIX = "sendLotteryResult"; + + private final ThreadPoolTaskScheduler taskScheduler = new ThreadPoolTaskScheduler(); + + private ScheduledFuture scheduledFuture; + + private final ConcurrentHashMap> scheduledFutures = new ConcurrentHashMap<>(); + + private final SendLotteryService sendLotteryService; + + public SendLotteryResultScheduler(SendLotteryService sendLotteryService) { + this.sendLotteryService = sendLotteryService; + } + + @PostConstruct + public void init() { + taskScheduler.initialize(); + log.info("sendLotteryResultScheduler init"); + List finishList = sendLotteryService.findFinishList(); + finishList.forEach(item -> { + scheduleSendLotteryResult(item.getDrawTime(), item.getId()); + }); + } + + @PreDestroy + public void destroy() { + taskScheduler.shutdown(); + } + + public String scheduleSendLotteryResult(LocalDateTime sendTime, String id) { + String result = ""; + + ScheduledFuture existingFuture = scheduledFutures.get(TASK_NAME_PREFIX + id); + if (existingFuture != null && !existingFuture.isCancelled()) { + cancelSendLotteryResult(id); + } + // 将 LocalDateTime 转换为 Instant,然后获取毫秒数 + ZoneId zoneId = ZoneId.systemDefault(); + Instant instant = sendTime.atZone(zoneId).toInstant(); + long delay = instant.toEpochMilli() - System.currentTimeMillis(); + + if (delay > 0) { + scheduledFuture = taskScheduler.schedule(() -> { + // 这里执行操作 + log.info("发送消息id{}", id); + try { + sendLotteryService.sendLotteryResultMessage(id.replace(TASK_NAME_PREFIX, "")); + } catch (Exception e) { + e.printStackTrace(); + } + + }, new Date(System.currentTimeMillis() + delay)); + + scheduledFutures.put(TASK_NAME_PREFIX + id, scheduledFuture); + log.info("scheduleDraw--------:{}", scheduledFutures); + } else { + // 处理时间已过的情况 + // 立即抽奖 + try { + sendLotteryService.sendLotteryResultMessage(id.replace(TASK_NAME_PREFIX, "")); + } catch (Exception e) { + e.printStackTrace(); + result = e.getMessage(); + } + } + return result; + } + + public void cancelSendLotteryResult(String id) { + ScheduledFuture scheduledFuture = scheduledFutures.get(TASK_NAME_PREFIX + id); + // 检查 ScheduledFuture 是否存在 + if (scheduledFuture != null) { + // 取消任务并尝试中断正在执行的任务 + boolean canceled = scheduledFuture.cancel(true); + if (canceled) { + log.info("Task with ID {} was canceled.", id); + } else { + log.info("Task with ID {} could not be canceled.", id); + } + // 从映射中移除该 ID 的条目 + scheduledFutures.remove(id); + } else { + log.info("No task found with ID: {}", id); + } + } +} diff --git a/luoo_user/src/main/java/com/luoo/user/pojo/Lottery.java b/luoo_user/src/main/java/com/luoo/user/pojo/Lottery.java index d7208e1..600f4c0 100644 --- a/luoo_user/src/main/java/com/luoo/user/pojo/Lottery.java +++ b/luoo_user/src/main/java/com/luoo/user/pojo/Lottery.java @@ -168,4 +168,7 @@ public class Lottery implements Serializable { @ApiModelProperty(value = "本人是否参与抽奖 1-已参加 2-未参加") private Integer isParticipate; + @ApiModelProperty(value = "结果是否已推送 1-已推送") + private Integer sendType; + } \ No newline at end of file diff --git a/luoo_user/src/main/java/com/luoo/user/service/DrawLotteryService.java b/luoo_user/src/main/java/com/luoo/user/service/DrawLotteryService.java index 3ede4bd..53f9649 100644 --- a/luoo_user/src/main/java/com/luoo/user/service/DrawLotteryService.java +++ b/luoo_user/src/main/java/com/luoo/user/service/DrawLotteryService.java @@ -1,22 +1,17 @@ package com.luoo.user.service; +import com.luoo.user.Scheduler.SendLotteryResultScheduler; import com.luoo.user.dao.LotteryDao; import com.luoo.user.dao.LotteryRegionDao; import com.luoo.user.dao.LotteryUserDao; -import com.luoo.user.dao.UserInfoDao; import com.luoo.user.pojo.Lottery; import com.luoo.user.pojo.LotteryRegion; import com.luoo.user.pojo.LotteryUser; -import com.luoo.user.pojo.UserInfo; -import constants.Constants; import constants.ErrorConstants; import dto.UserLoginDto; -import dto.UserMessageDto; -import enums.MessageTypeEnum; import enums.PointEnums; import exception.BizException; import org.apache.commons.lang.StringUtils; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import util.JwtUtil; @@ -33,24 +28,6 @@ import java.util.*; @Service public class DrawLotteryService { - // 中奖信息 - String[] winLotteryMessages = { - "恭喜你中奖了,你的运气真是太好了,连我都想跟你借钱买彩票了!", - "看来你的运气被幸运星咬了一口,中了个大奖!", - "你这是中了头奖,是不是昨晚做梦都在笑啊?", - "你的手气真是好得不得了,我都怀疑你是不是偷偷摸摸地跟财神爷打了招呼!", - "恭喜你中奖,你这是要发家致富的节奏啊!", - "你这是要把彩票中心吃垮的节奏啊,中了这么多奖!", - "你的运气真是好得让人眼红,我都想拜你为师,学学怎么中奖!", - "你的中奖概率比被闪电击中还低,你真是天生的幸运儿!", - "你的中奖记录比我的恋爱记录还丰富,真是让人羡慕嫉妒恨!", - "恭喜你中奖,你这是要成为我们朋友圈的土豪啊!", - "你这是要把彩票中心的钱都赢光,让他们破产吗?", - "你的中奖运气真是让人羡慕,我都想去拜拜财神爷,看看能不能沾沾你的光!", - "你的中奖记录比我的考试成绩还高,真是让人佩服得五体投地!", - "恭喜你中奖,你这是要成为我们村里的大富翁啊!" - }; - private final LotteryDao lotteryDao; private final LotteryRegionDao lotteryRegionDao; @@ -59,17 +36,15 @@ public class DrawLotteryService { private final JwtUtil jwtUtil; - private final UserMessageService userMessageService; + private final SendLotteryResultScheduler sendLotteryResultScheduler; - private final UserInfoDao userInfoDao; - public DrawLotteryService(LotteryDao lotteryDao, LotteryRegionDao lotteryRegionDao, LotteryUserDao lotteryUserDao, JwtUtil jwtUtil, UserMessageService userMessageService, UserInfoDao userInfoDao) { + public DrawLotteryService(LotteryDao lotteryDao, LotteryRegionDao lotteryRegionDao, LotteryUserDao lotteryUserDao, JwtUtil jwtUtil, SendLotteryResultScheduler sendLotteryResultScheduler) { this.lotteryDao = lotteryDao; this.lotteryRegionDao = lotteryRegionDao; this.lotteryUserDao = lotteryUserDao; this.jwtUtil = jwtUtil; - this.userMessageService = userMessageService; - this.userInfoDao = userInfoDao; + this.sendLotteryResultScheduler = sendLotteryResultScheduler; } public List findSigningList() { @@ -77,6 +52,7 @@ public class DrawLotteryService { } + /** * 自动抽奖结果 * @@ -120,6 +96,11 @@ public class DrawLotteryService { // 抽奖状态为报名中,自动抽奖 lottery.setStatus(PointEnums.LOTTERY_STATUS_LOTTERY.getCode()); lotteryDao.save(lottery); + + String result = sendLotteryResultScheduler.scheduleSendLotteryResult(lottery.getDrawTime(), lottery.getId()); + if (StringUtils.isNotBlank(result)) { + throw new BizException(result); + } } } @@ -142,21 +123,6 @@ public class DrawLotteryService { // 全部中奖 winnerList = lotteryUserList; } - lotteryUserList.forEach(lotteryUser -> { - UserMessageDto userMessageDto = new UserMessageDto(); - userMessageDto.setType(MessageTypeEnum.SYSTEM_MESSAGE.getType()); - userMessageDto.setTitle("开奖通知"); - String userId = lotteryUser.getUserId(); -// 你参与的“落网10周年纪念CD抽嚳磴㡳跆活动”已经开奖 - String content = "您参与的活动 " + lottery.getTitle() + " 已经开奖"; - userMessageDto.setContent(content); - userMessageDto.setObjectId(lottery.getId()); - userMessageDto.setObjectType("lottery"); - userMessageDto.setObjectCover(lottery.getImage()); - userMessageDto.setUserId(userId); - userMessageService.sendUserMessage(userMessageDto); - }); - winnerList.forEach(lotteryUser -> { lotteryUser.setResult(PointEnums.LOTTERY_RESULT_WIN.getCode()); @@ -165,28 +131,6 @@ public class DrawLotteryService { lotteryUser.setUpdateUser(userLoginDto.getUserId()); } lotteryUserDao.save(lotteryUser); - - // 发送恭喜中奖站内信 - UserMessageDto userMessageDto = new UserMessageDto(); -// userMessageDto.setType(MessageTypeEnum.PRIVATE_MESSAGE.getType()); - userMessageDto.setType(MessageTypeEnum.SYSTEM_MESSAGE.getType()); -// userMessageDto.setSendUserId(StringUtils.isNotBlank(token) ? jwtUtil.getUserLoginDto(token).getUserId() : null); - userMessageDto.setTitle("恭喜中奖!"); - - String userId = lotteryUser.getUserId(); - UserInfo userInfo = userInfoDao.getById(userId); - - String content = "亲爱的" + userInfo.getNickName() + ",您在积分抽奖 " + lottery.getTitle() + " 中幸运中奖!"; - userMessageDto.setObjectId(lottery.getId()); - userMessageDto.setObjectType("lottery"); - userMessageDto.setObjectCover(lottery.getImage()); - // winLotteryMessages 随机选取一条 - userMessageDto.setContent(content + winLotteryMessages[new Random().nextInt(winLotteryMessages.length)]); - userMessageDto.setUserId(userId); -// userMessageDto.setSendUserAvatar(Constants.RESOURCE_PREFIX + (StringUtils.isNotBlank(token) ? jwtUtil.getUserLoginDto(token).getAvatar() : null)); -// userMessageDto.setSendUserNickName(StringUtils.isNotBlank(token) ? jwtUtil.getUserLoginDto(token).getNickName() : null); - - userMessageService.sendUserMessage(userMessageDto); }); } diff --git a/luoo_user/src/main/java/com/luoo/user/service/SendLotteryService.java b/luoo_user/src/main/java/com/luoo/user/service/SendLotteryService.java new file mode 100644 index 0000000..8f137ec --- /dev/null +++ b/luoo_user/src/main/java/com/luoo/user/service/SendLotteryService.java @@ -0,0 +1,121 @@ +package com.luoo.user.service; + +import com.luoo.user.dao.LotteryDao; +import com.luoo.user.dao.LotteryUserDao; +import com.luoo.user.dao.UserInfoDao; +import com.luoo.user.pojo.Lottery; +import com.luoo.user.pojo.LotteryUser; +import com.luoo.user.pojo.QLottery; +import com.luoo.user.pojo.UserInfo; +import com.querydsl.jpa.impl.JPAQueryFactory; +import dto.UserMessageDto; +import enums.MessageTypeEnum; +import enums.PointEnums; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +import java.util.List; +import java.util.Objects; +import java.util.Random; + +/** + * @program: luoo_parent + * @description: + * @author: yawei.huang + * @create: 2024-12-06 19:20 + **/ +@Service +@Slf4j +public class SendLotteryService { + + // 中奖信息 + String[] winLotteryMessages = { + "恭喜你中奖了,你的运气真是太好了,连我都想跟你借钱买彩票了!", + "看来你的运气被幸运星咬了一口,中了个大奖!", + "你这是中了头奖,是不是昨晚做梦都在笑啊?", + "你的手气真是好得不得了,我都怀疑你是不是偷偷摸摸地跟财神爷打了招呼!", + "恭喜你中奖,你这是要发家致富的节奏啊!", + "你这是要把彩票中心吃垮的节奏啊,中了这么多奖!", + "你的运气真是好得让人眼红,我都想拜你为师,学学怎么中奖!", + "你的中奖概率比被闪电击中还低,你真是天生的幸运儿!", + "你的中奖记录比我的恋爱记录还丰富,真是让人羡慕嫉妒恨!", + "恭喜你中奖,你这是要成为我们朋友圈的土豪啊!", + "你这是要把彩票中心的钱都赢光,让他们破产吗?", + "你的中奖运气真是让人羡慕,我都想去拜拜财神爷,看看能不能沾沾你的光!", + "你的中奖记录比我的考试成绩还高,真是让人佩服得五体投地!", + "恭喜你中奖,你这是要成为我们村里的大富翁啊!" + }; + + private final LotteryDao lotteryDao; + + private final LotteryUserDao lotteryUserDao; + + private final UserMessageService userMessageService; + + private final UserInfoDao userInfoDao; + + private final JPAQueryFactory jpaQueryFactory; + + public SendLotteryService(LotteryDao lotteryDao, LotteryUserDao lotteryUserDao, UserMessageService userMessageService, UserInfoDao userInfoDao, JPAQueryFactory jpaQueryFactory) { + this.lotteryDao = lotteryDao; + this.lotteryUserDao = lotteryUserDao; + this.userMessageService = userMessageService; + this.userInfoDao = userInfoDao; + this.jpaQueryFactory = jpaQueryFactory; + } + + + public List findFinishList() { + // select * from tb_lottery where status = 2 and send_type is null + QLottery qLottery = QLottery.lottery; + return jpaQueryFactory.selectFrom(qLottery) + .where(qLottery.status.eq(PointEnums.LOTTERY_STATUS_LOTTERY.getCode()) + .and(qLottery.sendType.isNull())) + .fetch(); + } + + public void sendLotteryResultMessage(String id) { + + Lottery lottery = lotteryDao.findById(id).get(); + // 当前状态必须是已开奖状态 + // 必须是没有推送状态(校验状态,防止任务已被取消) + if (Objects.equals(lottery.getStatus(), PointEnums.LOTTERY_STATUS_LOTTERY.getCode()) + && lottery.getSendType() == null + ) { + List lotteryUserList = lotteryUserDao.findByLotteryId(id); + + lotteryUserList.forEach(lotteryUser -> { + UserMessageDto userMessageDto = new UserMessageDto(); + if (Objects.equals(lotteryUser.getResult(), PointEnums.LOTTERY_RESULT_WIN.getCode())) { + // 发送恭喜中奖站内信 + userMessageDto.setType(MessageTypeEnum.SYSTEM_MESSAGE.getType()); + userMessageDto.setTitle("恭喜中奖!"); + String userId = lotteryUser.getUserId(); + UserInfo userInfo = userInfoDao.getById(userId); + String content = "亲爱的" + userInfo.getNickName() + ",您在积分抽奖 " + lottery.getTitle() + " 中幸运中奖!"; + userMessageDto.setObjectId(lottery.getId()); + userMessageDto.setObjectType("lottery_" + lottery.getType()); + userMessageDto.setObjectCover(lottery.getImage()); + // winLotteryMessages 随机选取一条 + userMessageDto.setContent(content + winLotteryMessages[new Random().nextInt(winLotteryMessages.length)]); + userMessageDto.setUserId(userId); + } else { + userMessageDto.setType(MessageTypeEnum.SYSTEM_MESSAGE.getType()); + userMessageDto.setTitle("开奖通知"); + String userId = lotteryUser.getUserId(); + String content = "您参与的活动 " + lottery.getTitle() + " 已经开奖"; + userMessageDto.setContent(content); + userMessageDto.setObjectId(lottery.getId()); + userMessageDto.setObjectType("lottery_" + lottery.getType()); + userMessageDto.setObjectCover(lottery.getImage()); + userMessageDto.setUserId(userId); + } + userMessageService.sendUserMessage(userMessageDto); + }); + + lottery.setSendType(PointEnums.LOTTERY_STATUS_PUSH.getCode()); + lotteryDao.save(lottery); + } + } + +} diff --git a/luoo_user/src/main/resources/sql/20241206.sql b/luoo_user/src/main/resources/sql/20241206.sql new file mode 100644 index 0000000..0dbb063 --- /dev/null +++ b/luoo_user/src/main/resources/sql/20241206.sql @@ -0,0 +1,2 @@ +alter table tb_lottert + add send_type tinyint null comment '结果是否已推送 1-已推送'; \ No newline at end of file