fix: discard rocket gift overflow between levels
This commit is contained in:
parent
a5e85e8b71
commit
88b20f9ca3
@ -222,14 +222,17 @@ public class RocketEnergyAggregator {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 处理能量增加
|
||||
processRoomEnergyBatch(roomId, batch);
|
||||
// 处理能量增加;火箭满能时只消费到触发礼物,后续独立礼物留给下一级。
|
||||
int processedCount = processRoomEnergyBatch(roomId, batch);
|
||||
if (processedCount <= 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 处理成功后才删除Redis中的数据(使用 LTRIM)
|
||||
redisTemplate.opsForList().trim(queueKey, batch.size(), -1);
|
||||
redisTemplate.opsForList().trim(queueKey, processedCount, -1);
|
||||
|
||||
log.info("成功处理房间{}能量, 处理数量={}, 剩余={}",
|
||||
roomId, batch.size(), queueSize - batch.size());
|
||||
roomId, processedCount, queueSize - processedCount);
|
||||
|
||||
return true;
|
||||
|
||||
@ -242,7 +245,7 @@ public class RocketEnergyAggregator {
|
||||
/**
|
||||
* 处理单个房间的能量批次
|
||||
*/
|
||||
private void processRoomEnergyBatch(Long roomId, List<RocketEnergyAddCmd> batch) {
|
||||
private int processRoomEnergyBatch(Long roomId, List<RocketEnergyAddCmd> batch) {
|
||||
String riyadhToday = ZonedDateTimeAsiaRiyadhUtils.nowFormat("yyyy-MM-dd");
|
||||
|
||||
// 查询当前火箭状态
|
||||
@ -264,7 +267,7 @@ public class RocketEnergyAggregator {
|
||||
// 校验状态
|
||||
if (!rocketStatus.canAddEnergy()) {
|
||||
log.warn("火箭不可充能, roomId={}, status={}", roomId, rocketStatus.getStatus());
|
||||
return;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// 记录增加前的状态
|
||||
@ -272,23 +275,38 @@ public class RocketEnergyAggregator {
|
||||
long maxEnergy = rocketStatus.getMaxEnergy();
|
||||
|
||||
// 批量增加能量
|
||||
long totalEnergy = 0L;
|
||||
long requestedEnergy = 0L;
|
||||
long acceptedEnergy = 0L;
|
||||
int processedCount = 0;
|
||||
Long triggerUserId = null;
|
||||
|
||||
// 历史上可能存在“已满能但异步发射未完成”的状态;此时不消费新礼物。
|
||||
if (rocketStatus.isFullEnergy()) {
|
||||
Long retryTriggerUserId = batch.isEmpty() ? null : batch.get(0).getUserId();
|
||||
rocketLaunchManager.launchAsync(roomId, retryTriggerUserId);
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (RocketEnergyAddCmd cmd : batch) {
|
||||
long beforeEnergy = rocketStatus.getCurrentEnergy();
|
||||
long giftEnergy = cmd.getGiftGoldValue();
|
||||
|
||||
// 增加能量
|
||||
rocketStatus.addEnergy(cmd.getUserId(), cmd.getGiftGoldValue());
|
||||
totalEnergy += cmd.getGiftGoldValue();
|
||||
// 领域对象会把单笔礼物截断到当前火箭的剩余能量。
|
||||
rocketStatus.addEnergy(cmd.getUserId(), giftEnergy);
|
||||
requestedEnergy += giftEnergy;
|
||||
processedCount++;
|
||||
|
||||
long afterEnergy = rocketStatus.getCurrentEnergy();
|
||||
acceptedEnergy += afterEnergy - beforeEnergy;
|
||||
|
||||
// 记录触发满能量的用户
|
||||
if (beforeEnergy < maxEnergy && afterEnergy >= maxEnergy && triggerUserId == null) {
|
||||
triggerUserId = cmd.getUserId();
|
||||
log.info("找到触发升级的用户: userId={}, beforeEnergy={}, afterEnergy={}, maxEnergy={}",
|
||||
triggerUserId, beforeEnergy, afterEnergy, maxEnergy);
|
||||
long discardedEnergy = Math.max(0L, giftEnergy - (afterEnergy - beforeEnergy));
|
||||
log.info("找到触发升级的用户: userId={}, beforeEnergy={}, afterEnergy={}, maxEnergy={}, 单笔溢出丢弃={}",
|
||||
triggerUserId, beforeEnergy, afterEnergy, maxEnergy, discardedEnergy);
|
||||
// 当前礼物之后的队列记录是独立送礼,留到下一级火箭再处理。
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -300,8 +318,8 @@ public class RocketEnergyAggregator {
|
||||
throw e;
|
||||
}
|
||||
|
||||
log.info("批量增加火箭能量: roomId={}, 批次数量={}, 总能量={}, 更新前={}, 更新后={}/{}",
|
||||
roomId, batch.size(), totalEnergy, energyBeforeAdd,
|
||||
log.info("批量增加火箭能量: roomId={}, 读取数量={}, 处理数量={}, 请求能量={}, 计入能量={}, 更新前={}, 更新后={}/{}",
|
||||
roomId, batch.size(), processedCount, requestedEnergy, acceptedEnergy, energyBeforeAdd,
|
||||
rocketStatus.getCurrentEnergy(), rocketStatus.getMaxEnergy());
|
||||
|
||||
// 推送更新消息(节流)
|
||||
@ -320,6 +338,7 @@ public class RocketEnergyAggregator {
|
||||
// 异步触发发射
|
||||
rocketLaunchManager.launchAsync(roomId, triggerUserId);
|
||||
}
|
||||
return processedCount;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -108,7 +108,13 @@ public class RocketStatus {
|
||||
* 增加能量
|
||||
*/
|
||||
public void addEnergy(Long userId,Long energyValue) {
|
||||
this.currentEnergy += energyValue;
|
||||
if (energyValue == null || energyValue <= 0 || this.currentEnergy >= this.maxEnergy) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 单笔礼物只补满当前火箭;超出当前档位的能量不进入下一级。
|
||||
long acceptedEnergy = Math.min(energyValue, this.maxEnergy - this.currentEnergy);
|
||||
this.currentEnergy += acceptedEnergy;
|
||||
|
||||
RocketContributor contributor = findContributor(userId);
|
||||
if (contributor == null) {
|
||||
@ -119,46 +125,20 @@ public class RocketStatus {
|
||||
contributor.setFirstContributeTime(LocalDateTime.now());
|
||||
this.contributors.add(contributor);
|
||||
}
|
||||
contributor.addEnergy(energyValue);
|
||||
contributor.addEnergy(acceptedEnergy);
|
||||
contributor.setLastContributeTime(LocalDateTime.now());
|
||||
|
||||
recalculateContributionRate();
|
||||
this.updatedAt = LocalDateTime.now();
|
||||
}
|
||||
|
||||
// RocketStatus.java
|
||||
|
||||
|
||||
/**
|
||||
* 计算能发射的最高等级
|
||||
* 判断当前等级是否可以发射
|
||||
* @return 能发射的等级,如果能量不足返回null
|
||||
*/
|
||||
public RocketLevel calculateLaunchLevel(RocketConfigGateway configGateway) {
|
||||
long currentEnergy = this.currentEnergy;
|
||||
|
||||
// 如果当前已经是最高级,不能再发射
|
||||
if (this.level.isMaxLevel()) {
|
||||
return this.level;
|
||||
}
|
||||
|
||||
// 查询所有启用的配置
|
||||
List<RocketConfig> configs = configGateway.findAllEnabled();
|
||||
if (configs == null || configs.isEmpty()) {
|
||||
log.warn("未找到启用的火箭配置");
|
||||
return null;
|
||||
}
|
||||
|
||||
// 按等级从高到低排序
|
||||
configs.sort((a, b) -> b.getLevel().compareTo(a.getLevel()));
|
||||
|
||||
// 从最高等级开始查找,找到能量满足发射条件的最高等级
|
||||
for (RocketConfig config : configs) {
|
||||
if (currentEnergy >= config.getMaxEnergy()) {
|
||||
return RocketLevel.of(config.getLevel());
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
// 发射等级只能是正在充能的当前等级,禁止单笔大额礼物直接跨级。
|
||||
return isFullEnergy() ? this.level : null;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -187,14 +167,11 @@ public class RocketStatus {
|
||||
return;
|
||||
}
|
||||
|
||||
// 保留当前能量值
|
||||
long preservedEnergy = this.currentEnergy;
|
||||
|
||||
// 升级到目标等级
|
||||
RocketLevel oldLevel = this.level;
|
||||
this.level = targetLevel;
|
||||
this.maxEnergy = targetConfig.getMaxEnergy();
|
||||
this.currentEnergy = preservedEnergy; // 完全保留当前能量
|
||||
this.currentEnergy = 0L;
|
||||
this.status = RocketStatusEnum.CHARGING;
|
||||
|
||||
// 清空贡献者(新一轮)
|
||||
@ -202,8 +179,8 @@ public class RocketStatus {
|
||||
this.launchTime = null;
|
||||
this.claimExpireTime = null;
|
||||
|
||||
log.info("火箭升级成功, {}级 -> {}级, 保留能量={}, 新目标={}",
|
||||
oldLevel.getLevel(), targetLevel.getLevel(), preservedEnergy, this.maxEnergy);
|
||||
log.info("火箭升级成功, {}级 -> {}级, 新等级能量从0开始, 新目标={}",
|
||||
oldLevel.getLevel(), targetLevel.getLevel(), this.maxEnergy);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user