火箭领取接口完善

This commit is contained in:
tianfeng 2025-11-12 23:41:03 +08:00
parent 3bdfc23433
commit 5e0948c86b
7 changed files with 96 additions and 39 deletions

View File

@ -53,6 +53,7 @@ public class RocketRewardClaimCmdExe {
private final WalletGoldClient walletGoldClient;
private final PropsBackpackClient propsBackpackClient;
private final BadgeBackpackClient badgeBackpackClient;
private final RocketHistoryGateway rocketHistoryGateway;
private final Random random = new Random();
@ -63,7 +64,7 @@ public class RocketRewardClaimCmdExe {
Long userId = cmd.getReqUserId();
String lockKey = RocketKeys.LOCK.getKey(cmd.getRoomId(), "claim", userId);
return distributedLockUtil.executeWithLock(lockKey, 5L, () -> doClaim(cmd), "奖励领取操作过于频繁,请稍后重试");
return distributedLockUtil.executeWithLock(lockKey, 5L, () -> doClaim(cmd), "Reward collection operations are too frequent. Please try again later");
}
/**
@ -73,59 +74,52 @@ public class RocketRewardClaimCmdExe {
Long userId = cmd.getReqUserId();
Long roomId = cmd.getRoomId();
String today = LocalDate.now().toString();
// 1. 查询火箭状态
RocketStatus rocketStatus = rocketStatusGateway.findByRoomIdAndDate(roomId, today);
if (rocketStatus == null) {
throw new RuntimeException("火箭状态不存在");
// 1. 查询今天最新的火箭发射记录
RocketHistory latestHistory = rocketHistoryGateway.findLatestByRoomIdAndDate(roomId, today);
if (latestHistory == null) {
throw new RuntimeException("There are no rockets launched today, and there are no rewards to receive");
}
Integer rocketLevel = rocketStatus.getLevel().getLevel();
Integer rocketLevel = latestHistory.getLevel();
// 2. 校验是否已发射
if (rocketStatus.getStatus() != RocketStatusEnum.LAUNCHED) {
throw new RuntimeException("火箭尚未发射,无法领取奖励");
}
// 3. 检查是否已领取每天每个房间每个等级只能领一次
boolean hasClaimed = rocketRewardLogGateway.existsByRoomAndUserAndDateAndLevel(roomId, userId, today, rocketLevel);
// 2. 检查是否已领取每天每个房间每个等级只能领一次
boolean hasClaimed = rocketRewardLogGateway.existsByRocketAndUser(latestHistory.getId(), userId);
if (hasClaimed) {
throw new RuntimeException("今日该等级火箭已领取,请等待下一级或明天再来");
throw new RuntimeException("This class of rocket has been collected today. Please wait for the next stage or come back tomorrow.");
}
// 4. 查询火箭配置
// 3. 查询火箭配置
RocketConfig config = rocketConfigGateway.findByLevel(rocketLevel);
if (config == null) {
throw new RuntimeException("火箭配置不存在");
}
// 5. 检查奖励数量是否已达上限
Integer rewardQuantity = config.getRewardQuantity() != null ? config.getRewardQuantity() : 20;
if (rocketStatus.getClaimCount() >= rewardQuantity) {
throw new RuntimeException("奖励已被领完,请下次早点来");
// 4. MongoDB原子递增检查
int rewardQuantity = config.getRewardQuantity() != null ? config.getRewardQuantity() : 20;
boolean success = rocketHistoryGateway.tryIncrementClaimCount(latestHistory.getId(), rewardQuantity);
if (!success) {
throw new RuntimeException("The rewards have been collected, please come earlier next time");
}
// 6. 解析奖励配置
// 5. 解析奖励配置
List<PropsActivityRewardConfigInfoDTO> rewardList = parseRewardConfig(config.getRewardConfig().toJSONString());
if (rewardList == null || rewardList.isEmpty()) {
throw new RuntimeException("奖励配置为空");
}
// 7. 随机选择一个奖励
// 6. 随机选择一个奖励
PropsActivityRewardConfigInfoDTO selectedReward = rewardList.get(random.nextInt(rewardList.size()));
// 8. 发放奖励
// 7. 发放奖励
String walletBizNo = RocketRewardLog.buildBizNo(roomId.toString(), userId);
grantReward(userId, selectedReward, walletBizNo);
// 9. 保存领取记录
saveRewardLog(roomId, userId, today, rocketLevel, selectedReward, walletBizNo);
// 8. 保存领取记录
saveRewardLog(roomId, userId, latestHistory, selectedReward, walletBizNo);
// 10. 更新领取人数
rocketStatus.incrementClaimCount();
rocketStatusGateway.save(rocketStatus);
// 11. 推送领取成功消息
// 9. 推送领取成功消息
try {
String userName = "用户" + userId;
Long rewardAmount = getRewardAmount(selectedReward);
@ -134,7 +128,7 @@ public class RocketRewardClaimCmdExe {
log.error("推送奖励领取消息失败: roomId={}, userId={}", roomId, userId, e);
}
// 12. 构建返回结果
// 10. 构建返回结果
RocketRewardCO rewardCO = new RocketRewardCO();
rewardCO.setRewardType(selectedReward.getType());
rewardCO.setRewardItemId(selectedReward.getId());
@ -218,7 +212,6 @@ public class RocketRewardClaimCmdExe {
.build()
);
log.info("金币发放成功: userId={}, amount={}", userId, goldAmount);
} catch (Exception e) {
log.error("金币发放失败: userId={}, amount={}", userId, goldAmount, e);
throw new RuntimeException("金币发放失败");
@ -243,8 +236,8 @@ public class RocketRewardClaimCmdExe {
.setOpUser(userId);
propsBackpackClient.giveProps(cmd);
log.info("道具发放成功(TODO): userId={}, propId={}, quantity={}, type={}",
userId, propId, quantity, detailType);
// 发送通知
propsBackpackClient.givePropsNotify(userId, detailType, quantity, propId);
} catch (Exception e) {
log.error("道具发放失败: userId={}, propId={}", userId, propId, e);
throw new RuntimeException("道具发放失败");
@ -270,7 +263,8 @@ public class RocketRewardClaimCmdExe {
.setBadgeType(SysBadgeConfigTypeEnum.ACTIVITY)
);
log.info("徽章发放成功(TODO): userId={}, badgeId={}", userId, badgeId);
// 发送通知
propsBackpackClient.givePropsNotify(userId, SysBadgeConfigTypeEnum.ACTIVITY.name(), quantity, badgeId);
} catch (Exception e) {
log.error("徽章发放失败: userId={}, badgeId={}", userId, badgeId, e);
throw new RuntimeException("徽章发放失败");
@ -280,12 +274,13 @@ public class RocketRewardClaimCmdExe {
/**
* 保存领取记录
*/
private void saveRewardLog(Long roomId, Long userId, String date, Integer level,
private void saveRewardLog(Long roomId, Long userId, RocketHistory rocketHistory,
PropsActivityRewardConfigInfoDTO reward, String walletBizNo) {
RocketRewardLog log = new RocketRewardLog();
log.setRocketHistoryId(rocketHistory.getId());
log.setRoomId(roomId);
log.setUserId(userId);
log.setRocketLevel(level);
log.setRocketLevel(rocketHistory.getLevel());
log.setIsContributor(0);
log.setContributionEnergy(0L);
log.setContributionRate(null);

View File

@ -18,6 +18,22 @@ public interface RocketHistoryGateway {
*/
String save(RocketHistory history);
/**
* 查询今天最新的火箭发射记录按发射时间倒序
*/
RocketHistory findLatestByRoomIdAndDate(Long roomId, String date);
/**
* 尝试原子递增领取人数带上限检查
* @return 是否成功递增
*/
boolean tryIncrementClaimCount(String historyId, int maxCount);
/**
* 增加领取人数
*/
void incrementClaimCount(String historyId);
/**
* 根据ID查询
*/

View File

@ -26,6 +26,10 @@ public class RocketHistory {
private Integer totalContributors;
private RewardPool rewardPool;
private ClaimStats claimStats;
/**
* 已领取人数
*/
private Integer claimedCount;
private LocalDateTime launchTime;
private LocalDateTime claimStartTime;
private LocalDateTime claimEndTime;

View File

@ -54,7 +54,7 @@ public class RocketConfigConvertor {
} else {
config.setNormalRewardConfig(new JSONArray());
}
config.setRewardQuantity(entity.getRewardQuantity());
config.setStatus(entity.getStatus());
// config.setCreatedAt(entity.getCreatedAt());
// config.setUpdatedAt(entity.getUpdatedAt());
@ -91,7 +91,8 @@ public class RocketConfigConvertor {
} else {
entity.setNormalRewardConfig(null);
}
entity.setRewardQuantity(config.getRewardQuantity());
entity.setStatus(config.getStatus());
// createdAt updatedAt 由数据库自动管理

View File

@ -2,6 +2,7 @@ package com.red.circle.other.infra.database.mongo.repository;
import com.red.circle.other.infra.database.mongo.document.RocketHistoryDocument;
import org.springframework.data.mongodb.repository.MongoRepository;
import org.springframework.data.mongodb.repository.Query;
import org.springframework.stereotype.Repository;
import java.time.LocalDateTime;
@ -21,6 +22,11 @@ public interface RocketHistoryRepository extends MongoRepository<RocketHistoryDo
*/
List<RocketHistoryDocument> findByRoomIdOrderByLaunchTimeDesc(Long roomId);
/**
* 查询今天最新的火箭发射记录按发射时间倒序
*/
RocketHistoryDocument findFirstByRoomIdAndDateOrderByLaunchTimeDesc(Long roomId, String date);
/**
* 根据房间ID和日期查询
*/

View File

@ -1,5 +1,6 @@
package com.red.circle.other.infra.gateway;
import com.mongodb.client.result.UpdateResult;
import com.red.circle.other.domain.gateway.RocketHistoryGateway;
import com.red.circle.other.domain.rocket.RocketHistory;
import com.red.circle.other.infra.convertor.RocketHistoryConvertor;
@ -41,6 +42,40 @@ public class RocketHistoryGatewayImpl implements RocketHistoryGateway {
return saved.getId();
}
@Override
public RocketHistory findLatestByRoomIdAndDate(Long roomId, String date) {
RocketHistoryDocument document = rocketHistoryRepository.findFirstByRoomIdAndDateOrderByLaunchTimeDesc(roomId, date);
if (document == null) {
return null;
}
return rocketHistoryConvertor.toDomain(document);
}
@Override
public boolean tryIncrementClaimCount(String historyId, int maxCount) {
Query query = new Query();
query.addCriteria(Criteria.where("_id").is(historyId));
query.addCriteria(Criteria.where("claimedCount").lt(maxCount)); // 小于上限才更新
Update update = new Update();
update.inc("claimedCount", 1);
update.set("updatedAt", LocalDateTime.now());
UpdateResult result = mongoTemplate.updateFirst(query, update, RocketHistoryDocument.class);
return result.getModifiedCount() > 0; // 更新成功返回true
}
@Override
public void incrementClaimCount(String historyId) {
Query query = new Query(Criteria.where("_id").is(historyId));
Update update = new Update();
update.inc("claimedCount", 1);
update.set("updatedAt", LocalDateTime.now());
mongoTemplate.updateFirst(query, update, RocketHistoryDocument.class);
}
@Override
public RocketHistory findById(String id) {
return rocketHistoryRepository.findById(id)

View File

@ -15,7 +15,7 @@
</resultMap>
<sql id="Base_Column_List">
id, level, max_energy, reward_config, contributor_reward_rate,
id, level, max_energy, reward_config,reward_quantity, contributor_reward_rate,
normal_reward_config, status, created_at, updated_at
</sql>