This commit is contained in:
2026-07-27 14:29:46 +08:00
110 changed files with 13942 additions and 2044 deletions
+44 -5
View File
@@ -166,10 +166,27 @@ public sealed class WmsTransportTaskService
public async Task<WmsTransportTask> DispatchAsync(Guid taskId, string actor)
{
var task = await FindTaskAsync(taskId);
if (task.Status != WmsTransportTaskStatuses.Reserved)
throw new InvalidOperationException("只有 Reserved 状态的任务可以下发");
// 原子抢占:仅一条 Reserved 且未在下发中的任务能进入 Dispatching,避免双发
var now = DateTimeOffset.UtcNow;
var claimed = await _db.WmsTransportTasks
.Where(x => x.Id == taskId
&& x.Status == WmsTransportTaskStatuses.Reserved
&& x.DispatchStatus != "Dispatching"
&& x.DispatchStatus != "Dispatched")
.ExecuteUpdateAsync(s => s
.SetProperty(x => x.DispatchStatus, "Dispatching")
.SetProperty(x => x.UpdatedAt, now)
.SetProperty(x => x.UpdatedBy, actor));
if (claimed == 0)
{
var existing = await FindTaskAsync(taskId);
if (existing.Status != WmsTransportTaskStatuses.Reserved)
throw new InvalidOperationException("只有 Reserved 状态的任务可以下发");
throw new InvalidOperationException("任务正在下发中,请勿重复操作");
}
var task = await FindTaskAsync(taskId);
var source = await _db.Storages.AsNoTracking().FirstAsync(x => x.Id == task.SourceStorageId);
var target = await _db.Storages.AsNoTracking().FirstAsync(x => x.Id == task.TargetStorageId);
var container = await _db.Containers.AsNoTracking().FirstAsync(x => x.Id == task.ContainerId);
@@ -195,14 +212,36 @@ public sealed class WmsTransportTaskService
return task;
}
private async Task ExpireStaleReservationsAsync()
{
var now = DateTimeOffset.UtcNow;
var rows = await _db.WmsTransportReservations
.Where(x => x.Status == WmsReservationStatuses.Active
&& x.ExpiresAt != null
&& x.ExpiresAt < now)
.ToListAsync();
if (rows.Count == 0) return;
foreach (var row in rows)
row.Status = WmsReservationStatuses.Expired;
await _db.SaveChangesAsync();
}
private async Task EnsureNoActiveReservationAsync(Guid containerId, Guid targetStorageId)
{
await ExpireStaleReservationsAsync();
var now = DateTimeOffset.UtcNow;
if (await _db.WmsTransportReservations.AnyAsync(x =>
x.Status == WmsReservationStatuses.Active && x.ContainerId == containerId))
x.Status == WmsReservationStatuses.Active
&& (x.ExpiresAt == null || x.ExpiresAt > now)
&& x.ContainerId == containerId))
throw new InvalidOperationException("容器已被其他任务预占");
if (await _db.WmsTransportReservations.AnyAsync(x =>
x.Status == WmsReservationStatuses.Active && x.TargetStorageId == targetStorageId))
x.Status == WmsReservationStatuses.Active
&& (x.ExpiresAt == null || x.ExpiresAt > now)
&& x.TargetStorageId == targetStorageId))
throw new InvalidOperationException("目标库位已被其他任务预占");
}