using AyCode.Core.Extensions; using AyCode.Utils.Extensions; using Mango.Nop.Services; using Microsoft.AspNetCore.SignalR; using Nop.Core.Domain.Customers; using Nop.Data; using Nop.Plugin.Misc.AuctionPlugin.Domains.Dtos; using Nop.Plugin.Misc.AuctionPlugin.Domains.Entities; using Nop.Plugin.Misc.AuctionPlugin.Domains.Enums; using Nop.Plugin.Misc.AuctionPlugin.Hubs; using Nop.Plugin.Misc.AuctionPlugin.Hubs.Messages; using Nop.Services.Logging; namespace Nop.Plugin.Misc.AuctionPlugin.Services; public class AuctionBackgroundService : MgBackgroundServiceBase, IBackgroundService { private const int WARNING_STATUS_INTERVAL_SECOND = 15; private const string BACKGROUND_TASK_AUCTION_USER_EMAIL = "builtin@background_task_auction.com"; private readonly IHubContext _auctionHubContext; private readonly ILockService _lockService; private readonly AuctionService _auctionService; private readonly Customer _auctionSystemCustomer; public AuctionBackgroundService(ILogger logger, IServiceProvider service, IHubContext auctionHubContext, AuctionService auctionService, ILockService lockService, IRepository customerService) : base(logger, service, WARNING_STATUS_INTERVAL_SECOND * 1000) { //ExecuteIntervalMs = WARNING_STATUS_INTERVAL_SECOND * 1000; _lockService = lockService; _auctionService = auctionService; _auctionHubContext = auctionHubContext; _auctionSystemCustomer = customerService.Table.FirstOrDefault(x => x.Email == BACKGROUND_TASK_AUCTION_USER_EMAIL); if (_auctionSystemCustomer == null) Logger.Error($"AuctionBackgroundService.AuctionBackgroundService(); _auctionSystemCustomer == null; email: {BACKGROUND_TASK_AUCTION_USER_EMAIL}", null, null); } protected override async Task OnExecuteAsync(CancellationToken stoppingToken) { if (_auctionSystemCustomer == null) return; await Logger.InformationAsync($"AuctionBackgroundService.OnExecuteAsync(); Before lock; ", null, _auctionSystemCustomer); using (await _lockService.SemaphoreSlim.UseWaitAsync(stoppingToken)) { if (stoppingToken.IsCancellationRequested) return; await Logger.InformationAsync($"AuctionBackgroundService.OnExecuteAsync(); Enter lock;", null, _auctionSystemCustomer); var currentAutomaticAuctions = await _auctionService.GetAllCurrentAutoOpenAndClosedAuctionsAsync(); if (currentAutomaticAuctions.Count > 0) { await Logger.InformationAsync($"AuctionBackgroundService.OnExecuteAsync(); currentAutomaticAuctions.Count > 0; count: {currentAutomaticAuctions.Count}; names: {string.Join("; ", currentAutomaticAuctions.Select(x => x.AuctionName))}", null, _auctionSystemCustomer); var statusChangedMessageWrapper = new MessageWrapper { MessageType = nameof(ProductToAuctionStatusNotification), SenderId = _auctionSystemCustomer.Id, //TODO: -1; - J. ResponseType = ResponseType.ToAllClients }; foreach (var automaticAuction in currentAutomaticAuctions) { await CheckAndUpdateProductToAuctionsStatusAsync(automaticAuction, statusChangedMessageWrapper); await OpenOrCloseAutomaticAuctionsAsync(automaticAuction, statusChangedMessageWrapper); } } //await _auctionHubContext.Clients.All.SendAsync("OnDateTimeReceive", DateTime.Now.ToString("G")); //TODO: ez csak a teszt időszakig van itt!!! - J. await Logger.InformationAsync($"AuctionBackgroundService.OnExecuteAsync(); Exit lock;", null, _auctionSystemCustomer); } } private async Task CheckAndUpdateProductToAuctionsStatusAsync(Auction automaticAuction, MessageWrapper statusChangedMessageWrapper) { try { if (automaticAuction.Closed || automaticAuction.EndDateUtc > DateTime.UtcNow.AddSeconds(2 * WARNING_STATUS_INTERVAL_SECOND)) return; var activeProductToAuctions = await _auctionService.GetProductToAuctionsByAuctionIdAsync(automaticAuction.Id, true); if (activeProductToAuctions.Count == 0) return; var auctionDto = new AuctionDto(automaticAuction); var changedProductToAuctions = new List(activeProductToAuctions.Count); foreach (var activeProductToAuction in activeProductToAuctions) { var newPtaStatus = activeProductToAuction.AuctionStatus switch { AuctionStatus.Active => AuctionStatus.FirstWarning, AuctionStatus.FirstWarning => AuctionStatus.SecondWarning, AuctionStatus.SecondWarning => AuctionStatus.Sold, _ => AuctionStatus.None }; if (newPtaStatus == AuctionStatus.None) continue; var responseType = await _auctionService.UpdateProductToAuctionStatusIfValidAsync(newPtaStatus, automaticAuction, activeProductToAuction, _auctionSystemCustomer, false); if (responseType == ResponseType.None) continue; changedProductToAuctions.Add(activeProductToAuction); auctionDto.ProductToAuctionDtos.Add(new ProductToAuctionDto(activeProductToAuction)); } if (changedProductToAuctions.Count == 0) return; await _auctionService.UpdateProductToAuctionAsync(changedProductToAuctions); statusChangedMessageWrapper.Data = new ProductToAuctionStatusNotification(auctionDto, 0, "EMPTY").ToJson(); await _auctionHubContext.Clients.All.SendAsync("send", statusChangedMessageWrapper.ToJson()); } catch (Exception ex) { await Logger.ErrorAsync($"AuctionBackgroundService.CheckAndUpdateProductToAuctionsStatusAsync(); auctionId: {automaticAuction.Id}; auctionName: {automaticAuction.AuctionName}", ex, _auctionSystemCustomer); } } private async Task OpenOrCloseAutomaticAuctionsAsync(Auction automaticAuction, MessageWrapper statusChangedMessageWrapper) { try { if (!automaticAuction.Closed) { var allItemsFinished = (await _auctionService.GetProductToAuctionsByAuctionIdAsync(automaticAuction.Id, false)).All(x => x.AuctionStatus is AuctionStatus.Sold or AuctionStatus.NotSold); if (!allItemsFinished) return; automaticAuction.Closed = true; await _auctionService.UpdateAuctionAsync(automaticAuction); //TODO: send message... - J. return; } var productToAuctions = (await _auctionService.GetProductToAuctionsByAuctionIdAsync(automaticAuction.Id, false)).Where(x => x.AuctionStatus == AuctionStatus.None).ToList(); if (productToAuctions.Count == 0) return; automaticAuction.Closed = false; var auctionDto = new AuctionDto(automaticAuction); foreach (var productToAuction in productToAuctions) { var responseType = await _auctionService.UpdateProductToAuctionStatusIfValidAsync(AuctionStatus.Active, automaticAuction, productToAuction, _auctionSystemCustomer, false); if (responseType == ResponseType.None) continue; auctionDto.ProductToAuctionDtos.Add(new ProductToAuctionDto(productToAuction)); } await _auctionService.UpdateAuctionAsync(automaticAuction); await _auctionService.UpdateProductToAuctionAsync(productToAuctions); statusChangedMessageWrapper.Data = new ProductToAuctionStatusNotification(auctionDto, 0, $"Az aukciót megnyitottuk: {automaticAuction.AuctionName}").ToJson(); statusChangedMessageWrapper.HideToaster = true; await _auctionHubContext.Clients.All.SendAsync("send", statusChangedMessageWrapper.ToJson()); } catch (Exception ex) { await Logger.ErrorAsync($"AuctionBackgroundService.OpenOrCloseAutomaticAuctionsAsync(); auctionId: {automaticAuction.Id}; name: {automaticAuction.AuctionName}", ex, _auctionSystemCustomer); } } }