using DinerContracts.BindingModels; using DinerContracts.BusinessLogicsContacts; using DinerContracts.BusinessLogicsContracts; using DinerContracts.SearchModels; using DinerContracts.ViewModels; using DinerDataModels.Enums; using DocumentFormat.OpenXml.Office2010.Excel; using Microsoft.Extensions.Logging; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace DineryBusinessLogic.BusinessLogic { public class WorkModelling : IWorkProcess { private readonly ILogger _logger; private readonly Random _rnd; private IOrderLogic? _orderLogic; public WorkModelling(ILogger logger) { _logger = logger; _rnd = new Random(1000); } public void Work(IImplementerLogic implementerLogic, IOrderLogic orderLogic) { _orderLogic = orderLogic; var implementers = implementerLogic.ReadList(null); if (implementers == null) { _logger.LogWarning("DoWork. Implementers is null"); return; } var orders = _orderLogic.ReadList(new OrderSearchModel { Status = OrderStatus.Принят }); if (orders == null || orders.Count == 0) { _logger.LogWarning("DoWork. Orders is null or empty"); return; } _logger.LogDebug($"DoWork for {orders.Count} orders"); foreach (var implementer in implementers) { Task.Run(() => WorkerWorkAsync(implementer, orders)); } } // Иммитация работы исполнителя private async Task WorkerWorkAsync(ImplementerViewModel implementer, List orders) { if (_orderLogic == null || implementer == null) { return; } await RunOrderInWork(implementer); await Task.Run(() => { foreach (var order in orders) { try { _logger.LogDebug($"DoWork. Worker {implementer.ID} try get order {order.ID}"); // пытаемся назначить заказ на исполнителя _orderLogic.TakeOrderInWork(new OrderBindingModel { ID = order.ID, ImplementerID = implementer.ID }); // делаем работу Thread.Sleep(implementer.WorkExperience + _rnd.Next(100, 1000) * order.Count); _logger.LogDebug($"DoWork. Worker {implementer.ID} finish order {order.ID}"); _orderLogic.FinishOrder(new OrderBindingModel { ID = order.ID, }); } // кто-то мог уже перехватить заказ, игнорируем ошибку 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) { if (_orderLogic == null || implementer == null) { return; } try { var runOrder = await Task.Run(() => _orderLogic.ReadElement(new OrderSearchModel { ImplementerID = implementer.ID, Status = OrderStatus.Выполняется })); if (runOrder == null) { return; } _logger.LogDebug($"DoWork. Worker {implementer.ID} back to order {runOrder.ID}"); // доделываем работу Thread.Sleep(implementer.WorkExperience * _rnd.Next(100, 300) * runOrder.Count); _logger.LogDebug($"DoWork. Worker{implementer.ID} finish order {runOrder.ID}"); _orderLogic.FinishOrder(new OrderBindingModel { ID = runOrder.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; } } } }