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.Mvc;
|
||||
using Volo.Abp;
|
||||
@@ -19,7 +20,7 @@ public class ActivationCodeService : ApplicationService, IActivationCodeService
|
||||
private readonly ActivationCodeManager _activationCodeManager;
|
||||
private readonly IRechargeService _rechargeService;
|
||||
private readonly PremiumPackageManager _premiumPackageManager;
|
||||
|
||||
private IDistributedLockProvider DistributedLock => LazyServiceProvider.LazyGetRequiredService<IDistributedLockProvider>();
|
||||
public ActivationCodeService(
|
||||
ActivationCodeManager activationCodeManager,
|
||||
IRechargeService rechargeService,
|
||||
@@ -68,6 +69,10 @@ public class ActivationCodeService : ApplicationService, IActivationCodeService
|
||||
[HttpPost("activationCode/Redeem")]
|
||||
public async Task<ActivationCodeRedeemOutput> RedeemAsync(ActivationCodeRedeemInput input)
|
||||
{
|
||||
//自旋等待,防抖
|
||||
await using var handle =
|
||||
await DistributedLock.AcquireLockAsync($"Yi:AiHub:ActivationCodeLock:{input.Code}");
|
||||
|
||||
var userId = CurrentUser.GetId();
|
||||
var redeemContext = await _activationCodeManager.RedeemAsync(userId, input.Code);
|
||||
var goodsType = redeemContext.ActivationCode.GoodsType;
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
using Medallion.Threading;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using SqlSugar;
|
||||
@@ -23,7 +24,7 @@ public class DailyTaskService : ApplicationService
|
||||
private readonly ISqlSugarRepository<MessageAggregateRoot> _messageRepository;
|
||||
private readonly ISqlSugarRepository<PremiumPackageAggregateRoot> _premiumPackageRepository;
|
||||
private readonly ILogger<DailyTaskService> _logger;
|
||||
|
||||
private IDistributedLockProvider DistributedLock => LazyServiceProvider.LazyGetRequiredService<IDistributedLockProvider>();
|
||||
// 任务配置
|
||||
private readonly Dictionary<int, (long RequiredTokens, long RewardTokens, string Name, string Description)>
|
||||
_taskConfigs = new()
|
||||
@@ -113,6 +114,11 @@ public class DailyTaskService : ApplicationService
|
||||
public async Task ClaimTaskRewardAsync(ClaimTaskRewardInput input)
|
||||
{
|
||||
var userId = CurrentUser.GetId();
|
||||
//自旋等待,防抖
|
||||
await using var handle =
|
||||
await DistributedLock.AcquireLockAsync($"Yi:AiHub:ClaimTaskRewardLock:{userId}");
|
||||
|
||||
|
||||
var today = DateTime.Today;
|
||||
|
||||
// 1. 验证任务等级
|
||||
|
||||
Reference in New Issue
Block a user