processPendingTasks 优化,自动开始下一期优化

This commit is contained in:
wells
2026-08-09 11:13:06 +08:00
parent 114a0d93fe
commit ee5f33aba6
4 changed files with 112 additions and 79 deletions
@@ -94,6 +94,7 @@ public class OpsController {
}
/**
* 设置为管理员
* <p>
* 操作人需为该群群主;同时本地与 OpenIM 角色都会更新(OpenIM roleLevel=60=管理员),
* OpenIM 同步失败会抛异常回滚本地事务,保证本地与 IM 角色一致。
+104 -71
View File
@@ -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<String, PendingTaskInfo> 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<PendingTask>().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<Long> memberIds = groupMemberMapper.selectList(
new LambdaQueryWrapper<GroupMember>()
@@ -534,7 +606,7 @@ public class GameJob {
if (memberIds.isEmpty()) {
log.warn("群{}无成员,机器人跳过发包", groupId);
return;
return true;
}
User bot = userMapper.selectOne(new LambdaQueryWrapper<User>()
@@ -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;
}
}
}
@@ -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("只有群主可以开始游戏");
}
@@ -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<User> fakeUsers = fakeUserService.pickFakeUsers(10);
for (User fake : fakeUsers) {