using EgwCoreLib.Lux.Core.RestPayload; using EgwCoreLib.Lux.Data.Services; using EgwMultiEngineManager.Data; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.SignalR; using Newtonsoft.Json; using NLog; using StackExchange.Redis; using System.Diagnostics; using static EgwCoreLib.Lux.Data.Services.ProdService; namespace Lux.API.Controllers { [Route("api/[controller]")] [ApiController] public class ProdController : ControllerBase { #region Public Constructors public ProdController(ProdService prodService) { PService = prodService; } #endregion Public Constructors #region Public Methods /// /// Chiamata GET: test status alive /// GET: api/Prod/alive /// /// id oggetto /// [HttpGet("alive")] public async Task Alive() { Stopwatch sw = new Stopwatch(); sw.Start(); await Task.Delay(1); sw.Stop(); Log.Info($"Alive | {sw.Elapsed.TotalMilliseconds:N3} ms"); return Ok("OK"); } /// /// Chiamata GET: /// - fornisce il job da eseguire dalla coda (SE presente) /// GET: api/Prod/getjob/ABC012345 /// /// [HttpGet("getjob/{id}")] public async Task> GetJob(string id) { var result = await PService.GetJob(id); QuestionDTO deserRes = JsonConvert.DeserializeObject(result); return Ok(deserRes); } /// /// Chiamata GET: /// - fornisce il primo job da eseguire dalla coda (SE presente) /// - viene registrato come "in corso" e spostato dalla coda richiesta /// GET: api/Prod/getnext /// /// [HttpGet("getnext")] public async Task> GetNext() { var result = await PService.GetNext(); //return Ok(result); QuestionDTO deserRes = JsonConvert.DeserializeObject(result); return Ok(deserRes); } [HttpPost("jobcreate/{id}")] public async Task JobCreate(string id, [FromBody] Dictionary args) { bool answ = true; // simulo salvataggio await Task.Delay(50); // salvo! // ritorno return answ; } [HttpPost("jobestimate/{id}")] public async Task JobEstimate(string id, [FromBody] Dictionary args) { bool answ = true; // simulo salvataggio await Task.Delay(50); // salvo! // ritorno return answ; } /// /// Chiamata GET: num richieste in coda (se non specificato è waiting, altrimenti ) /// GET: api/Prod/queue-len/ /// GET: api/Prod/queue-len/waiting /// GET: api/Prod/queue-len/running /// /// id oggetto /// [HttpGet("qlen/{type}")] public async Task QueueLen(QueueType type = QueueType.waiting) { var result = await PService.QueueLen(type); return Ok(result); } /// /// Chiamata GET: dizionario stato richieste /// GET: api/Prod/queue-status/ /// /// id oggetto /// [HttpGet("qstatus")] public async Task QueueStatus() { Stopwatch sw = new Stopwatch(); sw.Start(); Dictionary queueStatus = new Dictionary(); long numWait = await PService.QueueLen(QueueType.waiting); long numRun = await PService.QueueLen(QueueType.running); // simulo status... queueStatus.Add("waiting", numWait); queueStatus.Add("running", numRun); sw.Stop(); Log.Info($"QueueStatus | {sw.Elapsed.TotalMilliseconds:N3} ms"); return Ok(queueStatus); } #endregion Public Methods #region Private Fields private static Logger Log = LogManager.GetCurrentClassLogger(); private ProdService PService; #endregion Private Fields #if false [HttpPost("enqueue")] /// /// Accodamento richiesta di calcolo prod /// /// Tipo richiesta /// UID (riga ordine) /// Contenuto della richiesta come QuestionDTO /// public async Task EnqueueRequest(string reqType, string reqUid, CalcRequestDTO currRequest) { bool done = false; int nId = 1; // salvo su cache x successivo reinvio da currRequest QuestionDTO calcRequest = new QuestionDTO(nId, currRequest.EnvType, currRequest.DictExec); // salvo in cache contenuto della richiesta x UID string currKey = $"{redisOrderReqKey}:{reqUid.Replace("/", ":")}"; done = await _redisService.SetAsync(currKey, calcRequest.sProcessArgs); // accodo la nuova richiesta //RedisKey queueKey = (RedisKey)$"{redisBaseKey}:OrderQueue:{reqType}"; _redisService.QueuePush(queueKey, (RedisValue)reqUid); // dizionario richieste: è il serializzato dell'elenco degli UID da calcolare... var currList = await _redisService.QueueListAllAsync(queueKey); Dictionary calcDict = new Dictionary(); calcDict.Add("ReqLen", $"{calcDict.Count}"); string listReq = JsonConvert.SerializeObject(currList); calcDict.Add("ReqList", listReq); // preparo richiesta di calcolo x UID da inviare QuestionDTO chRequest = new QuestionDTO(nId, currRequest.EnvType, calcDict); // invio sul channel redis della richiesta di processing await _redisService.PublishAsync(chPub, chRequest.sProcessArgs); // ritorno return done; } /// /// Chiamata GET: /// - elenco delle richieste di stima da eseguire /// - vengono registrate come "passate" al calcolo alla data-ora della richiesta /// GET: api/Prod/estimation /// /// [HttpGet("estimation")] public async Task>> EstimationRequestQueue() { Stopwatch sw = new Stopwatch(); sw.Start(); var listReq = new List(); // vado a recuperare da REDIS elenco degli ordini NON ancora associati ad 1/+ prod // opzione 1: restituisco TUTTI ordini NON ancora eseguiti // opzione 2: restituisco dall'inizio solo max(n) non ancora eseguiti? (es primi 5 ordini) // genero elenco degli ordini e per ogni ordine aggiungo il Dict await Task.Delay(100); // opzione 1: per tutti gli ordini ritornato registro data-ora invio e tolgo dalla coda... // opzione 2: aspetto conferma dal sistema che li ha presi in carico e registro data-ora... sw.Stop(); Log.Info($"EstimationRequestQueue | {sw.Elapsed.TotalMilliseconds:N3} ms"); return Ok(listReq); } /// /// Chiamata GET: /// - elenco delle richieste di ottimizzazione/nesting da eseguire /// - vengono registrate come "passate" al calcolo alla data-ora della richiesta /// GET: api/Prod/estimation /// /// [HttpGet("optmization")] public async Task>> OptimitionRequestQueue() { Stopwatch sw = new Stopwatch(); sw.Start(); var listReq = new List(); // vado a recuperare da REDIS elenco degli ordini NON ancora associati ad 1/+ prod // opzione 1: restituisco TUTTI ordini NON ancora eseguiti // opzione 2: restituisco dall'inizio solo max(n) non ancora eseguiti? (es primi 5 ordini) // genero elenco degli ordini e per ogni ordine aggiungo il Dict await Task.Delay(100); // opzione 1: per tutti gli ordini ritornato registro data-ora invio e tolgo dalla coda... // opzione 2: aspetto conferma dal sistema che li ha presi in carico e registro data-ora... sw.Stop(); Log.Info($"EstimationRequestQueue | {sw.Elapsed.TotalMilliseconds:N3} ms"); return Ok(listReq); } #endif } }