Files
lux/Lux.API/Controllers/WindowController.cs
T

274 lines
9.2 KiB
C#

using EgwMultiEngineManager;
using Lux.Data;
using Lux.Data.Services;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Newtonsoft.Json;
using StackExchange.Redis;
using System.Diagnostics;
using System.Runtime;
namespace Lux.API.Controllers
{
[Route("api/[controller]")]
[ApiController]
public class WindowController : ControllerBase
{
#region Public Constructors
public WindowController(IConfiguration config, ILogger<WindowController> logger, ImageCacheService imgServ, ExecProcessManager? EgwProcManager = null)
{
_logger = logger;
_config = config;
// setup compoenti REDIS
redisConn = ConnectionMultiplexer.Connect(_config.GetConnectionString("Redis") ?? "localhost");
redisDb = redisConn.GetDatabase();
// json serializer... FIX errore loop circolare https://www.ryadel.com/en/jsonserializationexception-self-referencing-loop-detected-error-fix-entity-framework-asp-net-core/
JSSettings = new JsonSerializerSettings()
{
ReferenceLoopHandling = ReferenceLoopHandling.Ignore
};
// init classe sottoscrizione PubSub CHannel messages REDIS
messageDisp.Subscribe(ChannelName("", true), (channel, message) =>
{
SaveCalcData(channel, message);
});
// verifico se usare engine
enableEgwEng = _config.GetValue<bool>("ServerConf:EgwEngineEnab");
#if false
if (enableEgwEng && EgwProcManager != null)
{
ProcessMan = EgwProcManager;
ProcessMan.m_AnswerReceived += ProcessMan_m_AnswerReceived;
}
#endif
ImgService = imgServ;
}
/// <summary>
/// Salva risultato calcolo da broadcast channel REDIS
/// </summary>
/// <param name="channel"></param>
/// <param name="message"></param>
private void SaveCalcData(RedisChannel channel, RedisValue message)
{
string rawData = $"{message}";
if (!string.IsNullOrEmpty(rawData) && rawData.Length > 2)
{
// provo a deserializzare
try
{
var retData = JsonConvert.DeserializeObject<ProcessArgsResult>(rawData);
if (retData != null)
{
// verifico nId di risposta x salvare correttamente
ProcessMan_m_AnswerReceived(retData);
}
}
catch (Exception exc)
{
_logger.LogError($"Errore in fase decodifica messaggio da REDIS Channel{Environment.NewLine}{exc}");
}
}
}
private void sendMessage(string notifyChannel, string message)
{
RedisChannel pubNotifyChannel = new RedisChannel(notifyChannel, RedisChannel.PatternMode.Literal);
messageDisp.Publish(pubNotifyChannel, message);
}
/// <summary>
/// Nome del channel sottoscritto per ritorno calcoli
/// </summary>
/// <param name="servId"></param>
/// <returns></returns>
private string ChannelName(string servId, bool isOut)
{
return isOut ? $"EgwEngineOutput" : $"EgwEngineInput";
// se implementassimo multi-elaborazione calcoli ogni esecutore ha un suo channel
//return $"EgwEngineOutput_{servId}";
}
/// <summary>
/// Oggetto subscriber x pubblicazione/sottoscrizione canali REDIS
/// </summary>
private ISubscriber _currSub { get; set; } = null!;
/// <summary>
/// Message Dispatcher: oggetto comunicazione pub/sub via REDIS channels corrente
/// </summary>
protected ISubscriber messageDisp
{
get
{
ISubscriber answ;
// se già valorizzato uso oggetto private...
if (_currSub != null)
{
answ = _currSub;
}
else
{
// sottoscrizione al dispatcher messaggi
answ = redisConn.GetSubscriber();
_currSub = answ;
}
// restituisco oggetto DB
return answ;
}
}
protected JsonSerializerSettings? JSSettings;
/// <summary>
/// Oggetto per connessione a REDIS
/// </summary>
protected ConnectionMultiplexer redisConn = null!;
/// <summary>
/// Oggetto DB redis da impiegare x chiamate R/W
/// </summary>
protected IDatabase redisDb = null!;
#endregion Public Constructors
#region Public Methods
/// <summary>
/// Chiamata POST: riceve Json in formato JWD serializzato, lo ripete come risposta
/// PUT: api/calc/svg/00000000-0000-0000-0000-000000000000
/// </summary>
/// <param name="id">id oggetto</param>
/// <returns></returns>
[HttpPost("calc/{id}")]
public async Task<ActionResult<string>> calc(string id, [FromBody] string currJwd)
{
Stopwatch sw = new Stopwatch();
sw.Start();
lastSvg = "";
string svgContent = "";
// ...se ricevo percorso --> leggo jwd/svg cablato
if (!string.IsNullOrEmpty(currJwd))
{
if (true || (enableEgwEng && ProcessMan != null))
{
Dictionary<string, string> DictExec = new Dictionary<string, string>();
DictExec.Add("Mode", "1");
DictExec.Add("Jwd", currJwd);
int nId = 1;
ProcessArgs currArgs = new ProcessArgs(nId, DictExec);
sendMessage(ChannelName("", false), currArgs.sProcessArgs);
svgContent = "DONE";
#if false
bool done = ProcessMan.ArgumentsEnqueue(currArgs);
waitResult = true;
int numWait = 200;
while (numWait > 0 && waitResult)
{
numWait--;
await Task.Delay(waitDelay);
}
#endif
}
#if false
// se ho risultato mostro...
if (!string.IsNullOrEmpty(lastSvg))
{
svgContent = lastSvg;
// salvo!
ImgService.SaveSvg(id, svgContent);
}
else
{
svgContent = "EMPTY";
}
#endif
}
sw.Stop();
_logger.LogInformation($"svgString | {sw.Elapsed.TotalMilliseconds:N3} ms");
return Ok(svgContent);
}
/// <summary>
/// Chiamata POST: riceve Json in formato JWD serializzato, lo ripete come risposta
/// PUT: api/calc/svg/00000000-0000-0000-0000-000000000000
/// </summary>
/// <param name="id">id oggetto</param>
/// <returns></returns>
[HttpGet("svg/{id}")]
public async Task<ActionResult<string>> svg(string id)
{
Stopwatch sw = new Stopwatch();
sw.Start();
string svgContent = "";
// ...se ricevo percorso --> leggo jwd/svg cablato
if (!string.IsNullOrEmpty(id))
{
svgContent = ImgService.LoadSvg(id);
}
sw.Stop();
_logger.LogInformation($"svgString | {sw.Elapsed.TotalMilliseconds:N3} ms");
return Ok(svgContent);
}
#endregion Public Methods
#region Private Fields
private readonly ILogger<WindowController> _logger;
private IConfiguration _config;
private bool enableEgwEng = true;
//private Dictionary<int, string> listSvg = new Dictionary<int, string>();
private string lastSvg = "";
private int waitDelay = 10;
private bool waitResult = false;
#endregion Private Fields
#region Private Properties
private ImageCacheService ImgService { get; set; }
/// <summary>
/// Esecutore di processi generico
/// </summary>
private ExecProcessManager? ProcessMan { get; set; }
#endregion Private Properties
#region Private Methods
/// <summary>
/// Restituisce una risposta all'esecuzione
/// </summary>
/// <param name="ProcessArgsResult"></param>
private void ProcessMan_m_AnswerReceived(ProcessArgsResult result)
{
// verifico che sia la mia richeista con id immagine... FARE!!!
// salvo il risultato...
if (result.Args != null && result.Args.Count > 0)
{
if (result.Args.ContainsKey("Svg"))
{
// salvo SVG
string newSvg = result.Args["Svg"];
// salvo nel dizionario
lastSvg = newSvg;
waitResult = false;
}
}
}
#endregion Private Methods
}
}