火箭领取接口完善
This commit is contained in:
parent
3bdfc23433
commit
5e0948c86b
@ -53,6 +53,7 @@ public class RocketRewardClaimCmdExe {
|
|||||||
private final WalletGoldClient walletGoldClient;
|
private final WalletGoldClient walletGoldClient;
|
||||||
private final PropsBackpackClient propsBackpackClient;
|
private final PropsBackpackClient propsBackpackClient;
|
||||||
private final BadgeBackpackClient badgeBackpackClient;
|
private final BadgeBackpackClient badgeBackpackClient;
|
||||||
|
private final RocketHistoryGateway rocketHistoryGateway;
|
||||||
|
|
||||||
private final Random random = new Random();
|
private final Random random = new Random();
|
||||||
|
|
||||||
@ -63,7 +64,7 @@ public class RocketRewardClaimCmdExe {
|
|||||||
Long userId = cmd.getReqUserId();
|
Long userId = cmd.getReqUserId();
|
||||||
String lockKey = RocketKeys.LOCK.getKey(cmd.getRoomId(), "claim", userId);
|
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 userId = cmd.getReqUserId();
|
||||||
Long roomId = cmd.getRoomId();
|
Long roomId = cmd.getRoomId();
|
||||||
String today = LocalDate.now().toString();
|
String today = LocalDate.now().toString();
|
||||||
|
|
||||||
// 1. 查询火箭状态
|
// 1. 查询今天最新的火箭发射记录
|
||||||
RocketStatus rocketStatus = rocketStatusGateway.findByRoomIdAndDate(roomId, today);
|
RocketHistory latestHistory = rocketHistoryGateway.findLatestByRoomIdAndDate(roomId, today);
|
||||||
if (rocketStatus == null) {
|
if (latestHistory == null) {
|
||||||
throw new RuntimeException("火箭状态不存在");
|
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. 校验是否已发射
|
// 2. 检查是否已领取(每天每个房间每个等级只能领一次)
|
||||||
if (rocketStatus.getStatus() != RocketStatusEnum.LAUNCHED) {
|
boolean hasClaimed = rocketRewardLogGateway.existsByRocketAndUser(latestHistory.getId(), userId);
|
||||||
throw new RuntimeException("火箭尚未发射,无法领取奖励");
|
|
||||||
}
|
|
||||||
|
|
||||||
// 3. 检查是否已领取(每天每个房间每个等级只能领一次)
|
|
||||||
boolean hasClaimed = rocketRewardLogGateway.existsByRoomAndUserAndDateAndLevel(roomId, userId, today, rocketLevel);
|
|
||||||
if (hasClaimed) {
|
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);
|
RocketConfig config = rocketConfigGateway.findByLevel(rocketLevel);
|
||||||
if (config == null) {
|
if (config == null) {
|
||||||
throw new RuntimeException("火箭配置不存在");
|
throw new RuntimeException("火箭配置不存在");
|
||||||
}
|
}
|
||||||
|
|
||||||
// 5. 检查奖励数量是否已达上限
|
// 4. MongoDB原子递增检查
|
||||||
Integer rewardQuantity = config.getRewardQuantity() != null ? config.getRewardQuantity() : 20;
|
int rewardQuantity = config.getRewardQuantity() != null ? config.getRewardQuantity() : 20;
|
||||||
if (rocketStatus.getClaimCount() >= rewardQuantity) {
|
boolean success = rocketHistoryGateway.tryIncrementClaimCount(latestHistory.getId(), rewardQuantity);
|
||||||
throw new RuntimeException("奖励已被领完,请下次早点来");
|
if (!success) {
|
||||||
|
throw new RuntimeException("The rewards have been collected, please come earlier next time");
|
||||||
}
|
}
|
||||||
|
|
||||||
// 6. 解析奖励配置
|
// 5. 解析奖励配置
|
||||||
List<PropsActivityRewardConfigInfoDTO> rewardList = parseRewardConfig(config.getRewardConfig().toJSONString());
|
List<PropsActivityRewardConfigInfoDTO> rewardList = parseRewardConfig(config.getRewardConfig().toJSONString());
|
||||||
if (rewardList == null || rewardList.isEmpty()) {
|
if (rewardList == null || rewardList.isEmpty()) {
|
||||||
throw new RuntimeException("奖励配置为空");
|
throw new RuntimeException("奖励配置为空");
|
||||||
}
|
}
|
||||||
|
|
||||||
// 7. 随机选择一个奖励
|
// 6. 随机选择一个奖励
|
||||||
PropsActivityRewardConfigInfoDTO selectedReward = rewardList.get(random.nextInt(rewardList.size()));
|
PropsActivityRewardConfigInfoDTO selectedReward = rewardList.get(random.nextInt(rewardList.size()));
|
||||||
|
|
||||||
// 8. 发放奖励
|
// 7. 发放奖励
|
||||||
String walletBizNo = RocketRewardLog.buildBizNo(roomId.toString(), userId);
|
String walletBizNo = RocketRewardLog.buildBizNo(roomId.toString(), userId);
|
||||||
grantReward(userId, selectedReward, walletBizNo);
|
grantReward(userId, selectedReward, walletBizNo);
|
||||||
|
|
||||||
// 9. 保存领取记录
|
// 8. 保存领取记录
|
||||||
saveRewardLog(roomId, userId, today, rocketLevel, selectedReward, walletBizNo);
|
saveRewardLog(roomId, userId, latestHistory, selectedReward, walletBizNo);
|
||||||
|
|
||||||
// 10. 更新领取人数
|
|
||||||
rocketStatus.incrementClaimCount();
|
|
||||||
rocketStatusGateway.save(rocketStatus);
|
|
||||||
|
|
||||||
// 11. 推送领取成功消息
|
// 9. 推送领取成功消息
|
||||||
try {
|
try {
|
||||||
String userName = "用户" + userId;
|
String userName = "用户" + userId;
|
||||||
Long rewardAmount = getRewardAmount(selectedReward);
|
Long rewardAmount = getRewardAmount(selectedReward);
|
||||||
@ -134,7 +128,7 @@ public class RocketRewardClaimCmdExe {
|
|||||||
log.error("推送奖励领取消息失败: roomId={}, userId={}", roomId, userId, e);
|
log.error("推送奖励领取消息失败: roomId={}, userId={}", roomId, userId, e);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 12. 构建返回结果
|
// 10. 构建返回结果
|
||||||
RocketRewardCO rewardCO = new RocketRewardCO();
|
RocketRewardCO rewardCO = new RocketRewardCO();
|
||||||
rewardCO.setRewardType(selectedReward.getType());
|
rewardCO.setRewardType(selectedReward.getType());
|
||||||
rewardCO.setRewardItemId(selectedReward.getId());
|
rewardCO.setRewardItemId(selectedReward.getId());
|
||||||
@ -218,7 +212,6 @@ public class RocketRewardClaimCmdExe {
|
|||||||
.build()
|
.build()
|
||||||
);
|
);
|
||||||
|
|
||||||
log.info("金币发放成功: userId={}, amount={}", userId, goldAmount);
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error("金币发放失败: userId={}, amount={}", userId, goldAmount, e);
|
log.error("金币发放失败: userId={}, amount={}", userId, goldAmount, e);
|
||||||
throw new RuntimeException("金币发放失败");
|
throw new RuntimeException("金币发放失败");
|
||||||
@ -243,8 +236,8 @@ public class RocketRewardClaimCmdExe {
|
|||||||
.setOpUser(userId);
|
.setOpUser(userId);
|
||||||
|
|
||||||
propsBackpackClient.giveProps(cmd);
|
propsBackpackClient.giveProps(cmd);
|
||||||
log.info("道具发放成功(TODO): userId={}, propId={}, quantity={}, type={}",
|
// 发送通知
|
||||||
userId, propId, quantity, detailType);
|
propsBackpackClient.givePropsNotify(userId, detailType, quantity, propId);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error("道具发放失败: userId={}, propId={}", userId, propId, e);
|
log.error("道具发放失败: userId={}, propId={}", userId, propId, e);
|
||||||
throw new RuntimeException("道具发放失败");
|
throw new RuntimeException("道具发放失败");
|
||||||
@ -270,7 +263,8 @@ public class RocketRewardClaimCmdExe {
|
|||||||
.setBadgeType(SysBadgeConfigTypeEnum.ACTIVITY)
|
.setBadgeType(SysBadgeConfigTypeEnum.ACTIVITY)
|
||||||
);
|
);
|
||||||
|
|
||||||
log.info("徽章发放成功(TODO): userId={}, badgeId={}", userId, badgeId);
|
// 发送通知
|
||||||
|
propsBackpackClient.givePropsNotify(userId, SysBadgeConfigTypeEnum.ACTIVITY.name(), quantity, badgeId);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error("徽章发放失败: userId={}, badgeId={}", userId, badgeId, e);
|
log.error("徽章发放失败: userId={}, badgeId={}", userId, badgeId, e);
|
||||||
throw new RuntimeException("徽章发放失败");
|
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) {
|
PropsActivityRewardConfigInfoDTO reward, String walletBizNo) {
|
||||||
RocketRewardLog log = new RocketRewardLog();
|
RocketRewardLog log = new RocketRewardLog();
|
||||||
|
log.setRocketHistoryId(rocketHistory.getId());
|
||||||
log.setRoomId(roomId);
|
log.setRoomId(roomId);
|
||||||
log.setUserId(userId);
|
log.setUserId(userId);
|
||||||
log.setRocketLevel(level);
|
log.setRocketLevel(rocketHistory.getLevel());
|
||||||
log.setIsContributor(0);
|
log.setIsContributor(0);
|
||||||
log.setContributionEnergy(0L);
|
log.setContributionEnergy(0L);
|
||||||
log.setContributionRate(null);
|
log.setContributionRate(null);
|
||||||
|
|||||||
@ -18,6 +18,22 @@ public interface RocketHistoryGateway {
|
|||||||
*/
|
*/
|
||||||
String save(RocketHistory history);
|
String save(RocketHistory history);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询今天最新的火箭发射记录(按发射时间倒序)
|
||||||
|
*/
|
||||||
|
RocketHistory findLatestByRoomIdAndDate(Long roomId, String date);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 尝试原子递增领取人数(带上限检查)
|
||||||
|
* @return 是否成功递增
|
||||||
|
*/
|
||||||
|
boolean tryIncrementClaimCount(String historyId, int maxCount);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 增加领取人数
|
||||||
|
*/
|
||||||
|
void incrementClaimCount(String historyId);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 根据ID查询
|
* 根据ID查询
|
||||||
*/
|
*/
|
||||||
|
|||||||
@ -26,6 +26,10 @@ public class RocketHistory {
|
|||||||
private Integer totalContributors;
|
private Integer totalContributors;
|
||||||
private RewardPool rewardPool;
|
private RewardPool rewardPool;
|
||||||
private ClaimStats claimStats;
|
private ClaimStats claimStats;
|
||||||
|
/**
|
||||||
|
* 已领取人数
|
||||||
|
*/
|
||||||
|
private Integer claimedCount;
|
||||||
private LocalDateTime launchTime;
|
private LocalDateTime launchTime;
|
||||||
private LocalDateTime claimStartTime;
|
private LocalDateTime claimStartTime;
|
||||||
private LocalDateTime claimEndTime;
|
private LocalDateTime claimEndTime;
|
||||||
|
|||||||
@ -54,7 +54,7 @@ public class RocketConfigConvertor {
|
|||||||
} else {
|
} else {
|
||||||
config.setNormalRewardConfig(new JSONArray());
|
config.setNormalRewardConfig(new JSONArray());
|
||||||
}
|
}
|
||||||
|
config.setRewardQuantity(entity.getRewardQuantity());
|
||||||
config.setStatus(entity.getStatus());
|
config.setStatus(entity.getStatus());
|
||||||
// config.setCreatedAt(entity.getCreatedAt());
|
// config.setCreatedAt(entity.getCreatedAt());
|
||||||
// config.setUpdatedAt(entity.getUpdatedAt());
|
// config.setUpdatedAt(entity.getUpdatedAt());
|
||||||
@ -91,7 +91,8 @@ public class RocketConfigConvertor {
|
|||||||
} else {
|
} else {
|
||||||
entity.setNormalRewardConfig(null);
|
entity.setNormalRewardConfig(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
entity.setRewardQuantity(config.getRewardQuantity());
|
||||||
entity.setStatus(config.getStatus());
|
entity.setStatus(config.getStatus());
|
||||||
// createdAt 和 updatedAt 由数据库自动管理
|
// createdAt 和 updatedAt 由数据库自动管理
|
||||||
|
|
||||||
|
|||||||
@ -2,6 +2,7 @@ package com.red.circle.other.infra.database.mongo.repository;
|
|||||||
|
|
||||||
import com.red.circle.other.infra.database.mongo.document.RocketHistoryDocument;
|
import com.red.circle.other.infra.database.mongo.document.RocketHistoryDocument;
|
||||||
import org.springframework.data.mongodb.repository.MongoRepository;
|
import org.springframework.data.mongodb.repository.MongoRepository;
|
||||||
|
import org.springframework.data.mongodb.repository.Query;
|
||||||
import org.springframework.stereotype.Repository;
|
import org.springframework.stereotype.Repository;
|
||||||
|
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
@ -21,6 +22,11 @@ public interface RocketHistoryRepository extends MongoRepository<RocketHistoryDo
|
|||||||
*/
|
*/
|
||||||
List<RocketHistoryDocument> findByRoomIdOrderByLaunchTimeDesc(Long roomId);
|
List<RocketHistoryDocument> findByRoomIdOrderByLaunchTimeDesc(Long roomId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询今天最新的火箭发射记录(按发射时间倒序)
|
||||||
|
*/
|
||||||
|
RocketHistoryDocument findFirstByRoomIdAndDateOrderByLaunchTimeDesc(Long roomId, String date);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 根据房间ID和日期查询
|
* 根据房间ID和日期查询
|
||||||
*/
|
*/
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
package com.red.circle.other.infra.gateway;
|
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.gateway.RocketHistoryGateway;
|
||||||
import com.red.circle.other.domain.rocket.RocketHistory;
|
import com.red.circle.other.domain.rocket.RocketHistory;
|
||||||
import com.red.circle.other.infra.convertor.RocketHistoryConvertor;
|
import com.red.circle.other.infra.convertor.RocketHistoryConvertor;
|
||||||
@ -41,6 +42,40 @@ public class RocketHistoryGatewayImpl implements RocketHistoryGateway {
|
|||||||
return saved.getId();
|
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
|
@Override
|
||||||
public RocketHistory findById(String id) {
|
public RocketHistory findById(String id) {
|
||||||
return rocketHistoryRepository.findById(id)
|
return rocketHistoryRepository.findById(id)
|
||||||
|
|||||||
@ -15,7 +15,7 @@
|
|||||||
</resultMap>
|
</resultMap>
|
||||||
|
|
||||||
<sql id="Base_Column_List">
|
<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
|
normal_reward_config, status, created_at, updated_at
|
||||||
</sql>
|
</sql>
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user