fix: 为领奖与兑换流程添加分布式锁,防止并发重复操作
- 在 DailyTaskService 与 ActivationCodeService 中引入 Medallion.Threading。 - 通过 LazyServiceProvider 获取 IDistributedLockProvider(DistributedLock 属性)。 - 在 ClaimTaskRewardAsync(DailyTaskService)和 RedeemAsync(ActivationCodeService)中使用 AcquireLockAsync 加锁(基于 userId / activation code),用于自旋等待、防抖,避免并发导致的重复发放或重复兑换问题。
This commit is contained in:
@@ -1,3 +1,4 @@
|
|||||||
|
using Medallion.Threading;
|
||||||
using Microsoft.AspNetCore.Authorization;
|
using Microsoft.AspNetCore.Authorization;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using Volo.Abp;
|
using Volo.Abp;
|
||||||
@@ -19,7 +20,7 @@ public class ActivationCodeService : ApplicationService, IActivationCodeService
|
|||||||
private readonly ActivationCodeManager _activationCodeManager;
|
private readonly ActivationCodeManager _activationCodeManager;
|
||||||
private readonly IRechargeService _rechargeService;
|
private readonly IRechargeService _rechargeService;
|
||||||
private readonly PremiumPackageManager _premiumPackageManager;
|
private readonly PremiumPackageManager _premiumPackageManager;
|
||||||
|
private IDistributedLockProvider DistributedLock => LazyServiceProvider.LazyGetRequiredService<IDistributedLockProvider>();
|
||||||
public ActivationCodeService(
|
public ActivationCodeService(
|
||||||
ActivationCodeManager activationCodeManager,
|
ActivationCodeManager activationCodeManager,
|
||||||
IRechargeService rechargeService,
|
IRechargeService rechargeService,
|
||||||
@@ -68,6 +69,10 @@ public class ActivationCodeService : ApplicationService, IActivationCodeService
|
|||||||
[HttpPost("activationCode/Redeem")]
|
[HttpPost("activationCode/Redeem")]
|
||||||
public async Task<ActivationCodeRedeemOutput> RedeemAsync(ActivationCodeRedeemInput input)
|
public async Task<ActivationCodeRedeemOutput> RedeemAsync(ActivationCodeRedeemInput input)
|
||||||
{
|
{
|
||||||
|
//自旋等待,防抖
|
||||||
|
await using var handle =
|
||||||
|
await DistributedLock.AcquireLockAsync($"Yi:AiHub:ActivationCodeLock:{input.Code}");
|
||||||
|
|
||||||
var userId = CurrentUser.GetId();
|
var userId = CurrentUser.GetId();
|
||||||
var redeemContext = await _activationCodeManager.RedeemAsync(userId, input.Code);
|
var redeemContext = await _activationCodeManager.RedeemAsync(userId, input.Code);
|
||||||
var goodsType = redeemContext.ActivationCode.GoodsType;
|
var goodsType = redeemContext.ActivationCode.GoodsType;
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
using Medallion.Threading;
|
||||||
using Microsoft.AspNetCore.Authorization;
|
using Microsoft.AspNetCore.Authorization;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using SqlSugar;
|
using SqlSugar;
|
||||||
@@ -23,7 +24,7 @@ public class DailyTaskService : ApplicationService
|
|||||||
private readonly ISqlSugarRepository<MessageAggregateRoot> _messageRepository;
|
private readonly ISqlSugarRepository<MessageAggregateRoot> _messageRepository;
|
||||||
private readonly ISqlSugarRepository<PremiumPackageAggregateRoot> _premiumPackageRepository;
|
private readonly ISqlSugarRepository<PremiumPackageAggregateRoot> _premiumPackageRepository;
|
||||||
private readonly ILogger<DailyTaskService> _logger;
|
private readonly ILogger<DailyTaskService> _logger;
|
||||||
|
private IDistributedLockProvider DistributedLock => LazyServiceProvider.LazyGetRequiredService<IDistributedLockProvider>();
|
||||||
// 任务配置
|
// 任务配置
|
||||||
private readonly Dictionary<int, (long RequiredTokens, long RewardTokens, string Name, string Description)>
|
private readonly Dictionary<int, (long RequiredTokens, long RewardTokens, string Name, string Description)>
|
||||||
_taskConfigs = new()
|
_taskConfigs = new()
|
||||||
@@ -113,6 +114,11 @@ public class DailyTaskService : ApplicationService
|
|||||||
public async Task ClaimTaskRewardAsync(ClaimTaskRewardInput input)
|
public async Task ClaimTaskRewardAsync(ClaimTaskRewardInput input)
|
||||||
{
|
{
|
||||||
var userId = CurrentUser.GetId();
|
var userId = CurrentUser.GetId();
|
||||||
|
//自旋等待,防抖
|
||||||
|
await using var handle =
|
||||||
|
await DistributedLock.AcquireLockAsync($"Yi:AiHub:ClaimTaskRewardLock:{userId}");
|
||||||
|
|
||||||
|
|
||||||
var today = DateTime.Today;
|
var today = DateTime.Today;
|
||||||
|
|
||||||
// 1. 验证任务等级
|
// 1. 验证任务等级
|
||||||
|
|||||||
Reference in New Issue
Block a user