红包可能出现的异常问题处理修复

This commit is contained in:
tianfeng 2025-11-26 17:15:28 +08:00
parent 4709b6f535
commit cdd73bfc03
2 changed files with 14 additions and 15 deletions

View File

@ -57,7 +57,7 @@ public class GrabRoomRedPacketCmdExe {
if (packetData == null || packetData.isEmpty()) {
// Redis未命中从数据库加载
RoomRedPacket redPacket = roomRedPacketGateway.findByPacketId(packetId);
ResponseAssert.notNull(OtherErrorCode.RED_PACKET_NOT_FOUND, grabbed);
ResponseAssert.notNull(OtherErrorCode.RED_PACKET_NOT_FOUND, redPacket);
// 检查状态
checkRedPacketStatus(redPacket);
@ -81,7 +81,7 @@ public class GrabRoomRedPacketCmdExe {
ResponseAssert.isFalse(OtherErrorCode.RED_PACKET_FINISHED, remainCount == null || remainCount < 0);
// 6. 设置防重标记Redis
long expireSeconds = Duration.between(LocalDateTime.now(), expireTime).getSeconds();
long expireSeconds = Math.max(60, Duration.between(LocalDateTime.now(), expireTime).getSeconds());
boolean setSuccess = roomRedPacketCacheService.setUserGrabbedFlag(packetId, userId, expireSeconds);
ResponseAssert.isTrue(OtherErrorCode.RED_PACKET_ALREADY_GRABBED, setSuccess);
@ -221,7 +221,7 @@ public class GrabRoomRedPacketCmdExe {
"status", redPacket.getStatus()
);
long expireSeconds = Duration.between(LocalDateTime.now(), redPacket.getExpireTime()).getSeconds() + 600;
long expireSeconds = Duration.between(LocalDateTime.now(), redPacket.getExpireTime()).getSeconds();
roomRedPacketCacheService.setRedPacket(redPacket.getPacketId(), packetData, expireSeconds);
}
}

View File

@ -61,33 +61,32 @@ public class SendRoomRedPacketCmdExe {
Long userId = cmd.getReqUserId();
cmd.setPacketType(2);
// 1. 参数校验
// 参数校验
validateParams(cmd);
// 2. 生成红包ID
String packetId = IdWorkerUtils.getIdStr();
// 3. 扣除用户金币同步调用钱包服务
deductUserGold(userId, cmd, packetId);
// 4. 计算过期时间
// 计算过期时间
LocalDateTime expireTime = LocalDateTime.now().plusMinutes(cmd.getExpireMinutes());
// 5. 创建红包记录
// 创建红包记录
RoomRedPacket redPacket = buildRedPacket(cmd, userId, packetId, expireTime);
roomRedPacketGateway.save(redPacket);
// 扣除用户金币同步调用钱包服务
deductUserGold(userId, cmd, packetId);
// 6. 拼手气红包预生成随机金额列表
// 拼手气红包预生成随机金额列表
if (RoomRedPacketType.RANDOM.getCode().equals(cmd.getPacketType())) {
List<Long> amounts = generateRandomAmounts(cmd.getTotalAmount(), cmd.getTotalCount());
long expireSeconds = cmd.getExpireMinutes() * 60;
roomRedPacketCacheService.setRandomAmounts(packetId, amounts, expireSeconds);
}
// 7. 写入Redis红包主数据
// 写入Redis红包主数据
cacheRedPacketData(redPacket);
// 8. 添加到房间红包列表
// 添加到房间红包列表
roomRedPacketCacheService.addToRoomList(
cmd.getRoomId(),
packetId,
@ -216,11 +215,11 @@ public class SendRoomRedPacketCmdExe {
List<Long> amounts = new ArrayList<>(totalCount);
long remainAmount = totalAmount;
int remainCount = totalCount;
for (int i = 0; i < totalCount - 1; i++) {
// 二倍均值法随机金额范围 [1, 剩余平均值 * 2]
long avgAmount = remainAmount / remainCount;
long maxAmount = avgAmount * 2;
long maxAmount = Math.min(avgAmount * 2, remainAmount - (remainCount - 1)); // 保证剩余够分
// 确保至少1金币
long amount = ThreadLocalRandom.current().nextLong(1, Math.max(2, maxAmount + 1));