processPendingTasks 优化,自动开始下一期优化
This commit is contained in:
@@ -94,6 +94,7 @@ public class OpsController {
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置为管理员
|
||||
* <p>
|
||||
* 操作人需为该群群主;同时本地与 OpenIM 角色都会更新(OpenIM roleLevel=60=管理员),
|
||||
* OpenIM 同步失败会抛异常回滚本地事务,保证本地与 IM 角色一致。
|
||||
|
||||
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user