using Microsoft.AspNetCore.Mvc; using NLog; using System.Diagnostics; using WebDoorCreator.Core; using WebDoorCreator.Data.DTO; using WebDoorCreator.Data.Services; namespace WebDoorCreator.API.Controllers { [Route("api/[controller]")] [ApiController] public class QueueController : ControllerBase { #region Public Constructors public QueueController(IConfiguration configuration, QueueDataService DataService, WebDoorCreatorService _WDService) { _configuration = configuration; logTimingEnable = configuration.GetValue("RuntimeOpt:LogTimingEnable"); QDataServ = DataService; WDService = _WDService; // aggiungo.. string statName = "QueueController"; bool doWrite = QDataServ.StatUpsert(statName, new TimeSpan(), 5).Result; // se campione "pieno"... if (doWrite) { // recupero e resetto ExecStats statRec = QDataServ.StatReset(statName).Result; Log.Trace($"Avviato QueueController x {statRec.NumCall}"); } } #endregion Public Constructors #region Public Methods /// /// Lunghezza coda in fase di processing /// /// [HttpGet("ActLenght")] public async Task> ActLenght() { Dictionary answ = new Dictionary(); var actPend = await QDataServ.NumRequestPending(); answ.Add("pending", actPend); var actProc = await QDataServ.NumRequestProcessing(); answ.Add("processing", actProc); var actErr = await QDataServ.NumRequestErrors(); answ.Add("errors", actErr); var actDone = await QDataServ.NumRequestDone(); answ.Add("done", actDone); return answ; } /// /// Cleanup dati delle code di calcolo /// /// Chiave x auth di reset /// [HttpPost("DCCacheCleanup")] public async Task DCCacheCleanup(string passPhrase) { string answ = "NA"; bool fatto = false; if (passPhrase == "bbbBirdIsTheWord") { fatto = await QDataServ.DoorCalcCacheCleanup(); } answ = fatto ? "OK" : "NO"; return answ; } /// /// Reset delle code di chiamata x ripetere simulazione /// /// Chiave x auth di reset /// [HttpPost("ResetQueue")] public async Task ResetQueue(string passPhrase) { string answ = "NA"; bool fatto = false; if (passPhrase == "bbbBirdIsTheWord") { fatto = await QDataServ.ResetQueue(); } answ = fatto ? "OK" : "NO"; return answ; } /// /// Reset della coda di processing x evitare condizioni di "stuck in calc" /// /// [HttpPost("ResetQueueProcessing")] public async Task ResetQueueProcessing() { string answ = "NA"; // fixme todo /* -------------- * da riscrivere * - server record x cancellazione logica delle porte OK * - il record (boolean, toDelete...) indica azione richiesta OK * - si prendono TUTTE le porte da DB con toDelete == true OK * - si eliminano su REDIS dalle 4 code (req, processing, error, done) OK * - check delle code processing, SE ci sono record rimasti li cerco sul DB * - se NON ci sono sul db --> li elimino da processing * - effettivo delete sul db di toDelete * * - proseguo come ora (sposto tra code processing --> request) */ var doors2Del = await WDService.DoorGet2Del(); if (doors2Del != null) { foreach (var item in doors2Del) { await WDService.RedisBulkDelByDoorId(item.DoorId); await QDataServ.RedisBulkDelHashByKey(item.DoorId); await WDService.DoorDelete(item); } } bool fatto = await QDataServ.ResetQueueProcessing(); answ = fatto ? "OK" : "NO"; return answ; } /// /// Invio elenco risultati elaborazioni (modalità boolean di esecuzione corretta) /// /// Risultati elaborazioni in formato CalcResultDTO /// [HttpPost("SaveProcResult")] public async Task SaveProcResult(List calcResults) { string answ = "NA"; bool fatto = await QDataServ.SaveProcessingResult(calcResults); answ = fatto ? "OK" : "NO"; Log.Debug("Eseguito SaveProcResult"); return answ; } /// /// Elenco richieste raggruppate x stato /// /// [HttpGet("StatusList")] public async Task>> StatusList() { Stopwatch sw = new Stopwatch(); if (logTimingEnable) { sw.Start(); } Dictionary> answ = new Dictionary>(); var actPend = await QDataServ.RequestPending(); answ.Add("pending", actPend); var actProc = await QDataServ.RequestProcessing(); answ.Add("processing", actProc); var actErr = await QDataServ.RequestErr(); answ.Add("errors", actErr); var actDone = await QDataServ.RequestDone(); answ.Add("done", actDone); if (logTimingEnable) { sw.Stop(); // aggiungo.. string statName = "StatusList"; bool doWrite = await QDataServ.StatUpsert(statName, sw.Elapsed, 5); // se campione "pieno"... if (doWrite) { // recupero e resetto ExecStats statRec = await QDataServ.StatReset(statName); Log.Info($"Eseguito {statName} x {statRec.NumCall} | {statRec.AvgTime.TotalMilliseconds:N3}ms"); } } return answ; } /// /// Chiede un numero massimo di items dalla coda NB: /// - verranno tolti dalla coda FIFO richieste /// - verranno messi nella coda FIFO processing /// /// [HttpGet("TakeNextItems")] public async Task> TakeProcessingItems(int numItems = 10) { var actQueue = await QDataServ.TakeProcessingItems(numItems); Log.Debug($"Eseguito TakeProcessingItems per {numItems} items"); return actQueue; } #endregion Public Methods #region Private Fields private static Logger Log = LogManager.GetCurrentClassLogger(); private IConfiguration _configuration = null!; private bool logTimingEnable = false; #endregion Private Fields #region Private Properties private QueueDataService QDataServ { get; set; } = null!; private WebDoorCreatorService WDService { get; set; } = null!; #endregion Private Properties } }