领取奖励新增锁

This commit is contained in:
tianfeng 2025-10-22 15:09:06 +08:00
parent e9a281e8dd
commit b206158d06

View File

@ -1,6 +1,7 @@
package com.red.circle.other.app.command; package com.red.circle.other.app.command;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.red.circle.component.redis.service.RedisService;
import com.red.circle.other.app.dto.clientobject.SpinsTaskRewardCO; import com.red.circle.other.app.dto.clientobject.SpinsTaskRewardCO;
import com.red.circle.other.app.dto.cmd.SpinsTaskReceiveRewardCmd; import com.red.circle.other.app.dto.cmd.SpinsTaskReceiveRewardCmd;
import com.red.circle.other.infra.database.rds.entity.task.SpinsTaskConfig; import com.red.circle.other.infra.database.rds.entity.task.SpinsTaskConfig;
@ -13,6 +14,7 @@ import com.red.circle.other.inner.endpoint.activity.LotteryTicketClient;
import com.red.circle.tool.core.date.TimestampUtils; import com.red.circle.tool.core.date.TimestampUtils;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
@ -20,6 +22,7 @@ import java.time.LocalDate;
import java.time.format.DateTimeFormatter; import java.time.format.DateTimeFormatter;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.concurrent.TimeUnit;
/** /**
* 领取任务奖励执行器 * 领取任务奖励执行器
@ -36,6 +39,10 @@ public class SpinsTaskReceiveRewardExe {
private final SpinsUserTaskProgressDAO spinsUserTaskProgressDAO; private final SpinsUserTaskProgressDAO spinsUserTaskProgressDAO;
private final SpinsUserTaskRecordDAO spinsUserTaskRecordDAO; private final SpinsUserTaskRecordDAO spinsUserTaskRecordDAO;
private final LotteryTicketClient lotteryTicketClient; private final LotteryTicketClient lotteryTicketClient;
private final RedisService redisService;
private static final String LOCK_KEY_PREFIX = "spins:task:receive:lock:";
private static final long LOCK_EXPIRE_TIME = 10; // 锁过期时间10秒
/** /**
* 执行领取任务奖励 * 执行领取任务奖励
@ -48,6 +55,36 @@ public class SpinsTaskReceiveRewardExe {
Long userId = cmd.getReqUserId(); Long userId = cmd.getReqUserId();
String taskCode = cmd.getTaskCode(); String taskCode = cmd.getTaskCode();
// 构建分布式锁key
String lockKey = LOCK_KEY_PREFIX + userId + ":" + taskCode;
// 尝试获取锁
boolean lockSuccess = redisService.setIfAbsent(lockKey, String.valueOf(System.currentTimeMillis()),
LOCK_EXPIRE_TIME, TimeUnit.SECONDS);
if (!lockSuccess) {
log.warn("领取任务奖励请求过于频繁,请稍后再试, userId={}, taskCode={}", userId, taskCode);
throw new RuntimeException("The request is too frequent. Please try again later");
}
try {
return executeReceiveReward(userId, taskCode);
} finally {
// 释放锁
redisService.delete(lockKey);
}
}
/**
* 执行领取任务奖励的核心逻辑
*/
private SpinsTaskRewardCO executeReceiveReward(Long userId, String taskCode) {
try {
Thread.sleep(1000L);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
// 1. 查询任务配置 // 1. 查询任务配置
List<SpinsTaskConfig> spinsTaskConfigs = spinsTaskConfigDAO.selectList( List<SpinsTaskConfig> spinsTaskConfigs = spinsTaskConfigDAO.selectList(
new LambdaQueryWrapper<SpinsTaskConfig>() new LambdaQueryWrapper<SpinsTaskConfig>()