using EgwCoreLib.Lux.Core.RestPayload;
using EgwCoreLib.Lux.Data.Services;
using EgwMultiEngineManager.Data;
using Microsoft.AspNetCore.Mvc;
using Newtonsoft.Json;
using NLog;
using StackExchange.Redis;
using System.Diagnostics;
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);
return Ok(result);
}
///
/// 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);
#if false
Stopwatch sw = new Stopwatch();
sw.Start();
string result = "";
// prendo dalla coda primo job (rimuovendolo...)
var rawReq = await _redisService.QueuePopAsync(queueKey);
if (rawReq.HasValue)
{
string reqUid = $"{rawReq}";
// metto UID in coda running
_redisService.QueuePush(queueKey, (RedisValue)reqUid);
// FixMe ToDo !!!: salvataggio data-ora per indicare avvio calcolo...
// recupero richiesta serializzata
string currKey = $"{redisOrderReqKey}:{reqUid.Replace("/", ":")}";
var rawRes = await _redisService.GetAsync(currKey);
if (!string.IsNullOrEmpty(rawRes))
{
result = rawRes;
}
}
sw.Stop();
Log.Info($"GetNext | {sw.Elapsed.TotalMilliseconds:N3} ms");
return Ok(result);
#endif
}
///
/// Chiamata GET: num richieste in coda (tot)
/// GET: api/Prod/alive
///
/// id oggetto
///
[HttpGet("queue")]
public async Task QueueLen()
{
var result = await PService.QueueLen();
return Ok(result);
#if false
Stopwatch sw = new Stopwatch();
sw.Start();
long numWaiting = await _redisService.QueueCountAsync(queueKey);
sw.Stop();
Log.Info($"QueueLen | {sw.Elapsed.TotalMilliseconds:N3} ms");
return Ok(numWaiting);
#endif
}
#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: dizionario stato richieste
/// GET: api/Prod/alive
///
/// id oggetto
///
[HttpGet("queue-status")]
public async Task QueueStatus()
{
Stopwatch sw = new Stopwatch();
sw.Start();
List? listEstim = new List();
List? listOptim = new List();
Dictionary queueStatus = new Dictionary();
// cerco in redis...
RedisValue rawEstim = await _redisDb.StringGetAsync($"{redisBaseKey}:EstimReq");
if (rawEstim.HasValue)
{
listEstim = JsonConvert.DeserializeObject>($"{rawEstim}");
}
RedisValue rawOptim = await _redisDb.StringGetAsync($"{redisBaseKey}:OptimReq");
if (rawOptim.HasValue)
{
listOptim = JsonConvert.DeserializeObject>($"{rawOptim}");
}
// simulo status...
queueStatus.Add("estimation", listEstim?.Count ?? 0);
queueStatus.Add("optimization", listOptim?.Count ?? 0);
sw.Stop();
Log.Info($"QueueStatus | {sw.Elapsed.TotalMilliseconds:N3} ms");
return Ok(queueStatus);
}
///
/// 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
}
}