using Microsoft.Extensions.Logging; using SushiBarContracts.BindingModels; using SushiBarContracts.BusinessLogicsContracts; using SushiBarContracts.SearchModels; using SushiBarContracts.ViewModels; using SushiBarDataModels.Enums; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace SushiBarBusinessLogic { public class WorkModeling : IWorkProcess { private readonly ILogger _logger; private readonly Random _rnd; private IOrderLogic? _orderLogic; public WorkModeling(ILogger Logger) { _logger = Logger; _rnd = new Random(1000); } public void DoWork(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 {Count} orders", orders.Count); 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("WorkerWorkAsync. Worker {Id} try get order {Order}", Implementer.Id, Order.Id); bool AcquireResult = _orderLogic.TakeOrderInWork(new OrderBindingModel { Id = Order.Id, ImplementerId = Implementer.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 }); } 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("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 }); 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; } } } }