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) {