using EgwCoreLib.Lux.Core.RestPayload; using EgwMultiEngineManager.Data; using Microsoft.Extensions.Configuration; using Newtonsoft.Json; using NLog; using RestSharp; using StackExchange.Redis; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace EgwCoreLib.Lux.Data.Services { public class ImageCacheService { #region Public Constructors public ImageCacheService(IConfiguration config, IRedisService redisService) { _config = config; _redisService = redisService; svgChannel = _config.GetValue("ServerConf:SvgChannel") ?? "svg:img"; liveTag = _config.GetValue("ServerConf:ImageLiveTag") ?? "svg"; cacheTag = _config.GetValue("ServerConf:ImageFileTag") ?? "svgfile"; calcTag = _config.GetValue("ServerConf:ImageCalcTag") ?? "svg-preview"; bomChannel = _config.GetValue("ServerConf:BomChannel") ?? "Egw-bom"; updateChannel = _config.GetValue("ServerConf:UpdateChannel") ?? "Egw-update"; // verifico la url base apiUrl = _config.GetValue("ServerConf:Prog.ApiUrl") ?? "https://iis01.egalware.com/lux/srv/api"; imgBasePath = _config.GetValue("ServerConf:ImageBaseUrl") ?? "window"; // fix opzioni base del RestClient restOptStd = new RestClientOptions { Timeout = TimeSpan.FromSeconds(60), BaseUrl = new Uri($"{apiUrl}/{imgBasePath}") }; Log.Info("ImageCache Service Started"); } #endregion Public Constructors #region Public Methods /// /// Effettua una generica chiamata ApiRest /// /// URL Api di base /// Richiesta completa /// public async Task CallRestGet(string ApiUrl, string ApiRequest) { RestResponse response; // cerco online using (RestClient client = new RestClient(ApiUrl)) { var request = new RestRequest(ApiRequest, Method.Get); response = await client.GetAsync(request); } return response; } /// #if false /// Effettua una generica chiamata ApiRest /// /// URL Api di base /// Richiesta completa /// Corpo Json trasmesso con richiesta /// public async Task CallRestPost(string ApiUrl, string ApiRequest, string JsonBody) { RestResponse response; // cerco online using (RestClient client = new RestClient(ApiUrl)) { var request = new RestRequest(ApiRequest, Method.Post); string rawData = JsonConvert.SerializeObject(JsonBody); request.AddJsonBody(rawData); response = await client.ExecutePostAsync(request); } return response; } #endif /// /// Effettua una generica chiamata ApiRest /// /// URL Api di base /// Richiesta completa /// Corpo Json trasmesso con richiesta /// public async Task CallRestPost(string ApiUrl, string ApiRequest, object rawBody) { RestResponse response; // cerco online using (RestClient client = new RestClient(ApiUrl)) { var request = new RestRequest(ApiRequest, Method.Post); string rawData = JsonConvert.SerializeObject(rawBody); request.AddJsonBody(rawData); response = await client.ExecutePostAsync(request); } return response; } /// /// Calcola URL immagine dato /// /// Base url IMG server (da config) /// Live = in fase di calcolo (cache REDIS), altrimenti da filesystem /// UID elemento/immagine /// Environment item /// public string ImageUrl(string baseUrl, bool isLive, string imgUID, EgwMultiEngineManager.Data.Constants.EXECENVIRONMENTS envir = EgwMultiEngineManager.Data.Constants.EXECENVIRONMENTS.WINDOW) { string tag = isLive ? liveTag : cacheTag; if (imgUID.EndsWith(".svg")) { imgUID.Replace(".svg",""); } string rndImg = $"{DateTime.Now:HHmmssfff}"; string fullUrl = $"{baseUrl}/{tag}/{imgUID}-{rndImg}.svg?envir={envir}".Replace("////", "//"); return fullUrl; } /// /// Recupera img redis SVG x id item richiesto /// /// UID item /// Environment item public string LoadSvg(string imgUid, EgwMultiEngineManager.Data.Constants.EXECENVIRONMENTS envir = EgwMultiEngineManager.Data.Constants.EXECENVIRONMENTS.WINDOW) { // recupero img da cache string currKey = $"{redisBaseKey}:{envir}:Images:{imgUid.Replace("/", ":")}"; var rawVal = _redisService.Get(currKey); return $"{rawVal}"; } /// /// Recupera img redis SVG x id item richiesto async /// /// UID item /// Environment item public async Task LoadSvgAsync(string imgId, EgwMultiEngineManager.Data.Constants.EXECENVIRONMENTS envir = EgwMultiEngineManager.Data.Constants.EXECENVIRONMENTS.WINDOW) { // recupero img da cache string currKey = $"{redisBaseKey}:{envir}:Images:{imgId.Replace("/", ":")}"; var rawVal = await _redisService.GetAsync(currKey); return $"{rawVal}"; } /// /// Calcola URL immagine dato /// /// Base url IMG server (da config) /// UID elemento/immagine /// JWD serializzato di cui si richiede l'immagine aggiornata /// public string ReqUpdateSvg(string baseUrl, string imgUID, string serJwd) { string answ = ""; if (imgUID.EndsWith(".svg")) { imgUID.Replace(".svg", ""); } string fullUrl = $"{baseUrl}/svg-preview/{imgUID}".Replace("////", "//"); return answ; } /// /// Salva e invia su channel BOM redis il doc richiesto /// /// /// /// public async Task SaveBomAsync(string uid, Constants.EXECENVIRONMENTS env, string bomContent) { // salvo in cache string currKey = $"{redisBaseKey}:{env}:BOM:{uid.Replace("/", ":")}"; var done = await _redisService.SetAsync(currKey, bomContent); // invio notifica nuova svg generata sul canale... viene inviato solo svg con ID nel canale string notifyChannel = $"{bomChannel}:{uid}"; long numSent = await _redisService.PublishAsync(notifyChannel, bomContent); return done; } /// /// Salva e invia su channel richiesto un update x UID /// è attesao un refresh per chi sottoscrive il canale /// /// /// public async Task PublishUpdateAsync(string uid, Constants.EXECENVIRONMENTS env) { bool done = false; // invio notifica sul canale di update generale... string notifyChannel = $"{updateChannel}:{env}"; // contenuto è UID long numSent = await _redisService.PublishAsync(notifyChannel, $"{uid}"); done = numSent > 0; return done; } /// /// Salva e invia su channel img redis SVG per il doc richiesto /// /// /// public async Task SaveHmlAsync(string uid, Constants.EXECENVIRONMENTS env, string rawData) { // salvo img in cache string currKey = $"{redisBaseKey}:{env}:HML:{uid.Replace("/", ":")}"; var done = await _redisService.SetAsync(currKey, rawData); // invio notifica nuova svg generata sul canale... viene inviato solo svg con ID nel canale string notifyChannel = $"{hmlChannel}:{uid}"; long numSent = await _redisService.PublishAsync(notifyChannel, rawData); return done; } /// /// Salva e invia su channel img redis SVG per il doc richiesto /// /// /// /// public bool SaveSvg(string imgId, EgwMultiEngineManager.Data.Constants.EXECENVIRONMENTS env, string svgContent) { // salvo img in cache string currKey = $"{redisBaseKey}:{env}:Images:{imgId.Replace("/", ":")}"; var done = _redisService.Set(currKey, svgContent); // invio notifica nuova imgsvg sul canale... viene "reimbustata" string notifyChannel = $"svg-gen:{imgId}"; long numSent = _redisService.Publish(notifyChannel, svgContent); return done; } /// /// Salva e invia su channel img redis SVG per il doc richiesto /// /// /// /// public async Task SaveSvgAsync(string imgId, EgwMultiEngineManager.Data.Constants.EXECENVIRONMENTS env, string svgContent) { // salvo img in cache string currKey = $"{redisBaseKey}:{env}:Images:{imgId.Replace("/", ":")}"; var done = await _redisService.SetAsync(currKey, svgContent); // invio notifica nuova svg generata sul canale... viene inviato solo svg con ID nel canale string notifyChannel = $"{svgChannel}:{imgId}"; long numSent = await _redisService.PublishAsync(notifyChannel, svgContent); return done; } #endregion Public Methods #region Private Fields private static Logger Log = LogManager.GetCurrentClassLogger(); private readonly IRedisService _redisService; private readonly string apiUrl = ""; private readonly string bomChannel = "bom:item"; private readonly string updateChannel = "ui:update"; private readonly string cacheTag = "svgfile"; private readonly string calcTag = "svgpreview"; private readonly string hmlChannel = "hml:item"; private readonly string imgBasePath = ""; private readonly string liveTag = "svg"; private readonly string svgChannel = "svg:img"; private IConfiguration _config; private string imageBaseUrl = ""; private string redisBaseKey = "Lux"; #endregion Private Fields #region Private Properties /// /// Conf client RestSharp standard: /// - base URI al sito /// - timeout 1 min /// private RestClientOptions restOptStd { get; set; } = new RestClientOptions(); #endregion Private Properties } }