diff --git a/src/WMS.Web.Domain/Services/InStockService.cs b/src/WMS.Web.Domain/Services/InStockService.cs index e9e5620f..e80f8382 100644 --- a/src/WMS.Web.Domain/Services/InStockService.cs +++ b/src/WMS.Web.Domain/Services/InStockService.cs @@ -2,7 +2,9 @@ using Microsoft.EntityFrameworkCore.Storage; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; using Newtonsoft.Json; +using StackExchange.Redis; using System; using System.Collections.Concurrent; using System.Collections.Generic; @@ -25,6 +27,7 @@ using WMS.Web.Domain.Infrastructure; using WMS.Web.Domain.IService; using WMS.Web.Domain.IService.Public; using WMS.Web.Domain.Mappers; +using WMS.Web.Domain.Options; using WMS.Web.Domain.Values; using WMS.Web.Domain.Values.Erp; @@ -51,9 +54,11 @@ namespace WMS.Web.Domain.Services private readonly IBoxInventoryRepositories _boxInventoryRepositories; private readonly ILogger _logger; private readonly IServiceScopeFactory _serviceScopeFactory; + private readonly AppOptions _options; + private ConnectionMultiplexer redisMultiplexer; + public StackExchange.Redis.IDatabase _redisDb = null; - private readonly ConcurrentDictionary _locks = new ConcurrentDictionary(); - public InStockService(IMapper mapper, ISerialNumbersRepositories serialNumbersRepositories, IErpService erpService, IBoxInventoryService boxInventoryService, ISerialNumberService serialNumberService, ILoginService loginService, IBoxRepositories boxRepositories, + public InStockService(IMapper mapper, IOptions options, ISerialNumbersRepositories serialNumbersRepositories, IErpService erpService, IBoxInventoryService boxInventoryService, ISerialNumberService serialNumberService, ILoginService loginService, IBoxRepositories boxRepositories, IBasicsRepositories basicsRepositories, IErpBasicDataExtendService erpBasicDataExtendService, IChangeMoveBoxService changeMoveBoxService, IInStockTaskBoxRepositories inStockTaskBoxRepositories, IInStockRepositories inStockRepositories, IInStockTaskRepositories inStockTaskRepositories, IBoxInventoryRepositories boxInventoryRepositories, ILogger logger, IServiceScopeFactory serviceScopeFactory) { @@ -73,6 +78,9 @@ namespace WMS.Web.Domain.Services _erpBasicDataExtendService = erpBasicDataExtendService; _serialNumbersRepositories = serialNumbersRepositories; _boxInventoryRepositories = boxInventoryRepositories; + _options = options?.Value; + redisMultiplexer = ConnectionMultiplexer.Connect(_options.RedisConnectionString); + _redisDb = redisMultiplexer.GetDatabase(); } /// @@ -133,42 +141,53 @@ namespace WMS.Web.Domain.Services /// public async Task Shelf(PurchaseShelfRequest instock, LoginInDto loginInfo) { - var taskId= instock.Details.Select(x => x.TaskId).FirstOrDefault(); + var taskId = instock.Details.Select(x => x.TaskId).FirstOrDefault(); - var taskLock = _locks.GetOrAdd(taskId, _ => new SemaphoreSlim(1, 1)); - await taskLock.WaitAsync(); - try + // 构建 Redis 锁的键名 + string lockKey = $"lock:taskid{taskId}"; + // 构建 Redis 锁的值,用于标识锁的持有者 + string lockValue = Guid.NewGuid().ToString(); + // 获取 Redis 锁,设置超时时间为 10 秒 + if (await _redisDb.LockTakeAsync(lockKey, lockValue, TimeSpan.FromSeconds(10))) { - IDbContextTransaction _transaction = _basicsRepositories.GetTransaction(); - bool isRollback = false; - bool isTransaction = false; - //1.添加入库单:(同步金蝶在save方法里面进行) - var save_result = await this.ShelfSave(instock, InstockType.Purchase, loginInfo, isTransaction); - if (!save_result.IsSuccess) isRollback = true; - - //实体 - var entity = save_result.Data; - - //提交事务 - var isSuccess = _basicsRepositories.CommitTransaction(isRollback, _transaction); - if (!isSuccess) - return save_result; - - //同步金蝶 - if (entity.Type == InstockType.Purchase) + try { - OperateRequest oRequest = new OperateRequest(); - oRequest.Ids.Add(entity.Id); - await Sync(oRequest, loginInfo, false); + IDbContextTransaction _transaction = _basicsRepositories.GetTransaction(); + bool isRollback = false; + bool isTransaction = false; + //1.添加入库单:(同步金蝶在save方法里面进行) + var save_result = await this.ShelfSave(instock, InstockType.Purchase, loginInfo, isTransaction); + if (!save_result.IsSuccess) isRollback = true; + + //实体 + var entity = save_result.Data; + + //提交事务 + var isSuccess = _basicsRepositories.CommitTransaction(isRollback, _transaction); + if (!isSuccess) + return save_result; + + //同步金蝶 + if (entity.Type == InstockType.Purchase) + { + OperateRequest oRequest = new OperateRequest(); + oRequest.Ids.Add(entity.Id); + await Sync(oRequest, loginInfo, false); + } + return Result.ReSuccess(); + } + finally + { + // 释放 Redis 锁 + await _redisDb.LockReleaseAsync(lockKey, lockValue); } - return Result.ReSuccess(); } - finally + else { - taskLock.Release(); + return Result.ReFailure(ResultCodes.Concurrent_Instock); } - + } /// diff --git a/src/WMS.Web.Domain/Services/InStockTaskBoxService.cs b/src/WMS.Web.Domain/Services/InStockTaskBoxService.cs index 17058422..b5971b43 100644 --- a/src/WMS.Web.Domain/Services/InStockTaskBoxService.cs +++ b/src/WMS.Web.Domain/Services/InStockTaskBoxService.cs @@ -37,13 +37,15 @@ namespace WMS.Web.Domain.Services var delete_ids = new List(); var t_boxIds = boxIds.Distinct().ToList(); var list= await _inStockTaskBoxRepositories.GetListBy(t_boxIds); - var boxInvetList = await _boxInventoryRepositories.GetList(t_boxIds); - foreach (var item in list) - { - var isHave= boxInvetList.Where(x => x.BoxId == item.BoxId).Any(); - if (!isHave) - delete_ids.Add(item.Id); - } + + delete_ids= list.Select(x => x.Id).ToList(); + //var boxInvetList = await _boxInventoryRepositories.GetList(t_boxIds); + //foreach (var item in list) + //{ + // var isHave= boxInvetList.Where(x => x.BoxId == item.BoxId).Any(); + // if (!isHave) + // delete_ids.Add(item.Id); + //} if (delete_ids.Count != 0) { diff --git a/src/WMS.Web.Domain/Services/Public/RedisClientService.cs b/src/WMS.Web.Domain/Services/Public/RedisClientService.cs index a631ed9d..3a8eb458 100644 --- a/src/WMS.Web.Domain/Services/Public/RedisClientService.cs +++ b/src/WMS.Web.Domain/Services/Public/RedisClientService.cs @@ -22,6 +22,8 @@ namespace WMS.Web.Domain.Services.Public db = redisMultiplexer.GetDatabase(); } + + #region String /// /// 保存单个key value diff --git a/src/WMS.Web.Domain/Values/ResultCodes.cs b/src/WMS.Web.Domain/Values/ResultCodes.cs index 93b8508a..b46fe6a0 100644 --- a/src/WMS.Web.Domain/Values/ResultCodes.cs +++ b/src/WMS.Web.Domain/Values/ResultCodes.cs @@ -24,7 +24,7 @@ namespace WMS.Web.Domain.Values public static ValueTuple NoDateError = (40005, "数据不存在"); public static ValueTuple SourceBillNoDateError = (40005, "来源单不存在,请核对后再试"); - public static ValueTuple Concurrent_Instock = (80005, "该任务单正在处理中"); + public static ValueTuple Concurrent_Instock = (80005, "该来源单正在处理中"); /// /// 没有菜单权限,无法登录