与任务执行,新增信号量锁,解决并发环境下数据的一致性问题
This commit is contained in:
@@ -54,8 +54,10 @@ namespace Tnb.WarehouseMgr
|
||||
public class BaseWareHouseService : IOverideVisualDevService, IDynamicApiController, ITransient
|
||||
{
|
||||
private static Lazy<Dictionary<string, IWHStorageService>> _stroageMapLazy;
|
||||
private static Dictionary<string, IWHStorageService> _storeMap = new(StringComparer.OrdinalIgnoreCase);
|
||||
public OverideVisualDevFunc OverideFuncs { get; } = new OverideVisualDevFunc();
|
||||
public static SemaphoreSlim s_taskExecuteSemaphore = new SemaphoreSlim(1);
|
||||
|
||||
|
||||
|
||||
private IEventPublisher _eventPublisher;
|
||||
|
||||
@@ -68,10 +70,6 @@ namespace Tnb.WarehouseMgr
|
||||
|
||||
|
||||
|
||||
/*public BaseWareHouseService(ChannelWriter<NotifyMessage>? channelWriter = default)
|
||||
{
|
||||
_channelWriter = channelWriter;
|
||||
}*/
|
||||
|
||||
static BaseWareHouseService()
|
||||
{
|
||||
|
||||
@@ -3,6 +3,7 @@ using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using JNPF;
|
||||
using JNPF.Common.Contracts;
|
||||
using JNPF.Logging;
|
||||
using Microsoft.Extensions.Logging;
|
||||
@@ -13,19 +14,35 @@ namespace Tnb.WarehouseMgr
|
||||
{
|
||||
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)
|
||||
{
|
||||
Task.Run(async () =>
|
||||
{
|
||||
_elevatorMap = await db.Queryable<WmsElevatorH>().ToDictionaryAsync(x => x.elevator_id, x => x.elevator_code);
|
||||
});
|
||||
}
|
||||
initializationTask = new Lazy<Task>(InitializeAsync);
|
||||
}
|
||||
|
||||
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 =>
|
||||
{
|
||||
|
||||
|
||||
@@ -61,7 +61,7 @@ namespace Tnb.WarehouseMgr
|
||||
IEventPublisher eventPublisher,
|
||||
IUserManager userManger,
|
||||
IElevatorControlService elevatorControlService
|
||||
) : base(repository.AsSugarClient())
|
||||
) //: base(repository.AsSugarClient())
|
||||
{
|
||||
_db = repository.AsSugarClient();
|
||||
_wareHouseService = wareHouseService;
|
||||
@@ -69,6 +69,7 @@ namespace Tnb.WarehouseMgr
|
||||
_eventPublisher = eventPublisher;
|
||||
_userManager = userManger;
|
||||
_elevatorControlService = elevatorControlService;
|
||||
_ = InitializationTask;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -111,7 +112,7 @@ namespace Tnb.WarehouseMgr
|
||||
try
|
||||
{
|
||||
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;
|
||||
(int sysStatus, int runStatus, int floorNo, int doorStatus, int agvStatus) = await _elevatorControlService.GetElevatorStatus(devName, CancellationToken.None);
|
||||
@@ -164,7 +165,7 @@ namespace Tnb.WarehouseMgr
|
||||
.FirstAsync();
|
||||
if (elevator.IsNull())
|
||||
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;
|
||||
(int sysStatus, int runStatus, int floorNo, int doorStatus, int agvStatus) = await _elevatorControlService.GetElevatorStatus(devName, CancellationToken.None);//elevator.elevator_code
|
||||
|
||||
@@ -54,7 +54,7 @@ namespace Tnb.WarehouseMgr
|
||||
|
||||
public WareHouseService(ISqlSugarRepository<WmsInstockH> repository, IDictionaryDataService dictionaryDataService,
|
||||
IBillRullService billRullService, IUserManager userManager, ICacheManager cacheManager, IElevatorControlService elevatorControlService)
|
||||
: base(repository.AsSugarClient())
|
||||
//: base(repository.AsSugarClient())
|
||||
{
|
||||
_db = repository.AsSugarClient();
|
||||
_dictionaryDataService = dictionaryDataService;
|
||||
@@ -62,6 +62,7 @@ namespace Tnb.WarehouseMgr
|
||||
_userManager = userManager;
|
||||
_cacheManager = cacheManager;
|
||||
_elevatorControlService = elevatorControlService;
|
||||
_ = InitializationTask;
|
||||
}
|
||||
|
||||
|
||||
@@ -215,19 +216,18 @@ namespace Tnb.WarehouseMgr
|
||||
/// 生成任务执行
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[HttpPost, Timed(Name = nameof(IWareHouseService.GenTaskExecute))]
|
||||
[HttpPost]
|
||||
public async Task GenTaskExecute()
|
||||
{
|
||||
|
||||
await s_taskExecuteSemaphore.WaitAsync();
|
||||
|
||||
Stopwatch sw = Stopwatch.StartNew();
|
||||
CancellationTokenSource agvCts = new();
|
||||
|
||||
var db = _db.CopyNew();
|
||||
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)
|
||||
.Select((a, b) => new WmsElevatorH
|
||||
@@ -420,6 +420,7 @@ namespace Tnb.WarehouseMgr
|
||||
}
|
||||
finally
|
||||
{
|
||||
s_taskExecuteSemaphore.Release();
|
||||
agvCts.Dispose();
|
||||
}
|
||||
}
|
||||
@@ -436,7 +437,7 @@ namespace Tnb.WarehouseMgr
|
||||
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();
|
||||
|
||||
@@ -510,14 +511,27 @@ namespace Tnb.WarehouseMgr
|
||||
Logger.Information($"开始执行电梯任务,任务ID:{disTask.id}");
|
||||
try
|
||||
{
|
||||
if (!_elevatorMap.TryGetValue(disTask.device_id, out var elevatorCode))
|
||||
if (!s_elevatorMap.TryGetValue(disTask.device_id, out var elevatorCode))
|
||||
{
|
||||
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+")}#梯");
|
||||
|
||||
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 closeDoorRes = await _elevatorControlService.SendOpenCloseCmd(devName, 4); //向电梯发送前门关门指令
|
||||
Logger.Information($"关门结果:{closeDoorRes}");
|
||||
|
||||
@@ -17,7 +17,9 @@ using JNPF.VisualDev;
|
||||
using JNPF.VisualDev.Entitys;
|
||||
using JNPF.VisualDev.Interfaces;
|
||||
using Mapster;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Newtonsoft.Json;
|
||||
using Spire.Doc.Formatting;
|
||||
using SqlSugar;
|
||||
using Tnb.BasicData.Entities;
|
||||
@@ -38,7 +40,7 @@ namespace Tnb.WarehouseMgr
|
||||
[OverideVisualDev(ModuleConsts.MODULE_WMSEMPTYINSTOCK_ID)]
|
||||
[ServiceModule(BizTypeId)]
|
||||
|
||||
public class WmsEmptyInstockService : BaseWareHouseService, IWmsEmptyInstockService
|
||||
public class WmsEmptyInstockService : BaseWareHouseService<WmsEmptyInstockService>, IWmsEmptyInstockService
|
||||
{
|
||||
private const string BizTypeId = "26121986416677";
|
||||
private readonly ISqlSugarClient _db;
|
||||
@@ -64,7 +66,7 @@ namespace Tnb.WarehouseMgr
|
||||
_wareHouseService = wareHouseService;
|
||||
_userManager = userManager;
|
||||
_billRullService = billRullService;
|
||||
|
||||
|
||||
OverideFuncs.CreateAsync = WmsEmptyIn;
|
||||
}
|
||||
private async Task<dynamic> WmsEmptyIn(VisualDevModelDataCrInput input)
|
||||
@@ -189,6 +191,7 @@ namespace Tnb.WarehouseMgr
|
||||
finally
|
||||
{
|
||||
//向队列写入消息
|
||||
Logger.Information("调用预任务生成");
|
||||
await InvokeGenPretaskExcute();
|
||||
}
|
||||
return Task.FromResult(true);
|
||||
|
||||
Reference in New Issue
Block a user