与任务执行,新增信号量锁,解决并发环境下数据的一致性问题

This commit is contained in:
yang.lee
2023-11-03 22:12:01 +08:00
parent 669c4228e8
commit 537e54b565
5 changed files with 61 additions and 28 deletions

View File

@@ -54,8 +54,10 @@ namespace Tnb.WarehouseMgr
public class BaseWareHouseService : IOverideVisualDevService, IDynamicApiController, ITransient public class BaseWareHouseService : IOverideVisualDevService, IDynamicApiController, ITransient
{ {
private static Lazy<Dictionary<string, IWHStorageService>> _stroageMapLazy; private static Lazy<Dictionary<string, IWHStorageService>> _stroageMapLazy;
private static Dictionary<string, IWHStorageService> _storeMap = new(StringComparer.OrdinalIgnoreCase);
public OverideVisualDevFunc OverideFuncs { get; } = new OverideVisualDevFunc(); public OverideVisualDevFunc OverideFuncs { get; } = new OverideVisualDevFunc();
public static SemaphoreSlim s_taskExecuteSemaphore = new SemaphoreSlim(1);
private IEventPublisher _eventPublisher; private IEventPublisher _eventPublisher;
@@ -68,10 +70,6 @@ namespace Tnb.WarehouseMgr
/*public BaseWareHouseService(ChannelWriter<NotifyMessage>? channelWriter = default)
{
_channelWriter = channelWriter;
}*/
static BaseWareHouseService() static BaseWareHouseService()
{ {

View File

@@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using JNPF;
using JNPF.Common.Contracts; using JNPF.Common.Contracts;
using JNPF.Logging; using JNPF.Logging;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
@@ -13,19 +14,35 @@ namespace Tnb.WarehouseMgr
{ {
public class BaseWareHouseService<T> : BaseWareHouseService public class BaseWareHouseService<T> : BaseWareHouseService
{ {
protected static Dictionary<string, object> _elevatorMap = new Dictionary<string, object>(); protected static Dictionary<string, object> s_elevatorMap = new Dictionary<string, object>();
private static readonly Lazy<Task> initializationTask;
public BaseWareHouseService(ISqlSugarClient db)
static BaseWareHouseService()
{ {
if (_elevatorMap.Count < 1) initializationTask = new Lazy<Task>(InitializeAsync);
{
Task.Run(async () =>
{
_elevatorMap = await db.Queryable<WmsElevatorH>().ToDictionaryAsync(x => x.elevator_id, x => x.elevator_code);
});
}
} }
private static async Task InitializeAsync()
{
ConnectionStringsOptions connectionOpts = App.GetConfig<ConnectionStringsOptions>("ConnectionStrings", true);
ConnectionConfig cfg = new()
{
ConfigId = connectionOpts.ConfigId,
ConnectionString = connectionOpts.ConnectString,
DbType = DbType.PostgreSQL,
IsAutoCloseConnection = true,
};
SqlSugarScope context = new(cfg);
s_elevatorMap = await context.Queryable<WmsElevatorH>().ToDictionaryAsync(x => x.elevator_id, x => x.elevator_code);
}
public static Task InitializationTask => initializationTask.Value;
protected ILogger Logger => LoggerFactory.Create(builder => builder.AddFile($"{AppContext.BaseDirectory}/logs/custom{DateTime.Now:yyyyMMdd}.log", cfgOpts => protected ILogger Logger => LoggerFactory.Create(builder => builder.AddFile($"{AppContext.BaseDirectory}/logs/custom{DateTime.Now:yyyyMMdd}.log", cfgOpts =>
{ {

View File

@@ -61,7 +61,7 @@ namespace Tnb.WarehouseMgr
IEventPublisher eventPublisher, IEventPublisher eventPublisher,
IUserManager userManger, IUserManager userManger,
IElevatorControlService elevatorControlService IElevatorControlService elevatorControlService
) : base(repository.AsSugarClient()) ) //: base(repository.AsSugarClient())
{ {
_db = repository.AsSugarClient(); _db = repository.AsSugarClient();
_wareHouseService = wareHouseService; _wareHouseService = wareHouseService;
@@ -69,6 +69,7 @@ namespace Tnb.WarehouseMgr
_eventPublisher = eventPublisher; _eventPublisher = eventPublisher;
_userManager = userManger; _userManager = userManger;
_elevatorControlService = elevatorControlService; _elevatorControlService = elevatorControlService;
_ = InitializationTask;
} }
/// <summary> /// <summary>
@@ -111,7 +112,7 @@ namespace Tnb.WarehouseMgr
try try
{ {
Logger.Information($"当前任务Id:{elevator.distask_id}"); Logger.Information($"当前任务Id:{elevator.distask_id}");
if (_elevatorMap.TryGetValue(elevator.device_id, out var elevatorCode)) if (s_elevatorMap.TryGetValue(elevator.device_id, out var elevatorCode))
{ {
var devName = elevatorCode?.ToString() ?? _eleCtlCfg.DevName; var devName = elevatorCode?.ToString() ?? _eleCtlCfg.DevName;
(int sysStatus, int runStatus, int floorNo, int doorStatus, int agvStatus) = await _elevatorControlService.GetElevatorStatus(devName, CancellationToken.None); (int sysStatus, int runStatus, int floorNo, int doorStatus, int agvStatus) = await _elevatorControlService.GetElevatorStatus(devName, CancellationToken.None);
@@ -164,7 +165,7 @@ namespace Tnb.WarehouseMgr
.FirstAsync(); .FirstAsync();
if (elevator.IsNull()) if (elevator.IsNull())
throw new Exception($"根据参数,sourceName:{input.sourceName},taskCode:{input.taskCode},未找到匹配的电梯任务"); throw new Exception($"根据参数,sourceName:{input.sourceName},taskCode:{input.taskCode},未找到匹配的电梯任务");
if (_elevatorMap.TryGetValue(elevator.elevator_id, out var elevatorCode)) if (s_elevatorMap.TryGetValue(elevator.elevator_id, out var elevatorCode))
{ {
var devName = elevatorCode?.ToString() ?? _eleCtlCfg.DevName; var devName = elevatorCode?.ToString() ?? _eleCtlCfg.DevName;
(int sysStatus, int runStatus, int floorNo, int doorStatus, int agvStatus) = await _elevatorControlService.GetElevatorStatus(devName, CancellationToken.None);//elevator.elevator_code (int sysStatus, int runStatus, int floorNo, int doorStatus, int agvStatus) = await _elevatorControlService.GetElevatorStatus(devName, CancellationToken.None);//elevator.elevator_code

View File

@@ -54,7 +54,7 @@ namespace Tnb.WarehouseMgr
public WareHouseService(ISqlSugarRepository<WmsInstockH> repository, IDictionaryDataService dictionaryDataService, public WareHouseService(ISqlSugarRepository<WmsInstockH> repository, IDictionaryDataService dictionaryDataService,
IBillRullService billRullService, IUserManager userManager, ICacheManager cacheManager, IElevatorControlService elevatorControlService) IBillRullService billRullService, IUserManager userManager, ICacheManager cacheManager, IElevatorControlService elevatorControlService)
: base(repository.AsSugarClient()) //: base(repository.AsSugarClient())
{ {
_db = repository.AsSugarClient(); _db = repository.AsSugarClient();
_dictionaryDataService = dictionaryDataService; _dictionaryDataService = dictionaryDataService;
@@ -62,6 +62,7 @@ namespace Tnb.WarehouseMgr
_userManager = userManager; _userManager = userManager;
_cacheManager = cacheManager; _cacheManager = cacheManager;
_elevatorControlService = elevatorControlService; _elevatorControlService = elevatorControlService;
_ = InitializationTask;
} }
@@ -215,19 +216,18 @@ namespace Tnb.WarehouseMgr
/// 生成任务执行 /// 生成任务执行
/// </summary> /// </summary>
/// <returns></returns> /// <returns></returns>
[HttpPost, Timed(Name = nameof(IWareHouseService.GenTaskExecute))] [HttpPost]
public async Task GenTaskExecute() public async Task GenTaskExecute()
{ {
await s_taskExecuteSemaphore.WaitAsync();
Stopwatch sw = Stopwatch.StartNew(); Stopwatch sw = Stopwatch.StartNew();
CancellationTokenSource agvCts = new(); CancellationTokenSource agvCts = new();
var db = _db.CopyNew(); var db = _db.CopyNew();
try try
{ {
/*if (_elevatorMap.Count < 1)
{
_elevatorMap = await _db.Queryable<WmsElevatorH>().ToDictionaryAsync(x => x.elevator_id, x => x.elevator_code);
}*/
//获取电梯数据 //获取电梯数据
var elevatorList = await db.Queryable<WmsElevatorH>().InnerJoin<WmsElevatorD>((a, b) => a.id == b.bill_id) var elevatorList = await db.Queryable<WmsElevatorH>().InnerJoin<WmsElevatorD>((a, b) => a.id == b.bill_id)
.Select((a, b) => new WmsElevatorH .Select((a, b) => new WmsElevatorH
@@ -420,6 +420,7 @@ namespace Tnb.WarehouseMgr
} }
finally finally
{ {
s_taskExecuteSemaphore.Release();
agvCts.Dispose(); agvCts.Dispose();
} }
} }
@@ -436,7 +437,7 @@ namespace Tnb.WarehouseMgr
foreach (var (_, devId, disTaskId, floorNO) in endLocCodes) foreach (var (_, devId, disTaskId, floorNO) in endLocCodes)
{ {
if (!_elevatorMap.TryGetValue(devId, out var elevatorCode)) continue; if (!s_elevatorMap.TryGetValue(devId, out var elevatorCode)) continue;
var devName = elevatorCode.ToString(); var devName = elevatorCode.ToString();
@@ -510,14 +511,27 @@ namespace Tnb.WarehouseMgr
Logger.Information($"开始执行电梯任务任务ID:{disTask.id}"); Logger.Information($"开始执行电梯任务任务ID:{disTask.id}");
try try
{ {
if (!_elevatorMap.TryGetValue(disTask.device_id, out var elevatorCode)) if (!s_elevatorMap.TryGetValue(disTask.device_id, out var elevatorCode))
{ {
return; return;
} }
var devName = _elevatorMap[disTask.device_id]?.ToString() ?? _eleCtlCfg.DevName; var devName = s_elevatorMap[disTask.device_id]?.ToString() ?? _eleCtlCfg.DevName;
Logger.Information($"当前:{devName.Match(@"\d+")}#梯"); Logger.Information($"当前:{devName.Match(@"\d+")}#梯");
await _elevatorControlService.WriteTagAsync(devName, ElevatorConsts.AGVControl, 1);
(int sysStatus, int runStatus, int curFloorNo, int doorStatus, int agvStatus) eleStatusMulti = (-1, -1, -1, -1, -1);
if (!_elevatorAgvCtlStatusMap.TryGetValue(disTask.id, out var agvCtlStatus) || agvCtlStatus != (int)EnumAgvStatus.AGV运行状态)
{
do
{
eleStatusMulti = await _elevatorControlService.GetElevatorStatus(devName, CancellationToken.None);
await Task.Delay(500);
} while (eleStatusMulti.agvStatus != (int)EnumAgvStatus.AGV运行状态);
Logger.Information($"{devName.Match(@"\d+")}#, 当前Agv状态:{eleStatusMulti.agvStatus.ToEnum<EnumAgvStatus>().ToString()}");
_elevatorAgvCtlStatusMap[disTask.id] = eleStatusMulti.agvStatus;
}
var doorStatus = -1; var doorStatus = -1;
var closeDoorRes = await _elevatorControlService.SendOpenCloseCmd(devName, 4); //向电梯发送前门关门指令 var closeDoorRes = await _elevatorControlService.SendOpenCloseCmd(devName, 4); //向电梯发送前门关门指令
Logger.Information($"关门结果:{closeDoorRes}"); Logger.Information($"关门结果:{closeDoorRes}");

View File

@@ -17,7 +17,9 @@ using JNPF.VisualDev;
using JNPF.VisualDev.Entitys; using JNPF.VisualDev.Entitys;
using JNPF.VisualDev.Interfaces; using JNPF.VisualDev.Interfaces;
using Mapster; using Mapster;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Newtonsoft.Json;
using Spire.Doc.Formatting; using Spire.Doc.Formatting;
using SqlSugar; using SqlSugar;
using Tnb.BasicData.Entities; using Tnb.BasicData.Entities;
@@ -38,7 +40,7 @@ namespace Tnb.WarehouseMgr
[OverideVisualDev(ModuleConsts.MODULE_WMSEMPTYINSTOCK_ID)] [OverideVisualDev(ModuleConsts.MODULE_WMSEMPTYINSTOCK_ID)]
[ServiceModule(BizTypeId)] [ServiceModule(BizTypeId)]
public class WmsEmptyInstockService : BaseWareHouseService, IWmsEmptyInstockService public class WmsEmptyInstockService : BaseWareHouseService<WmsEmptyInstockService>, IWmsEmptyInstockService
{ {
private const string BizTypeId = "26121986416677"; private const string BizTypeId = "26121986416677";
private readonly ISqlSugarClient _db; private readonly ISqlSugarClient _db;
@@ -64,7 +66,7 @@ namespace Tnb.WarehouseMgr
_wareHouseService = wareHouseService; _wareHouseService = wareHouseService;
_userManager = userManager; _userManager = userManager;
_billRullService = billRullService; _billRullService = billRullService;
OverideFuncs.CreateAsync = WmsEmptyIn; OverideFuncs.CreateAsync = WmsEmptyIn;
} }
private async Task<dynamic> WmsEmptyIn(VisualDevModelDataCrInput input) private async Task<dynamic> WmsEmptyIn(VisualDevModelDataCrInput input)
@@ -189,6 +191,7 @@ namespace Tnb.WarehouseMgr
finally finally
{ {
//向队列写入消息 //向队列写入消息
Logger.Information("调用预任务生成");
await InvokeGenPretaskExcute(); await InvokeGenPretaskExcute();
} }
return Task.FromResult(true); return Task.FromResult(true);