与任务执行,新增信号量锁,解决并发环境下数据的一致性问题
This commit is contained in:
@@ -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()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -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 =>
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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}");
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
Reference in New Issue
Block a user