From ee5f33aba66b7c71ecaa5dfc779afb94b38b7d93 Mon Sep 17 00:00:00 2001 From: wells <123456@qq.com> Date: Sun, 9 Aug 2026 11:13:06 +0800 Subject: [PATCH] =?UTF-8?q?processPendingTasks=20=E4=BC=98=E5=8C=96?= =?UTF-8?q?=EF=BC=8C=E8=87=AA=E5=8A=A8=E5=BC=80=E5=A7=8B=E4=B8=8B=E4=B8=80?= =?UTF-8?q?=E6=9C=9F=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/tailbet/controller/OpsController.java | 1 + src/main/java/com/tailbet/job/GameJob.java | 175 +++++++++++------- .../tailbet/service/impl/GameServiceImpl.java | 10 +- .../service/impl/GroupServiceImpl.java | 5 - 4 files changed, 112 insertions(+), 79 deletions(-) diff --git a/src/main/java/com/tailbet/controller/OpsController.java b/src/main/java/com/tailbet/controller/OpsController.java index 75de635..d97251f 100644 --- a/src/main/java/com/tailbet/controller/OpsController.java +++ b/src/main/java/com/tailbet/controller/OpsController.java @@ -94,6 +94,7 @@ public class OpsController { } /** + * 设置为管理员 *

* 操作人需为该群群主;同时本地与 OpenIM 角色都会更新(OpenIM roleLevel=60=管理员), * OpenIM 同步失败会抛异常回滚本地事务,保证本地与 IM 角色一致。 diff --git a/src/main/java/com/tailbet/job/GameJob.java b/src/main/java/com/tailbet/job/GameJob.java index 8eabe19..a509489 100644 --- a/src/main/java/com/tailbet/job/GameJob.java +++ b/src/main/java/com/tailbet/job/GameJob.java @@ -328,7 +328,75 @@ public class GameJob { public void resetDailyFakeUsers() { fakeUserService.resetDailyActiveFakes(); } + /** + * 处理延迟任务队列(每秒执行) + */ + @Scheduled(fixedDelay = 1000) + public void processPendingTasks() { + LocalDateTime now = LocalDateTime.now(); + for (Map.Entry entry : pendingTasks.entrySet()) { + PendingTaskInfo task = entry.getValue(); + if (task.getExecuteTime() == null) { + pendingTasks.remove(entry.getKey()); + deleteTaskFromDb(task.getTaskId()); + continue; + } + if (task.getExecuteTime().isBefore(now) || task.getExecuteTime().isEqual(now)) { + boolean success = executeTask(task); + if (success) { + pendingTasks.remove(entry.getKey()); + deleteTaskFromDb(task.getTaskId()); + } else { + // 失败时保留内存与数据库中的任务,5秒后再重试 + task.setExecuteTime(LocalDateTime.now().plusSeconds(5)); + updateTaskExecuteTimeInDb(task); + log.warn("任务执行失败,保留任务待重试: taskId={}", task.getTaskId()); + } + } + } + } + /** + * 更新延迟任务的执行时间(失败重试场景) + */ + private void updateTaskExecuteTimeInDb(PendingTaskInfo task) { + try { + PendingTask dbTask = pendingTaskMapper.selectOne( + new LambdaQueryWrapper().eq(PendingTask::getTaskId, task.getTaskId())); + if (dbTask != null) { + dbTask.setExecuteTime(task.getExecuteTime()); + pendingTaskMapper.updateById(dbTask); + } + } catch (Exception e) { + log.error("更新延迟任务执行时间失败: taskId={}, error={}", task.getTaskId(), e.getMessage()); + } + } + + /** + * 执行延迟任务 + * + * @return true 表示执行成功(可清理);false 表示执行失败(需保留以重试) + */ + private boolean executeTask(PendingTaskInfo task) { + try { + switch (task.getType()) { + case "settle": + return onSettle(task.getRoundId(), task.getGroupId(), task.getDigit()); + case "auto_next": + return onAutoNext(task.getGroupId()); + case "start_rp": + return onStartRp(task.getRoundId(), task.getGroupId()); + case "bot_send_rp": + return botSendRp(task.getRoundId(), task.getGroupId()); + default: + log.warn("未知任务类型: {}", task.getType()); + return false; + } + } catch (Exception e) { + log.error("执行任务失败: taskId={}, error={}", task.getTaskId(), e.getMessage()); + return false; + } + } /** * 安排开始发红包 */ @@ -479,50 +547,54 @@ public class GameJob { /** * 开始发红包 */ - public void onStartRp(Long roundId, Long groupId) { - GameRound round = gameRoundMapper.selectById(roundId); - if (round == null) { - return; + public boolean onStartRp(Long roundId, Long groupId) { + try { + GameRound round = gameRoundMapper.selectById(roundId); + if (round == null) { + return true; + } + + // 更新局状态为开始发红包 + round.setStatus(IGameService.STATUS_RP_SENDING); + round.setStartRpTime(LocalDateTime.now()); + gameRoundMapper.updateById(round); + + // 广播开始发红包 + broadcastStartRp(groupId, round.getRoundNo()); + + // 安排超时后如果没人发包则机器人自动发 + int autoRpTimeout = getConfigInt("auto_rp_timeout", 10); + scheduleBotSendRp(roundId, groupId, autoRpTimeout); + return true; + } catch (Exception e) { + log.error("开始发红包失败: roundId={}, error={}", roundId, e.getMessage()); + return false; } - - // 更新局状态为开始发红包 - round.setStatus(IGameService.STATUS_RP_SENDING); - round.setStartRpTime(LocalDateTime.now()); - gameRoundMapper.updateById(round); - - // 广播开始发红包 - broadcastStartRp(groupId, round.getRoundNo()); - - // 安排超时后如果没人发包则机器人自动发 - int autoRpTimeout = getConfigInt("auto_rp_timeout", 10); - scheduleBotSendRp(roundId, groupId, autoRpTimeout); } /** * 机器人自动发包 */ - public void botSendRp(Long roundId, Long groupId) { + public boolean botSendRp(Long roundId, Long groupId) { GameRound round = gameRoundMapper.selectById(roundId); if (round == null) { - return; + return true; } // 仅在"开始发红包"状态下才执行,避免误触发 if (round.getStatus() == null || round.getStatus() != IGameService.STATUS_RP_SENDING) { log.debug("本局{}当前状态非发红包中(status={}),机器人跳过发包", roundId, round.getStatus()); - return; + return true; } // 已有用户先发包,机器人不再重复发包(让用户的红包触发开奖) if (round.getFirstRpId() != null) { log.info("本局{}已有用户先发包(firstRpId={}),机器人跳过发包", roundId, round.getFirstRpId()); - return; + return true; } - // 即使未设置目标尾数,机器人也会发包(由RedPacketService按随机金额处理) - // 从本群成员中查找机器人账号 List memberIds = groupMemberMapper.selectList( new LambdaQueryWrapper() @@ -534,7 +606,7 @@ public class GameJob { if (memberIds.isEmpty()) { log.warn("群{}无成员,机器人跳过发包", groupId); - return; + return true; } User bot = userMapper.selectOne(new LambdaQueryWrapper() @@ -545,7 +617,7 @@ public class GameJob { if (bot == null) { log.warn("群{}成员中无可用机器人账号,跳过发包", groupId); - return; + return true; } try { @@ -557,15 +629,17 @@ public class GameJob { RedPacket rp = redPacketService.sendRp(bot.getId(), groupId, amount, count, roundId); log.info("机器人自动发包: roundId={}, rpId={}, amount={}, count={}, targetDigit={}", roundId, rp.getId(), amount, count, round.getTargetDigit()); + return true; } catch (Exception e) { log.error("机器人发包失败: roundId={}, error={}", roundId, e.getMessage(), e); + return false; } } /** * 开奖结算 */ - public void onSettle(Long roundId, Long groupId, int digit) { + public boolean onSettle(Long roundId, Long groupId, int digit) { try { gameService.settle(roundId, digit); @@ -586,8 +660,10 @@ public class GameJob { roundTasks.remove(roundId); log.info("局结算完成: roundId={}, digit={}", roundId, digit); + return true; } catch (Exception e) { log.error("结算失败: roundId={}, error={}", roundId, e.getMessage()); + return false; } } @@ -701,61 +777,18 @@ public class GameJob { } - /** - * 处理延迟任务队列(每秒执行) - */ - @Scheduled(fixedDelay = 1000) - public void processPendingTasks() { - LocalDateTime now = LocalDateTime.now(); - pendingTasks.entrySet().removeIf(entry -> { - PendingTaskInfo task = entry.getValue(); - if (task.getExecuteTime() == null) { - deleteTaskFromDb(task.getTaskId()); - return true; - } - if (task.getExecuteTime().isBefore(now) || task.getExecuteTime().isEqual(now)) { - executeTask(task); - deleteTaskFromDb(task.getTaskId()); - return true; - } - return false; - }); - } - /** - * 执行延迟任务 - */ - private void executeTask(PendingTaskInfo task) { - try { - switch (task.getType()) { - case "settle": - onSettle(task.getRoundId(), task.getGroupId(), task.getDigit()); - break; - case "auto_next": - onAutoNext(task.getGroupId()); - break; - case "start_rp": - onStartRp(task.getRoundId(), task.getGroupId()); - break; - case "bot_send_rp": - botSendRp(task.getRoundId(), task.getGroupId()); - break; - default: - log.warn("未知任务类型: {}", task.getType()); - } - } catch (Exception e) { - log.error("执行任务失败: taskId={}, error={}", task.getTaskId(), e.getMessage()); - } - } /** * 自动开始下一期 */ - private void onAutoNext(Long groupId) { + private boolean onAutoNext(Long groupId) { try { gameService.startGame(groupId, 0L); // 0L表示系统自动 + return true; } catch (Exception e) { log.error("自动开始下一期失败: groupId={}, error={}", groupId, e.getMessage()); + return false; } } } diff --git a/src/main/java/com/tailbet/service/impl/GameServiceImpl.java b/src/main/java/com/tailbet/service/impl/GameServiceImpl.java index c97cb1b..d306fb9 100644 --- a/src/main/java/com/tailbet/service/impl/GameServiceImpl.java +++ b/src/main/java/com/tailbet/service/impl/GameServiceImpl.java @@ -116,14 +116,18 @@ public class GameServiceImpl implements IGameService { } /** - * 开始游戏(群主操作) + * 开始游戏(群主操作或系统自动,userId=0L 表示系统) */ @Override @Transactional public GameRound startGame(Long groupId, Long userId) { - // 校验群主权限 Group group = groupMapper.selectById(groupId); - if (group == null || !group.getOwnerUserId().equals(userId)) { + if (group == null) { + throw new RuntimeException("群组不存在"); + } + + // 校验群主权限(系统调用时 userId=0L 跳过校验) + if (!Long.valueOf(0L).equals(userId) && !group.getOwnerUserId().equals(userId)) { throw new RuntimeException("只有群主可以开始游戏"); } diff --git a/src/main/java/com/tailbet/service/impl/GroupServiceImpl.java b/src/main/java/com/tailbet/service/impl/GroupServiceImpl.java index 076af4c..47ba5e8 100644 --- a/src/main/java/com/tailbet/service/impl/GroupServiceImpl.java +++ b/src/main/java/com/tailbet/service/impl/GroupServiceImpl.java @@ -134,11 +134,6 @@ public class GroupServiceImpl implements IGroupService { groupMemberMapper.insert(buildMember(groupId, botUserId, ROLE_NORMAL, now)); } - // 机器人入群 - if (!ownerIsBot) { - groupMemberMapper.insert(buildMember(groupId, botUserId, ROLE_NORMAL, now)); - } - // 从现有假人中挑选10个进群 List fakeUsers = fakeUserService.pickFakeUsers(10); for (User fake : fakeUsers) {