using EgwCoreLib.Lux.Core.RestPayload; using static Egw.Window.Data.Enums; using static EgwCoreLib.Lux.Core.Enums; namespace Lux.API.Services { public class ExternalMessageProcessor { #region Public Constructors /// /// Init classe message processor con accesso REDIS e DB /// /// /// /// /// public ExternalMessageProcessor(IImageCacheService imgService, IDataLayerServices dlService, ICalcRuidService crService, IProdService prodService) { cacheService = imgService; dbService = dlService; _calcRuidService = crService; _prodService = prodService; } #endregion Public Constructors #region Public Methods public async Task HandleResultMessageAsync(string channel, string message) { Log.Info($"Processing message from {channel} | {message.Length}"); Stopwatch sw = new Stopwatch(); sw.Start(); string rawData = $"{message}"; if (!string.IsNullOrEmpty(rawData) && rawData.Length > 2) { try { AnswerDTO? retData = JsonConvert.DeserializeObject(rawData); bool saved = await ProcessAnswer(retData); #if DEBUG // se in debug forzo save dell'ultima chiamata comunque... saved = false; #endif // se non avessi salvato e non sapessi cosa fosse --> salvo comunque x debug... if (!saved && retData != null) { string UID = retData.Args["UID"]; var envir = retData.ExecEnvironment; // salvo in area generica... await SaveRawData(UID, retData.ExecEnvironment, rawData); } } catch (Exception exc) { Log.Error($"Errore in fase decodifica messaggio da REDIS Channel{Environment.NewLine}{exc}"); } } sw.Stop(); Log.Info($"HandleResultMessageAsync | {sw.Elapsed.TotalMilliseconds:N3} ms"); #if false // Process message (parse, validate, act) var payload = message; // or JSON-deserialize, etc. await _redisService.SetAsync("last:result", payload); #endif } /// /// Rilettura della risposta in formato RawData x Debug /// /// /// public async Task LoadRawData(string UID, Constants.EXECENVIRONMENTS envir) { // rileggo string rawData = await cacheService.LoadDebug(UID, envir); return rawData; } /// /// Processing di una risposta AnswerDTO /// /// /// public async Task ProcessAnswer(AnswerDTO? retData) { bool saved = false; if (retData != null) { if (retData.Args != null && retData.Args.Count > 0) { /*------------------------------------------ * Richieste "continue" di stato/update * ----------------------------------------*/ string UID = retData.Args["UID"]; string RUID = ""; Egw.Window.Data.Enums.QuestionModes cMode = QuestionModes.NULL; if (retData.Args.ContainsKey("Mode")) { string sMode = retData.Args["Mode"]; if (int.TryParse(sMode, out int iMode)) { bool modeValido = Enum.IsDefined(typeof(QuestionModes), iMode); if (modeValido) { cMode = (QuestionModes)iMode; } } } // gestione RUID if (retData.Args.ContainsKey("RUID")) { RUID = retData.Args["RUID"]; // salvo SUBITO chiusura statistiche... string hKey = await _calcRuidService.CompleteRequestAsync(RUID); // verifico eventuali spostamenti code calcolo await _prodService.UpdateQueueAsync(retData.ExecEnvironment, hKey); } // gestione ritorno preview SVG if (retData.Args.ContainsKey("Svg")) { // recupero UID ed SVG string newSvg = retData.Args["Svg"]; // reinvio in redis (cache + channel) await cacheService.SaveSvgAsync(UID, retData.ExecEnvironment, newSvg); saved = true; } // gestione ritorno preview PNG if (retData.Args.ContainsKey("Png")) { // recupero UID ed SVG string newPng = retData.Args["Png"]; // reinvio in redis (cache + channel) await cacheService.SavePngAsync(UID, retData.ExecEnvironment, newPng); saved = true; } // gesitone ritorno BOM if (retData.Args.ContainsKey("BOM")) { // recupero UID e BOM string newBom = retData.Args["BOM"]; // salvo BOM ricevuta RAW in redis (cache) await cacheService.SaveBomAsync(UID, retData.ExecEnvironment, newBom); // salvo la BOM completa con i dati recuperati dal DB await dbService.SaveBomAsync(UID, cMode, retData.ExecEnvironment, newBom); // reset cache redis... await cacheService.ExecFlushRedisPatternAsync((RedisValue)$"{redisBaseKey}:Offers:*"); await cacheService.ExecFlushRedisPatternAsync((RedisValue)$"{redisBaseKey}:OfferRows:*"); // pubblico refresh info così da segnalare richiesta di update conseguente await cacheService.PublishUpdateAsync(UID, retData.ExecEnvironment); saved = true; } // gestione ritorno tipo Shape if (retData.Args.ContainsKey("SashShape")) { // recupero UID ed SVG string newShape = retData.Args["SashShape"]; // reinvio in redis (cache + channel) await cacheService.SaveShapeAsync(UID, retData.ExecEnvironment, newShape); saved = true; } // gestione ritorno tipo Stima Tempi e lavorabilità (x carico macchine/schedulazione) if (retData.Args.ContainsKey("Estimate")) { // recupero lista risultati calcolo... string rawAnsw = retData.Args["Estimate"]; List? machineEstimList = new List(); // deserializzo try { await dbService.SaveProdEstimateAsync(UID, retData.ExecEnvironment, rawAnsw); } catch (Exception exc) { Log.Error($"Eccezione in gestione Estimate{Environment.NewLine}{exc}"); } // reinvio in redis (cache + channel) await cacheService.SaveProdEstimateAsync(UID, retData.ExecEnvironment, rawAnsw); saved = true; } // gestione ritorno tipo Balance dei gruppi di lavorazione (x carico macchine/schedulazione) if (retData.Args.ContainsKey("Balance")) { // ATTENZIONE! qui oltre al valore UID deve leggere ANCHE il gruppo cui è riferito (es: Group: 1) // recupero lista risultati calcolo... string refGroup = retData.Args["Group"]; string rawBalance = retData.Args["Balance"]; List? machineEstimList = new List(); // deserializzo try { await dbService.SaveProdBalanceAsync(UID, refGroup, retData.ExecEnvironment, rawBalance); } catch (Exception exc) { Log.Error($"Eccezione in gestione Balance{Environment.NewLine}{exc}"); } // sistemo code, definendo nuova key... string qKey = $"{QuestionModes.ORDER}:{QuestionOrderSubModes.BALANCE}:{UID}.{refGroup}"; await _prodService.SetDoneAsync(retData.ExecEnvironment, qKey, ProdQueueType.running); // reinvio in redis (cache + channel) await cacheService.SaveProdBalanceAsync(UID, retData.ExecEnvironment, rawBalance); saved = true; } // gestione ritorno opzioni HW if (retData.Args.ContainsKey("HardwareOptions")) { // recupero UID ed SVG string newHwOpt = retData.Args["HardwareOptions"]; // reinvio in redis (cache + channel) await cacheService.SaveHwOptAsync(UID, retData.ExecEnvironment, newHwOpt); saved = true; } /*------------------------------------------ * Richieste "one shot" di configurazione * - fare 1/gg o su richiesta utente * ----------------------------------------*/ // Gestione ritorno lista preferiti HW (ammissibili) if (retData.Args.ContainsKey("HardwareModelList")) { // recupero UID e lista preferiti HW string newHml = retData.Args["HardwareModelList"]; // salvo HardwareList ricevuta await cacheService.SaveHmlAsync(UID, retData.ExecEnvironment, newHml); await dbService.SaveHmlAsync(UID, retData.ExecEnvironment, newHml); saved = true; } // gestione ritorno lista profili VALIDI per JWD if (retData.Args.ContainsKey("ProfileListAsync")) { // recupero UID e elenco profili validi string profList = retData.Args["ProfileListAsync"]; // salvo ProfileListAsync ricevuta await cacheService.SaveProfileListAsync(UID, retData.ExecEnvironment, profList); await dbService.SaveProfileListAsync(UID, retData.ExecEnvironment, profList); saved = true; } // gestione ritorno lista AreaProfiles per live JWD if (retData.Args.ContainsKey("AreaProfiles")) { // recupero UID e elenco profili validi string areaProfList = retData.Args["AreaProfiles"]; // salvo ProfileListAsync ricevuta await cacheService.SaveProfileElemAsync(UID, retData.ExecEnvironment, areaProfList); saved = true; } // gestione ritorno dati Threshold x profilo VALIDI per JWD if (retData.Args.ContainsKey("ThresholdList")) { // recupero UID e elenco profili validi string threshList = retData.Args["ThresholdList"]; // recuperro anche i profile data string profData = retData.Args["ProfileData"]; // salvo ProfileListAsync ricevuta await cacheService.SaveProfileThreshAsync(UID, retData.ExecEnvironment, threshList, profData); await dbService.SaveProfileThreshAsync(UID, retData.ExecEnvironment, threshList, profData); saved = true; } } } return saved; } /// /// Salvataggio della risposta in formato RawData x Debug /// /// /// public async Task SaveRawData(string UID, Constants.EXECENVIRONMENTS envir, string rawData) { // salvo in area generica... await cacheService.SaveDebug(UID, envir, rawData); } #endregion Public Methods #region Private Fields private static Logger Log = LogManager.GetCurrentClassLogger(); private readonly ICalcRuidService _calcRuidService; private readonly IProdService _prodService; private readonly IImageCacheService cacheService; private readonly IDataLayerServices dbService; private string redisBaseKey = "Lux:Cache"; #endregion Private Fields } }