274 lines
9.2 KiB
C#
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
|
|
}
|
|
} |