From 83e8f6eff2906ef6a2fc58e5ffdf857c0f1d605b Mon Sep 17 00:00:00 2001 From: malimova Date: Thu, 23 May 2024 15:09:31 +0400 Subject: [PATCH] =?UTF-8?q?=D0=BF=D0=BE=D1=87=D0=B8=D0=BD=D0=B8=D0=BB?= =?UTF-8?q?=D0=B0,=20=D1=81=D0=B4=D0=B0=D1=87=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ConfectioneryBusinessLogic/OrderLogic.cs | 240 +++++++++--------- .../WorkModeling.cs | 78 +++--- .../ConfectioneryDatabaseModelSnapshot.cs | 4 +- 3 files changed, 167 insertions(+), 155 deletions(-) diff --git a/Confectionery/ConfectioneryBusinessLogic/OrderLogic.cs b/Confectionery/ConfectioneryBusinessLogic/OrderLogic.cs index c6e9e30..65049ef 100644 --- a/Confectionery/ConfectioneryBusinessLogic/OrderLogic.cs +++ b/Confectionery/ConfectioneryBusinessLogic/OrderLogic.cs @@ -13,15 +13,128 @@ using System.Threading.Tasks; namespace ConfectioneryBusinessLogic { - public class OrderLogic : IOrderLogic - { - private readonly ILogger _logger; - private readonly IOrderStorage _orderStorage; - public OrderLogic(ILogger logger, IOrderStorage orderStorage) - { - _logger = logger; - _orderStorage = orderStorage; - } + public class OrderLogic : IOrderLogic + { + private readonly ILogger _logger; + private readonly IOrderStorage _orderStorage; + static readonly object _locker = new object(); + public OrderLogic(ILogger logger, IOrderStorage orderStorage) + { + _logger = logger; + _orderStorage = orderStorage; + } + public List? ReadList(OrderSearchModel? model) + { + _logger.LogInformation("ReadList. ClientId:{ClientId}.Status:{Status}.ImplementerId:{ImplementerId}.DateFrom:{DateFrom}.DateTo:{DateTo}OrderId:{Id}", + model?.ClientId, model?.Status, model?.ImplementerId, model?.DateFrom, model?.DateTo, model?.Id); + var list = model == null ? _orderStorage.GetFullList() : _orderStorage.GetFilteredList(model); + if (list == null) + { + _logger.LogWarning("ReadList return null list"); + return null; + } + _logger.LogInformation("ReadList. Count:{Count}", list.Count); + return list; + } + public bool CreateOrder(OrderBindingModel model) + { + CheckModel(model); + if (model.Status != OrderStatus.Неизвестен) + return false; + model.Status = OrderStatus.Принят; + if (_orderStorage.Insert(model) == null) + { + _logger.LogWarning("Insert operation failed"); + return false; + } + return true; + } + + public bool TakeOrderInWork(OrderBindingModel model) + { + lock (_locker) + { + return ChangeStatus(model, OrderStatus.Выполняется); + } + } + + public bool FinishOrder(OrderBindingModel model) + { + return ChangeStatus(model, OrderStatus.Готов); + } + + public bool DeliveryOrder(OrderBindingModel model) + { + return ChangeStatus(model, OrderStatus.Выдан); + } + + private void CheckModel(OrderBindingModel model, bool withParams = true) + { + if (model == null) + { + throw new ArgumentNullException(nameof(model)); + } + if (!withParams) + { + return; + } + if (model.Count <= 0) + { + throw new ArgumentException("Колличество суши в заказе не может быть меньше 1", nameof(model.Count)); + } + if (model.Sum <= 0) + { + throw new ArgumentException("Стоимость заказа на может быть меньше 1", nameof(model.Sum)); + } + if (model.DateImplement.HasValue && model.DateImplement < model.DateCreate) + { + throw new ArithmeticException($"Дата выдачи заказа {model.DateImplement} не может быть раньше даты его создания {model.DateCreate}"); + } + _logger.LogInformation("Sushi. SushiId:{SushiId}.Count:{Count}.Sum:{Sum}Id:{Id}", + model.PastryId, model.Count, model.Sum, model.Id); + } + + private bool ChangeStatus(OrderBindingModel model, OrderStatus requiredStatus) + { + CheckModel(model, false); + var element = _orderStorage.GetElement(new OrderSearchModel() + { + Id = model.Id + }); + if (element == null) + { + throw new InvalidOperationException(nameof(element)); + } + model.DateCreate = element.DateCreate; + model.PastryId = element.PastryId; + model.DateImplement = element.DateImplement; + model.ClientId = element.ClientId; + if (!model.ImplementerId.HasValue) + { + model.ImplementerId = element.ImplementerId; + } + model.Status = element.Status; + model.Count = element.Count; + model.Sum = element.Sum; + if (requiredStatus - model.Status == 1) + { + model.Status = requiredStatus; + if (model.Status == OrderStatus.Готов) + { + model.DateImplement = DateTime.Now; + } + if (_orderStorage.Update(model) == null) + { + _logger.LogWarning("Update operation failed"); + return false; + } + return true; + } + _logger.LogWarning("Changing status operation faled: Current-{Status}:required-{requiredStatus}.", model.Status, requiredStatus); + throw new InvalidOperationException($"Невозможно приствоить статус {requiredStatus} заказу с текущим статусом {model.Status}"); + + } + public OrderViewModel? ReadElement(OrderSearchModel model) { if (model == null) @@ -39,112 +152,5 @@ namespace ConfectioneryBusinessLogic _logger.LogInformation("ReadElement find. Id:{Id}", element.Id); return element; } - public List? ReadList(OrderSearchModel? model) - { - _logger.LogInformation("ReadList. ClientId:{ClientId}.Status:{Status}.ImplementerId:{ImplementerId}.DateFrom:{DateFrom}.DateTo:{DateTo}OrderId:{Id}", - model?.ClientId, model?.Status, model?.ImplementerId, model?.DateFrom, model?.DateTo, model?.Id); - var list = model == null ? _orderStorage.GetFullList() : _orderStorage.GetFilteredList(model); - if (list == null) - { - _logger.LogWarning("ReadList return null list"); - return null; - } - _logger.LogInformation("ReadList. Count:{Count}", list.Count); - return list; - } - public bool CreateOrder(OrderBindingModel model) - { - CheckModel(model); - if (model.Status != OrderStatus.Неизвестен) - return false; - model.Status = OrderStatus.Принят; - if (_orderStorage.Insert(model) == null) - { - _logger.LogWarning("Insert operation failed"); - return false; - } - return true; - } - - public bool TakeOrderInWork(OrderBindingModel model) - { - return ChangeStatus(model, OrderStatus.Выполняется); - } - - public bool FinishOrder(OrderBindingModel model) - { - return ChangeStatus(model, OrderStatus.Готов); - } - - public bool DeliveryOrder(OrderBindingModel model) - { - return ChangeStatus(model, OrderStatus.Выдан); - } - - private void CheckModel(OrderBindingModel model, bool withParams = true) - { - if (model == null) - { - throw new ArgumentNullException(nameof(model)); - } - if (!withParams) - { - return; - } - if (model.Count <= 0) - { - throw new ArgumentException("Колличество кондитерских изделий в заказе не может быть меньше 1", nameof(model.Count)); - } - if (model.Sum <= 0) - { - throw new ArgumentException("Стоимость заказа на может быть меньше 1", nameof(model.Sum)); - } - if (model.DateImplement.HasValue && model.DateImplement < model.DateCreate) - { - throw new ArithmeticException($"Дата выдачи заказа {model.DateImplement} не может быть раньше даты его создания {model.DateCreate}"); - } - _logger.LogInformation("Pastry. PastryId:{PastryId}.Count:{Count}.Sum:{Sum}Id:{Id}", - model.PastryId, model.Count, model.Sum, model.Id); - } - - private bool ChangeStatus(OrderBindingModel model, OrderStatus requiredStatus) - { - CheckModel(model, false); - var element = _orderStorage.GetElement(new OrderSearchModel() - { - Id = model.Id - }); - if (element == null) - { - throw new ArgumentNullException(nameof(element)); - } - model.DateCreate = element.DateCreate; - model.PastryId = element.PastryId; - model.DateImplement = element.DateImplement; - model.ClientId = element.ClientId; - if (!model.ImplementerId.HasValue) - { - model.ImplementerId = element.ImplementerId; - } - model.Status = element.Status; - model.Count = element.Count; - model.Sum = element.Sum; - if (requiredStatus - model.Status == 1) - { - model.Status = requiredStatus; - if (model.Status == OrderStatus.Готов) - { - model.DateImplement = DateTime.Now; - } - if (_orderStorage.Update(model) == null) - { - _logger.LogWarning("Update operation failed"); - return false; - } - return true; - } - _logger.LogWarning("Changing status operation faled: Current-{Status}:required-{requiredStatus}.", model.Status, requiredStatus); - throw new ArgumentException($"Невозможно присвоить статус {requiredStatus} заказу с текущим статусом {model.Status}"); - } - } + } } diff --git a/Confectionery/ConfectioneryBusinessLogic/WorkModeling.cs b/Confectionery/ConfectioneryBusinessLogic/WorkModeling.cs index 7091f98..083ddb7 100644 --- a/Confectionery/ConfectioneryBusinessLogic/WorkModeling.cs +++ b/Confectionery/ConfectioneryBusinessLogic/WorkModeling.cs @@ -20,9 +20,9 @@ namespace ConfectioneryBusinessLogic.BusinessLogics private IOrderLogic? _orderLogic; - public WorkModeling(ILogger logger) + public WorkModeling(ILogger Logger) { - _logger = logger; + _logger = Logger; _rnd = new Random(1000); } @@ -48,87 +48,93 @@ namespace ConfectioneryBusinessLogic.BusinessLogics } } - private async Task WorkerWorkAsync(ImplementerViewModel implementer, List orders) + private async Task WorkerWorkAsync(ImplementerViewModel Implementer, List Orders) { - if (_orderLogic == null || implementer == null) + if (_orderLogic == null || Implementer == null) { return; } - await RunOrderInWork(implementer); + + await RunOrderInWork(Implementer); await Task.Run(() => { - foreach (var order in orders) + foreach (var Order in Orders) { try { - _logger.LogDebug("DoWork. Worker {Id} try get order {Order}", implementer.Id, order.Id); - // пытаемся назначить заказ на исполнителя - _orderLogic.TakeOrderInWork(new OrderBindingModel + _logger.LogDebug("WorkerWorkAsync. Worker {Id} try get order {Order}", Implementer.Id, Order.Id); + bool AcquireResult = _orderLogic.TakeOrderInWork(new OrderBindingModel { - Id = order.Id, - ImplementerId = implementer.Id + Id = Order.Id, + ImplementerId = Implementer.Id }); - // делаем работу - Thread.Sleep(implementer.WorkExperience * _rnd.Next(100, 1000) * order.Count); - _logger.LogDebug("DoWork. Worker {Id} finish order {Order}", implementer.Id, order.Id); + + if (!AcquireResult) + { + _logger.LogDebug("WorkerWorkAsync. Worker {Id} tried to get order {Order} but it's already acquired by other worker", Implementer.Id, Order.Id); + continue; + } + + Thread.Sleep(Implementer.WorkExperience * _rnd.Next(100, 1000) * Order.Count); + + _logger.LogDebug("WorkerWorkAsync. Worker {Id} finish order {Order}", Implementer.Id, Order.Id); _orderLogic.FinishOrder(new OrderBindingModel { - Id = order.Id + Id = Order.Id }); + + Thread.Sleep(Implementer.Qualification * _rnd.Next(10, 100)); } - // кто-то мог уже перехватить заказ, игнорируем ошибку + catch (InvalidOperationException ex) { _logger.LogWarning(ex, "Error try get work"); } - // заканчиваем выполнение имитации в случае иной ошибки + catch (Exception ex) { _logger.LogError(ex, "Error while do work"); - throw; } - // отдыхаем - Thread.Sleep(implementer.Qualification * _rnd.Next(10, 100)); } }); } - private async Task RunOrderInWork(ImplementerViewModel implementer) + private async Task RunOrderInWork(ImplementerViewModel Implementer) { - if (_orderLogic == null || implementer == null) - { + if (_orderLogic == null || Implementer == null) return; - } + try { - var runOrder = await Task.Run(() => _orderLogic.ReadElement(new OrderSearchModel + var RunOrder = await Task.Run(() => _orderLogic.ReadElement(new OrderSearchModel { - ImplementerId = implementer.Id, + ImplementerId = Implementer.Id, Status = OrderStatus.Выполняется })); - if (runOrder == null) + + if (RunOrder == null) { return; } - _logger.LogDebug("DoWork. Worker {Id} back to order {Order}", implementer.Id, runOrder.Id); - // доделываем работу - Thread.Sleep(implementer.WorkExperience * _rnd.Next(100, 300) * runOrder.Count); - _logger.LogDebug("DoWork. Worker {Id} finish order {Order}", implementer.Id, runOrder.Id); + _logger.LogDebug("RunOrderInWork. Worker {Id} back to order {Order}", Implementer.Id, RunOrder.Id); + Thread.Sleep(Implementer.WorkExperience * _rnd.Next(100, 300) * RunOrder.Count); + + _logger.LogDebug("RunOrderInWork. Worker {Id} finish order {Order}", Implementer.Id, RunOrder.Id); _orderLogic.FinishOrder(new OrderBindingModel { - Id = runOrder.Id + Id = RunOrder.Id }); - // отдыхаем - Thread.Sleep(implementer.Qualification * _rnd.Next(10, 100)); + + Thread.Sleep(Implementer.Qualification * _rnd.Next(10, 100)); } - // заказа может не быть, просто игнорируем ошибку + catch (InvalidOperationException ex) { _logger.LogWarning(ex, "Error try get work"); } - // а может возникнуть иная ошибка, тогда просто заканчиваем выполнение имитации + catch (Exception ex) { _logger.LogError(ex, "Error while do work"); diff --git a/Confectionery/ConfectioneryDatabaseImplement/Migrations/ConfectioneryDatabaseModelSnapshot.cs b/Confectionery/ConfectioneryDatabaseImplement/Migrations/ConfectioneryDatabaseModelSnapshot.cs index 552abb4..605726a 100644 --- a/Confectionery/ConfectioneryDatabaseImplement/Migrations/ConfectioneryDatabaseModelSnapshot.cs +++ b/Confectionery/ConfectioneryDatabaseImplement/Migrations/ConfectioneryDatabaseModelSnapshot.cs @@ -203,9 +203,9 @@ namespace ConfectioneryDatabaseImplement.Migrations b.Navigation("Client"); - b.Navigation("Implementer"); + b.Navigation("Implementer"); - b.Navigation("Pastry"); + b.Navigation("Pastry"); }); modelBuilder.Entity("ConfectioneryDatabaseImplement.Models.PastryComponent", b =>