using EgwCoreLib.Utils; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Configuration; using MP.Core.DTO; using MP.Core.Objects; using MP.Data.DbModels; using Newtonsoft.Json; using NLog; using StackExchange.Redis; using System; using System.Collections.Generic; using System.Data; using System.Diagnostics; using System.Globalization; using System.Linq; using System.Text; using System.Threading.Tasks; namespace MP.Data.Services { public class TabDataService : BaseServ { #region Public Constructors /// /// Init servizio TAB /// /// public TabDataService(IConfiguration configuration, IConnectionMultiplexer redConn) : base(configuration, redConn) { _configuration = configuration; // conf DB ConnStr = _configuration.GetConnectionString("MP.All"); if (string.IsNullOrEmpty(ConnStr)) { Log.Error("ConnString empty!"); } else { StringBuilder sb = new StringBuilder(); dbTabController = new Controllers.MpTabController(configuration); sb.AppendLine($"TabDataService | MpTabController OK"); dbIocController = new Controllers.MpIocController(configuration); sb.AppendLine($"TabDataService | MpIocController OK"); dbInveController = new Controllers.MpInveController(configuration); sb.AppendLine($"TabDataService | MpInveController OK"); Log.Info(sb.ToString()); // sistemo i parametri x redHas... CodModulo = _configuration.GetValue("SpecialConf:CodModulo"); CodModuloParam = _configuration.GetValue("SpecialConf:CodModuloParam"); #if false MpIoNS = _configuration.GetValue("ServerConf:MpIoNS"); #endif var cstringArray = ConnStr.Split(";"); foreach (var item in cstringArray) { var cData = item.Trim().Split("="); if (cData.Length == 2) { if (!connStrParams.ContainsKey(cData[0])) { connStrParams.Add(cData[0], cData[1]); } } } // sistemo DataSource = connStrParams["Server"]; DataBase = connStrParams["Database"]; } } #endregion Public Constructors #region Public Events /// /// Evento report dati invalidati x rilettura /// public event EventHandler DataInvalidated = delegate { }; /// /// Evento richiesta rilettura dati pagina (x refresh pagine aperte) /// public event EventHandler ReloadRequest = delegate { }; #endregion Public Events #region Public Properties /// /// Conmfig attivo da DB /// public List CurrConfig { get; set; } = new List(); #endregion Public Properties #region Public Methods /// /// Aggiunge un task all'elenco di quelli salvati (in modalità upsert) /// /// /// /// /// public bool addTask4Machine(string idxMacchina, Enums.taskType taskKey, string taskVal) { bool answ = false; string currHash = exeTaskHash(idxMacchina); string currSavedParHash = savedTaskHash(idxMacchina); Dictionary currTask = new Dictionary(); Dictionary savedTask = new Dictionary(); try { //Log.Info($"Request: idxMacchina: {idxMacchina} | taskKey: {taskKey} | taskVal: {taskVal}"); // leggo task attuali... currTask = mTaskMacchina(idxMacchina); if (currTask.ContainsKey($"{taskKey}")) { currTask[$"{taskKey}"] = taskVal; } else { currTask.Add($"{taskKey}", taskVal); } answ = redisHashDictSet(currHash, currTask); Log.Info($"Task ADD | hash: {currHash} | - idxMacchina: {idxMacchina} | taskKey: {taskKey} | taskVal: {taskVal}"); } catch { } // verifico in base al tipo di task se fare backup... switch (taskKey) { case Enums.taskType.setArt: case Enums.taskType.setComm: case Enums.taskType.setPzComm: case Enums.taskType.setProg: // leggo task SALVATI attuali... savedTask = mSavedTaskMacchina(idxMacchina); savedTask[taskKey.ToString()] = taskVal; answ = redisHashDictSet(currSavedParHash, savedTask); break; case Enums.taskType.endProd: // salvo un DICT vuoto x resettare savedTask = new Dictionary(); answ = redisHashDictSet(currSavedParHash, savedTask); break; default: break; } return answ; } /// /// Elenco allarmi macchina /// /// Macchina /// Inizio periodo /// Fine periodo /// /// public async Task> AlarmLogListFilt(string idxMacchina, DateTime dtFrom, DateTime dtTo, bool showMulti) { string source = "DB"; Stopwatch sw = new Stopwatch(); sw.Start(); List? result = new List(); // cerco in _redisConn... string currKey = $"{redisBaseKey}:AlarmLog:{idxMacchina}:{dtFrom:yyyyMMdd-HHmmss}:{dtTo::yyyyMMdd-HHmmss}:{showMulti}"; RedisValue rawData = await _redisDb.StringGetAsync(currKey); if (rawData.HasValue) { result = JsonConvert.DeserializeObject>($"{rawData}"); source = "REDIS"; } else { result = await Task.FromResult(dbTabController.AlarmLogListFilt(idxMacchina, dtFrom, dtTo, showMulti)); // serializzo e salvo... rawData = JsonConvert.SerializeObject(result); await _redisDb.StringSetAsync(currKey, rawData, UltraFastCache); } if (result == null) { result = new List(); } sw.Stop(); Log.Debug($"AlarmLogListFilt | {source} | {sw.Elapsed.TotalMilliseconds}ms"); return result; } /// /// Registrato ACK allarme /// /// Id Allarme /// Data Ack /// User Ack /// public bool AlarmLogSetAck(int alarmLogId, DateTime dtAck, string userAck) { bool answ = dbTabController.AlarmLogSetAck(alarmLogId, dtAck, userAck); return answ; } /// /// Registrato ACK allarme /// /// Id Allarme /// Data Ack /// public bool AlarmLogSetNotify(int alarmLogId, DateTime dtNotify) { bool answ = dbTabController.AlarmLogSetNotify(alarmLogId, dtNotify); return answ; } /// /// Elenco completo EVENTI /// /// public async Task> AnagEventiGetAll() { // setup parametri costanti string source = "DB"; Stopwatch sw = new Stopwatch(); sw.Start(); List? result = new List(); // cerco in _redisConn... string currKey = $"{redisBaseKey}:AnagEventi:ALL"; RedisValue rawData = await _redisDb.StringGetAsync(currKey); if (rawData.HasValue) { result = JsonConvert.DeserializeObject>($"{rawData}"); source = "REDIS"; } else { result = dbTabController.AnagEventiGetAll(); // serializzo e salvo... rawData = JsonConvert.SerializeObject(result); await _redisDb.StringSetAsync(currKey, rawData, LongCache); } if (result == null) { result = new List(); } sw.Stop(); Log.Debug($"AnagEventiGetAll | {source} | {sw.Elapsed.TotalMilliseconds}ms"); return result; } /// /// Elenco EVENTI validi x macchina /// /// public List AnagEventiGetByMacch(string IdxMacch) { string source = "DB"; Stopwatch sw = new Stopwatch(); sw.Start(); List? result = new List(); // cerco in _redisConn... string currKey = $"{redisBaseKey}:VSEB:{IdxMacch}"; RedisValue rawData = _redisDb.StringGet(currKey); if (rawData.HasValue) { result = JsonConvert.DeserializeObject>($"{rawData}"); source = "REDIS"; } else { result = dbTabController.AnagEventiGetByMacc(IdxMacch); // serializzo e salvo... rawData = JsonConvert.SerializeObject(result); _redisDb.StringSet(currKey, rawData, LongCache); } if (result == null) { result = new List(); } sw.Stop(); Log.Debug($"AnagEventiGetByMacch | {source} | {sw.Elapsed.TotalMilliseconds}ms"); return result; } /// /// Restituisce l'anagrafica EVENTI per intero /// /// public async Task> AnagTagsOrd() { // setup parametri costanti string source = "DB"; Stopwatch sw = new Stopwatch(); sw.Start(); List? result = new List(); // cerco in _redisConn... string currKey = $"{redisBaseKey}:AnagTags"; RedisValue rawData = await _redisDb.StringGetAsync(currKey); if (rawData.HasValue) { result = JsonConvert.DeserializeObject>($"{rawData}"); source = "REDIS"; } else { result = dbTabController.AnagTagsOrd(); // serializzo e salvo... rawData = JsonConvert.SerializeObject(result); await _redisDb.StringSetAsync(currKey, rawData, UltraLongCache); } if (result == null) { result = new List(); } sw.Stop(); Log.Debug($"AnagTagsOrd | {source} | {sw.Elapsed.TotalMilliseconds}ms"); return result; } /// /// Elenco completo STATI /// /// public async Task> AnaStatiGetAll() { // setup parametri costanti DateTime startDate = new DateTime(2000, 1, 1); DateTime endDate = DateTime.Today.AddDays(1); string source = "DB"; Stopwatch sw = new Stopwatch(); sw.Start(); List? result = new List(); // cerco in _redisConn... string currKey = $"{redisBaseKey}:AnagStati"; RedisValue rawData = await _redisDb.StringGetAsync(currKey); //if (!string.IsNullOrEmpty($"{rawData}")) if (rawData.HasValue) { result = JsonConvert.DeserializeObject>($"{rawData}"); source = "REDIS"; } else { result = dbTabController.AnagStatiGetAll(); // serializzo e salvo... rawData = JsonConvert.SerializeObject(result); await _redisDb.StringSetAsync(currKey, rawData, LongCache); } if (result == null) { result = new List(); } sw.Stop(); Log.Debug($"AnaStatiGetAll | {source} | {sw.Elapsed.TotalMilliseconds}ms"); return result; } /// /// Restitusice elenco articoli dato tipo (es KIT) /// /// /// /// public List ArticoliGetByTipo(string tipo, string azienda = "*") { List? result = new List(); Stopwatch stopWatch = new Stopwatch(); stopWatch.Start(); string readType = "DB"; string sKey = string.IsNullOrEmpty(tipo) ? "ALL" : tipo; string currKey = $"{MP.Core.Utils.redisArtList}:{azienda}:Tipo:{sKey}"; // cerco in _redisConn dato valore sel idxMaccSel... RedisValue rawData = _redisDb.StringGet(currKey); if (rawData.HasValue) { result = JsonConvert.DeserializeObject>($"{rawData}"); readType = "REDIS"; } else { result = dbTabController.ArticoliGetByTipo(tipo, azienda); // serializzo e salvo... rawData = JsonConvert.SerializeObject(result); _redisDb.StringSet(currKey, rawData, UltraLongCache); } if (result == null) { result = new List(); } stopWatch.Stop(); TimeSpan ts = stopWatch.Elapsed; Log.Debug($"ArticoliGetByTipo | Read from {readType}: {ts.TotalMilliseconds}ms"); return result; } /// /// Recupera elenco ultimi commenti /// /// Idx macchina, "*" = tutte /// Num di giorni da recuperare da adesso /// public async Task> CommentiGetLastByMacc(string idxMacchina, int numDays) { // setup parametri costanti string source = "DB"; Stopwatch sw = new Stopwatch(); sw.Start(); List result = new List(); DateTime adesso = DateTime.Now; // cerco in _redisConn... string currKey = $"{redisBaseKey}:Commenti:{idxMacchina}:{adesso:yyMMdd-HHmm}:{numDays}"; RedisValue rawData = await _redisDb.StringGetAsync(currKey); //if (!string.IsNullOrEmpty($"{rawData}")) if (rawData.HasValue) { result = JsonConvert.DeserializeObject>($"{rawData}"); source = "REDIS"; } else { result = dbTabController.CommentiGetLastByMacc(idxMacchina, numDays); // serializzo e salvo... rawData = JsonConvert.SerializeObject(result); await _redisDb.StringSetAsync(currKey, rawData, UltraFastCache); } if (result == null) { result = new List(); } sw.Stop(); Log.Debug($"CommentiGetLastByMacc | {source} | {sw.Elapsed.TotalMilliseconds}ms"); return result; } /// /// Effettua conferma prod macchina dell'intero periodo da confermare (ultima conferma /// --> dtEvent) /// /// idx macchina da confermare /// 0=periodo, 1 = giorno, 2 = turno /// qta pezzi BUONI da confermare /// qta pezzi SCARTO da confermare /// DataOra in cui registrare approvazione /// Matricola operatore /// public bool ConfermaProdMacchina(string idxMacchina, int modoConfProd, int numPzConfermati, int numPzScarto, DateTime DataOraApp, int MatrOpr) { bool answ = false; answ = dbTabController.ConfermaProdMacchina(idxMacchina, modoConfProd, numPzConfermati, numPzScarto, DataOraApp, MatrOpr); return answ; } /// /// Effettua conferma prod macchina dell'intero periodo da confermare (ultima conferma /// --> dtEvent) /// /// idx macchina da confermare /// 0=periodo, 1 = giorno, 2 = turno /// qta pezzi BUONI da confermare /// /// qta pezzi LASCIATI alla macchina da confermare (2 eventi 121 rettifica neg/pos) /// /// qta pezzi SCARTO da confermare /// DataOra in cui registrare approvazione /// Matricola operatore /// public bool ConfermaProdMacchinaFull(string idxMacchina, int modoConfProd, int numPzConfermati, int numPzLasciati, int numPzScarto, DateTime DataOraApp, int MatrOpr) { bool answ = false; answ = dbTabController.ConfermaProdMacchinaFull(idxMacchina, modoConfProd, numPzConfermati, numPzLasciati, numPzScarto, DataOraApp, MatrOpr); return answ; } /// /// Config values attivi /// /// public List ConfigGetAll() { string source = "DB"; Stopwatch sw = new Stopwatch(); sw.Start(); List? result = new List(); // cerco in _redisConn... string currKey = $"{redisBaseKey}:Conf"; RedisValue rawData = _redisDb.StringGet(currKey); //if (!string.IsNullOrEmpty($"{rawData}")) if (rawData.HasValue) { result = JsonConvert.DeserializeObject>($"{rawData}"); source = "REDIS"; } else { result = dbTabController.ConfigGetAll(); // serializzo e salvo... rawData = JsonConvert.SerializeObject(result); _redisDb.StringSet(currKey, rawData, LongCache); } if (result == null) { result = new List(); } sw.Stop(); Log.Debug($"ConfigGetAll | {source} | {sw.Elapsed.TotalMilliseconds}ms"); return result; } /// /// Recupera il valore in formato STRING /// /// Valore da cercare /// String in cui salvare il valore se trovato /// public bool ConfigGetVal(string chiave, ref string varObj) { bool answ = false; // se mancasse provo a configurare.. if (CurrConfig == null || CurrConfig.Count == 0) { SetupConfig(); } if (CurrConfig != null && CurrConfig.Count > 0) { // sistemo i parametri opzionali... ConfigModel? risultato = CurrConfig.FirstOrDefault(x => x.Chiave == chiave); if (risultato != null) { varObj = risultato.Valore; answ = !string.IsNullOrEmpty(risultato.Valore); } } return answ; } /// /// Recupera il valore in formato INT /// /// Valore da cercare /// Int in cui salvare il valore se trovato /// public bool ConfigGetVal(string chiave, ref int varObj) { bool answ = false; // se mancasse provo a configurare.. if (CurrConfig == null || CurrConfig.Count == 0) { SetupConfig(); } if (CurrConfig != null && CurrConfig.Count > 0) { // sistemo i parametri opzionali... ConfigModel? risultato = CurrConfig.FirstOrDefault(x => x.Chiave == chiave); if (risultato != null) { answ = int.TryParse(risultato.Valore, out varObj); } } return answ; } /// /// Recupera il valore in formato DOUBLE /// /// Valore da cercare /// Int in cui salvare il valore se trovato /// public bool ConfigGetVal(string chiave, ref double varObj) { bool answ = false; // se mancasse provo a configurare.. if (CurrConfig == null || CurrConfig.Count == 0) { SetupConfig(); } if (CurrConfig != null && CurrConfig.Count > 0) { // sistemo i parametri opzionali... ConfigModel? risultato = CurrConfig.FirstOrDefault(x => x.Chiave == chiave); if (risultato != null) { NumberStyles numStyle; CultureInfo culture; numStyle = NumberStyles.Number; culture = CultureInfo.InvariantCulture; //culture = CultureInfo.CreateSpecificCulture("en-US"); answ = double.TryParse(risultato.Valore, numStyle, culture, out varObj); } } return answ; } /// /// Recupera il valore in formato BOOL /// /// Valore da cercare /// Boolean in cui salvare il valore se trovato /// public bool ConfigGetVal(string chiave, ref bool varObj) { bool answ = false; // se mancasse provo a configurare.. if (CurrConfig == null || CurrConfig.Count == 0) { SetupConfig(); } if (CurrConfig != null && CurrConfig.Count > 0) { // sistemo i parametri opzionali... ConfigModel? risultato = CurrConfig.FirstOrDefault(x => x.Chiave == chiave); if (risultato != null) { answ = bool.TryParse(risultato.Valore, out varObj); } } return answ; } /// /// Inserimento record in DDB /// /// /// /// /// /// /// /// public async Task DDB_DoRecalc(string idxMacchina, DateTime inizio, int idxStatoStart, int nStepEventi, int nRecCheck, bool checkOnly) { bool answ = dbTabController.DDB_DoRecalc(idxMacchina, inizio, idxStatoStart, nStepEventi, nRecCheck, checkOnly); await FlushCache(); return answ; } /// /// Recupera record successivo da DDB /// /// /// /// public DiarioDiBordoModel DDB_getNext(string idxMacchina, DateTime inizioStato) { return dbTabController.DDB_getNext(idxMacchina, inizioStato); } public string DecryptData(string encData) { return SteamCrypto.DecryptString(encData, Constants.passPhrase); } /// /// Restituisce elenco ElencoConfermeProd filtrato e async /// /// /// /// /// public async Task> ElencoConfProdFiltAsync(string idxMacchina, DateTime dataFrom, DateTime dataTo) { // setup parametri costanti string source = "DB"; Stopwatch sw = new Stopwatch(); sw.Start(); List result = new List(); // cerco in _redisConn... string currKey = $"{redisBaseKey}:ElConfProd:{idxMacchina}:{dataFrom:yyyyyMMdd-HHmm}:{dataFrom:yyyyyMMdd-HHmm}"; RedisValue rawData = await _redisDb.StringGetAsync(currKey); if (rawData.HasValue) { result = JsonConvert.DeserializeObject>($"{rawData}") ?? new List(); source = "REDIS"; } else { result = dbTabController.ElencoConfProdFilt(idxMacchina, dataFrom, dataTo); // serializzo e salvo... rawData = JsonConvert.SerializeObject(result); await _redisDb.StringSetAsync(currKey, rawData, UltraLongCache); } sw.Stop(); string callName = $"ElencoConfProdFiltAsync.{source}"; int numRec = esCollect.RecordCall(callName, sw.Elapsed.TotalMilliseconds); if (numRec >= nRecLog) { Log.Debug(esCollect.GetCallSum(callName, true)); } return result; } /// /// Fix ODL per Elenco Lotti /// /// /// /// public async Task ElencoLottiUpsertByOdl(int idxOdl, bool flgStorico) { bool answ = false; try { // inserisco evento answ = dbTabController.ElencoLottiUpsertByOdl(idxOdl, flgStorico); await FlushCache("EL"); } catch (Exception exc) { string logMsg = $"Eccezione in ElencoLottiUpsertByOdl | idxOdl: {idxOdl} | flgStorico: {flgStorico}{Environment.NewLine}{exc}"; Log.Error(logMsg); } return answ; } /// /// Elenco operatori /// /// public async Task> ElencoOperatori() { string source = "DB"; Stopwatch sw = new Stopwatch(); sw.Start(); List? result = new List(); // cerco in _redisConn... string currKey = $"{redisBaseKey}:ElencoOpr"; RedisValue rawData = await _redisDb.StringGetAsync(currKey); if (rawData.HasValue) { result = JsonConvert.DeserializeObject>($"{rawData}"); source = "REDIS"; } else { result = dbTabController.ElencoOperatori(); // serializzo e salvo... rawData = JsonConvert.SerializeObject(result); await _redisDb.StringSetAsync(currKey, rawData, LongCache); } if (result == null) { result = new List(); } sw.Stop(); Log.Debug($"ElencoOperatori | {source} | {sw.Elapsed.TotalMilliseconds}ms"); return result; } public string EncryptData(string rawData) { return SteamCrypto.EncryptString(rawData, Constants.passPhrase); } /// /// Elimina una riga in EventList se trovata /// /// /// /// /// public async Task EvListDelete(string idxMacchina, DateTime dtEvento, int idxTipo) { bool fatto = false; try { // inserisco evento fatto = dbTabController.EvListDelete(idxMacchina, dtEvento, idxTipo); // reset cache eventi/commenti await FlushCache("EvList"); await FlushCache("Commenti"); } catch (Exception exc) { string logMsg = $"Eccezione in EvListDelete | macchina: {idxMacchina} | DataEv: {dtEvento} | idxTipo: {idxTipo}{Environment.NewLine}{exc}"; Log.Error(logMsg); } return fatto; } /// /// Recupera record EventList date condizioni filtro /// /// Idx macchina, "*" = tutte /// Data limite per recupero antecedenti /// Tipo evento cercato, 0 = tutti /// Num massimo di record da recuperare /// public async Task> EvListGetLastBySearch(string idxMacchina, DateTime dtLimit, int idxTipo, int maxRec) { // setup parametri costanti string source = "DB"; Stopwatch sw = new Stopwatch(); sw.Start(); List result = new List(); // cerco in _redisConn... string currKey = $"{redisBaseKey}:EvList:Last:{idxMacchina}:{idxTipo}:{dtLimit:yyyyMMdd-HHmm}:{maxRec}"; RedisValue rawData = await _redisDb.StringGetAsync(currKey); //if (!string.IsNullOrEmpty($"{rawData}")) if (rawData.HasValue) { result = JsonConvert.DeserializeObject>($"{rawData}"); source = "REDIS"; } else { result = await dbTabController.EvListGetLastBySearch(idxMacchina, dtLimit, idxTipo, maxRec); // serializzo e salvo... rawData = JsonConvert.SerializeObject(result); await _redisDb.StringSetAsync(currKey, rawData, LongCache); } if (result == null) { result = new List(); } sw.Stop(); Log.Debug($"EvListGetLastBySearch | {source} | {sw.Elapsed.TotalMilliseconds}ms"); return result; } /// /// Scrive una riga in EventList inviato nel db + check /// /// Record da registrare /// public async Task EvListInsert(EventListModel newRec, Enums.tipoInputEvento tipoEv) { bool inserito = false; try { // inserisco evento inserito = await dbTabController.EvListInsert(newRec); // reset cache eventi/commenti await FlushCache("EvList"); await FlushCache("Commenti"); } catch (Exception exc) { string logMsg = $"Eccezione in fase di scrittura evento con i seguenti dati | macchina: {newRec.IdxMacchina} | IdxTipo: {newRec.IdxTipo} | CodArticolo: {newRec.CodArticolo} | Value {newRec.Value} | MatrOpr {newRec.MatrOpr} | Pallet {newRec.pallet}{Environment.NewLine}{exc}"; Log.Error(logMsg); } // se non è un commento... if (tipoEv != Enums.tipoInputEvento.commento) { try { // faccio controllo per eventuale cambio stato da tab transizioni... dbTabController.CheckCambiaStatoBatch(tipoEv, newRec.IdxMacchina, newRec.InizioStato ?? DateTime.Now, newRec.IdxTipo, newRec.CodArticolo, newRec.Value, newRec.MatrOpr, newRec.pallet); } catch (Exception exc) { string logMsg = $"Eccezione in checkCambiaStatoBatch(6) | tipoInputEvento: {tipoEv} |macchina: {newRec.IdxMacchina} | IdxTipo: {newRec.IdxTipo} | CodArticolo: {newRec.CodArticolo} | Value: {newRec.Value} | MatrOpr: {newRec.MatrOpr} | Pallet: {newRec.pallet}{Environment.NewLine}{exc}"; Log.Error(logMsg); } } // formatto output inputComandoMapo answ = new inputComandoMapo(); answ.outValue = inserito.ToString(); answ.needStatusRefresh = true; return answ; } /// /// Recupera elenco fermi non qualificati da filtro /// /// Idx macchina, "*" = tutte /// Num massimo di giorni antecedenti /// Durata minima (in minuti) /// public async Task> FermiNonQualificatiFilt(string idxMacchina, int gg, double durataMin) { // setup parametri costanti string source = "DB"; Stopwatch sw = new Stopwatch(); sw.Start(); List result = new List(); // cerco in _redisConn... string currKey = $"{redisBaseKey}:FNQ:{idxMacchina}:{gg}:{durataMin:N0}"; RedisValue rawData = await _redisDb.StringGetAsync(currKey); if (rawData.HasValue) { result = JsonConvert.DeserializeObject>($"{rawData}"); source = "REDIS"; } else { result = dbTabController.FermiNonQualificatiFilt(idxMacchina, gg, durataMin); // serializzo e salvo... rawData = JsonConvert.SerializeObject(result); await _redisDb.StringSetAsync(currKey, rawData, FastCache); } if (result == null) { result = new List(); } sw.Stop(); Log.Debug($"FermiNonQualificatiFilt | {source} | {sw.Elapsed.TotalMilliseconds}ms"); return result; } /// /// Pulizia cache Redis (tutta) /// /// public async Task FlushCache() { RedisValue pattern = new RedisValue($"{redisBaseKey}:*"); bool answ = await ExecFlushRedisPatternAsync(pattern); return answ; } /// /// Pulizia cache Redis per chiave specifica (da redisBaseKey...) /// /// public async Task FlushCache(string KeyReq) { RedisValue pattern = new RedisValue($"{redisBaseKey}:{KeyReq}:*"); bool answ = await ExecFlushRedisPatternAsync(pattern); return answ; } /// /// Flush di tutta la cache relativa ad i dati ODL/PODL /// /// public async Task FlushOdlCache() { await FlushCache("ODL"); await FlushCache("PODL"); await FlushCache("VSODL"); await FlushCache("StatoMacc"); await FlushCache("MSFD"); } public TimeSpan GetKeyTTL(string redKey) { TimeSpan answ = TimeSpan.FromMinutes(-1); try { answ = _redisDb.KeyTimeToLive(redKey) ?? new TimeSpan(); } catch (Exception exc) { Log.Info($"Errore GetKeyTTL | currKey: {redKey}{Environment.NewLine}{exc}"); } return answ; } /// /// Elenco DTO resoconto InsManuali macchina da records dettaglio /// /// Dettagli /// public List InsManDayDto(List listDetail) { List? result = new List(); if (listDetail.Count > 0) { string idxMacchina = listDetail.FirstOrDefault().IdxMacchina; // proietto... result = listDetail .GroupBy(x => x.InizioStato.Date) .Select(group => new InsManDayDto { DataRif = group.Key, IdxMacchina = idxMacchina, MinProdTot = group.Sum(item => item.MinProd), PzBuoniTot = group.Sum(item => item.PzBuoni), RatioImport = group.Count(item => item.Imported != null) / group.Count() }) .ToList(); } return result; } /// /// Elimina record + svuotamento cache /// /// public async Task InsManDelete(InsManualiModel currRecord) { bool fatto = false; // salvo fatto = dbTabController.InsManDelete(currRecord); // svuoto cache RedisValue pattern = $"{redisBaseKey}:InsMan:*"; await ExecFlushRedisPatternAsync(pattern); return fatto; } /// /// Riempie eventuali buchi con evento indicato /// /// Data per cui effettuare ricalcolo giornata /// Record dettaglio giornata /// IdxTipo da riempire /// MatrOperatore corrente /// public async Task InsManFillMissing(DateTime dtRif, List listDetail, int idxTipoEv, int matrOpr) { List rec2add = new List(); InsManualiModel newRec = new InsManualiModel(); if (listDetail.Count > 0) { // punto come record attuale il primo InsManualiModel currRec = listDetail.FirstOrDefault(); string idxMacc = currRec.IdxMacchina; DateTime periodStart = currRec.InizioStato; DateTime periodEnd = currRec.FineStato.Value; // se NON parte da mezzanotte metto un "pad iniziale"... if (periodStart.TimeOfDay > new TimeSpan(0)) { // creo record x la durata necessaria newRec = new InsManualiModel() { CodArticolo = "ND", KeyRichiesta = "", IdxMacchina = idxMacc, InizioStato = periodStart.Date, FineStato = periodStart, IdxTipoEv = idxTipoEv, MatrOpr = matrOpr, PzBuoni = 0, TCiclo = 0, MinProd = (decimal)periodStart.TimeOfDay.TotalMinutes }; rec2add.Add(newRec); } // cerco ultimo record... che sia della data odierna! currRec = listDetail.Where(x => x.InizioStato.Date == dtRif.Date).LastOrDefault(); periodStart = currRec.InizioStato; periodEnd = currRec.FineStato.Value; // se andassi a domani lo "accorcio"... if (periodEnd < dtRif.Date.AddDays(1).AddSeconds(-1)) { // se non arrivo a mezzanotte aggiungo "pad finale" var lastPeriod = TimeSpan.FromHours(24).Subtract(periodEnd.TimeOfDay).TotalMinutes; if (lastPeriod > 1) { // creo record x la durata necessaria newRec = new InsManualiModel() { CodArticolo = "ND", KeyRichiesta = "", IdxMacchina = idxMacc, InizioStato = periodEnd, FineStato = periodEnd.Date.AddDays(1).AddSeconds(-1), IdxTipoEv = idxTipoEv, MatrOpr = matrOpr, PzBuoni = 0, TCiclo = 0, MinProd = (decimal)lastPeriod }; rec2add.Add(newRec); } } // eseguo upsert massivo await InsManUpsert(rec2add); } return rec2add.Count; } /// /// Elenco insManuali macchina /// /// Macchina /// Inizio periodo /// Fine periodo /// public List InsManFilt(string idxMacchina, DateTime dtFrom, DateTime dtTo) { string source = "DB"; Stopwatch sw = new Stopwatch(); sw.Start(); List? result = new List(); // cerco in _redisConn... string currKey = $"{redisBaseKey}:InsMan:{idxMacchina}:{dtFrom:yyyyMMdd-HHmmss}:{dtTo::yyyyMMdd-HHmmss}"; RedisValue rawData = _redisDb.StringGet(currKey); if (rawData.HasValue) { result = JsonConvert.DeserializeObject>($"{rawData}"); source = "REDIS"; } else { result = dbTabController.InsManFilt(idxMacchina, dtFrom, dtTo); // serializzo e salvo... rawData = JsonConvert.SerializeObject(result); _redisDb.StringSet(currKey, rawData, FastCache); } if (result == null) { result = new List(); } sw.Stop(); Log.Debug($"InsManFilt | {source} | {sw.Elapsed.TotalMilliseconds}ms"); return result; } /// /// Chiama stored x congelare i dati giornalieri /// /// /// /// public async Task InsManFreezeDay(string idxMacchina, DateTime dtCurr) { bool fatto = false; Stopwatch sw = new Stopwatch(); sw.Start(); Log.Info($"Inizio InsManFreezeDay | idxMacchina: {idxMacchina}"); // salvo fatto = await dbTabController.InsManFreezeDay(idxMacchina, dtCurr); // svuoto cache RedisValue pattern = $"{redisBaseKey}:InsMan:*"; await ExecFlushRedisPatternAsync(pattern); sw.Stop(); Log.Info($"Fine InsManFreezeDay | idxMacchina: {idxMacchina} | elapsed: {sw.Elapsed.TotalMilliseconds:N2} ms"); return fatto; } /// /// Elenco DTO x plotting seq stati giornaliero /// /// Data per cui effettuare ricalcolo giornata /// Record dettaglio giornata /// public List InsManSeqDayStatus(DateTime dtRif, List listDetail) { List? result = new List(); // per sicurezza RIORDINO! listDetail = listDetail .Where(x => x.InizioStato.Date == dtRif.Date) .OrderBy(x => x.InizioStato) .ToList(); if (listDetail.Count > 0) { DateTime periodStart = listDetail.FirstOrDefault().InizioStato; DateTime periodEnd = listDetail.FirstOrDefault().FineStato.Value; double duration = 0; int lastIdxTipo = -1; ManualStatusDTO currRec = new ManualStatusDTO(); // se NON parte da mezzanotte metto un "pad iniziale"... if (periodStart.TimeOfDay > new TimeSpan(0)) { lastIdxTipo = 0; currRec = new ManualStatusDTO { IdxTipo = lastIdxTipo, CssBlock = "bg-light text-dark", Title = "missing", Value = periodStart.TimeOfDay.TotalMinutes, ValueMax = 1440 }; } // ciclo tutti i record, verificando idxTipo... foreach (var item in listDetail) { if (item.IdxTipoEv != lastIdxTipo) { // aggiungo rec precedente... se > 0 if (currRec.Value > 0) { result.Add(currRec); } lastIdxTipo = item.IdxTipoEv; periodStart = item.InizioStato; periodEnd = item.FineStato.Value; //calcolo errore se supero giorno... bool hasError = periodEnd > dtRif.Date.AddDays(1); duration = (double)item.MinProd; currRec = new ManualStatusDTO { IdxTipo = lastIdxTipo, // fare da DB --> anagEventi CssBlock = item.IdxTipoEv == 1 ? "bg-success text-light" : "bg-secondary text-light", Title = $"{periodStart:HH:mm}-{periodEnd:HH:mm}", Value = duration, ValueMax = 1440, HasError = hasError }; } else { duration += (double)item.MinProd; periodEnd = item.FineStato.Value; //calcolo errore se supero giorno... bool hasError = periodEnd > dtRif.Date.AddDays(1); currRec = new ManualStatusDTO { IdxTipo = lastIdxTipo, // fare da DB --> anagEventi CssBlock = item.IdxTipoEv == 1 ? "bg-success text-light" : "bg-secondary text-light", Title = $"{periodStart:HH:mm}-{periodEnd:HH:mm}", Value = duration, ValueMax = 1440, HasError = hasError }; } } // aggiungo rec precedente... se > 0 if (currRec.Value > 0) { result.Add(currRec); } // se non arrivo a mezzanotte aggiungo "pad finale" if (periodEnd <= dtRif.Date.AddDays(1).AddSeconds(-1)) { var deltaFin = TimeSpan.FromHours(24).Subtract(periodEnd.TimeOfDay); if (deltaFin.TotalMinutes > 0.01) { lastIdxTipo = 0; currRec = new ManualStatusDTO { IdxTipo = lastIdxTipo, CssBlock = "bg-light text-dark", Title = "missing", Value = deltaFin.TotalMinutes, ValueMax = 1440 }; result.Add(currRec); } } } return result; } /// /// Esegue salvataggio record + svuotamento cache /// /// public async Task InsManUpsert(InsManualiModel currRecord) { bool fatto = false; // salvo fatto = dbTabController.InsManUpsert(currRecord); // svuoto cache RedisValue pattern = $"{redisBaseKey}:InsMan:*"; await ExecFlushRedisPatternAsync(pattern); return fatto; } /// /// Esegue salvataggio record + svuotamento cache /// /// public async Task InsManUpsert(List listRecord) { bool fatto = false; // salvo fatto = dbTabController.InsManUpsert(listRecord); // svuoto cache RedisValue pattern = $"{redisBaseKey}:InsMan:*"; await ExecFlushRedisPatternAsync(pattern); return fatto; } /// /// Recupero info IOB x TAB (da info registrate IOB-WIN--> MP-IO) /// /// /// public async Task IobInfoAsync(string IdxMacchina) { string source = "DB"; Stopwatch sw = new Stopwatch(); sw.Start(); IOB_data? result = new IOB_data(); // cerco in _redisConn... string currKey = RedHashMpIO($"hM2IOB:{IdxMacchina}"); RedisValue rawData = await _redisDb.StringGetAsync(currKey); //if (!string.IsNullOrEmpty($"{rawData}")) if (rawData.HasValue) { result = JsonConvert.DeserializeObject($"{rawData}"); source = "REDIS"; } else { Log.Error($"Errore: non trovato valore valido in REDIS | key: {currKey}"); Log.Info($"REDIS | conf: {_redisConn.Configuration}"); Log.Info($" --> Valore trovato:{Environment.NewLine}{rawData}"); } if (result == null) { result = new IOB_data(); Log.Debug($"Init valore default | IdxMacchina: {IdxMacchina}"); } sw.Stop(); Log.Debug($"IobInfoAsync per {IdxMacchina} | {source} | {sw.Elapsed.TotalMilliseconds}ms"); return result; } /// Elenco PODL macchina Macchina Solo disponibili (1) o tutte (0) Gruppo public async Task> ListPODLByMacc(string idxMacchina, bool onlyFree, bool onlyDirect) { string source = "DB"; Stopwatch sw = new Stopwatch(); sw.Start(); List? result = new List(); // cerco in _redisConn... string currKey = $"{redisBaseKey}:PODL:{idxMacchina}:{onlyFree}:{onlyDirect}"; RedisValue rawData = await _redisDb.StringGetAsync(currKey); if (rawData.HasValue) { result = JsonConvert.DeserializeObject>($"{rawData}"); source = "REDIS"; } else { result = await Task.FromResult(dbTabController.ListPODLByMacc(idxMacchina, onlyFree, onlyDirect)); // serializzo e salvo... rawData = JsonConvert.SerializeObject(result); await _redisDb.StringSetAsync(currKey, rawData, UltraFastCache); } if (result == null) { result = new List(); } sw.Stop(); Log.Debug($"ListPODLByMacc | {source} | {sw.Elapsed.TotalMilliseconds}ms"); return result; } /// /// Elenco parametri validi tab/campo /// /// public List ListValuesFilt(string tabName, string fieldName) { string source = "DB"; Stopwatch sw = new Stopwatch(); sw.Start(); List? result = new List(); // cerco in _redisConn... string currKey = $"{redisBaseKey}:ListVal:{tabName}:{fieldName}"; RedisValue rawData = _redisDb.StringGet(currKey); if (rawData.HasValue) { result = JsonConvert.DeserializeObject>($"{rawData}"); source = "REDIS"; } else { result = dbTabController.ListValuesFilt(tabName, fieldName); // serializzo e salvo... rawData = JsonConvert.SerializeObject(result); _redisDb.StringSet(currKey, rawData, UltraLongCache); } if (result == null) { result = new List(); } sw.Stop(); Log.Debug($"ListValuesFilt | {source} | {sw.Elapsed.TotalMilliseconds}ms"); return result; } /// /// Elenco lotti esterni presenti sul db di ARCA /// /// Codice articolo /// Codice lotto /// Codice magazzino /// public async Task> LottoEsterno(string codArt, string codLotto, string codMagazzino) { // setup parametri costanti string source = "DB"; Stopwatch sw = new Stopwatch(); sw.Start(); List result = new List(); // cerco in _redisConn... string currKey = $"{redisBaseKey}:LottoExt:{codMagazzino}:{codArt}:{codLotto}"; RedisValue rawData = await _redisDb.StringGetAsync(currKey); if (rawData.HasValue) { result = JsonConvert.DeserializeObject>($"{rawData}"); source = "REDIS"; } else { result = dbInveController.LottoEsterno(codArt, codLotto, codMagazzino); // serializzo e salvo... rawData = JsonConvert.SerializeObject(result); await _redisDb.StringSetAsync(currKey, rawData, UltraLongCache); } if (result == null) { result = new List(); } sw.Stop(); Log.Debug($"LottoEsterno | {source} | {sw.Elapsed.TotalMilliseconds}ms"); return result; } /// /// Effettua ricalcolo MSE x macchina indicata /// /// idx macchina da confermare /// Abilitazione insert ev macchina /// public bool MacchinaSetInsEnab(string idxMacchina, bool insEnabled) { bool answ = dbTabController.MacchinaSetInsEnab(idxMacchina, insEnabled); return answ; } /// /// Intera tabella relazione master/slave in machine (gestione setup master --> slave) /// /// public async Task> Macchine2Slave() { // setup parametri costanti string source = "DB"; Stopwatch sw = new Stopwatch(); sw.Start(); List result = new List(); // cerco in _redisConn... string currKey = $"{redisBaseKey}:Mach2Slave"; RedisValue rawData = await _redisDb.StringGetAsync(currKey); //if (!string.IsNullOrEmpty($"{rawData}")) if (rawData.HasValue) { result = JsonConvert.DeserializeObject>($"{rawData}"); source = "REDIS"; } else { result = dbTabController.Macchine2Slave(); // serializzo e salvo... rawData = JsonConvert.SerializeObject(result); await _redisDb.StringSetAsync(currKey, rawData, UltraFastCache); } if (result == null) { result = new List(); } sw.Stop(); Log.Debug($"Macchine2Slave | {source} | {sw.Elapsed.TotalMilliseconds}ms"); return result; } /// /// Elenco MacchineModel dato operatore secondo gruppi (macchine/operatore) /// /// /// public async Task> MacchineByMatrOper(int MatrOpr) { int rndWait = rnd.Next(0, 2); await Task.Delay(rndWait); // setup parametri costanti string source = "DB"; Stopwatch sw = new Stopwatch(); sw.Start(); List result = new List(); // cerco in _redisConn... string currKey = $"{redisBaseKey}:MachByMatOp:{MatrOpr}"; RedisValue rawData = _redisDb.StringGet(currKey); //if (!string.IsNullOrEmpty($"{rawData}")) if (rawData.HasValue) { result = JsonConvert.DeserializeObject>($"{rawData}"); source = "REDIS"; } else { result = dbTabController.MacchineByMatrOper(MatrOpr); // serializzo e salvo... rawData = JsonConvert.SerializeObject(result); _redisDb.StringSet(currKey, rawData, UltraLongCache); } if (result == null) { result = new List(); } sw.Stop(); string callName = $"MacchineByMatrOper.{source}"; int numRec = esCollect.RecordCall(callName, sw.Elapsed.TotalMilliseconds); if (numRec >= nRecLog) { Log.Debug(esCollect.GetCallSum(callName, true)); } return result; } /// /// Lista parametri correnti (ObjItemDTO) della macchina /// /// /// public List MachineParamList(string idxMacchina) { // setup parametri costanti string source = "NA"; Stopwatch sw = new Stopwatch(); sw.Start(); List? result = new List(); // cerco in _redisConn... string currKey = RedHashMpIO($"CurrentParameters:{idxMacchina}"); RedisValue rawData = _redisDb.StringGet(currKey); if (rawData.HasValue && rawData.Length() > 2) { var rawVal = JsonConvert.DeserializeObject>($"{rawData}"); // ordino! result = rawVal .OrderBy(x => x.displOrdinal) .ThenBy(x => x.description) .ToList(); source = "REDIS"; } if (result == null) { result = new List(); source = "NONE"; } sw.Stop(); Log.Debug($"CurrParamList | {source} | {sw.Elapsed.TotalMilliseconds}ms"); return result; } /// /// Aggiornamento parametro per macchina /// /// /// UID del parametro macchina come definito in file json /// /// public bool MachineParamUpdate(string idxMacchina, string uid, string reqValue) { bool answ = false; // recupero items... List dcList = MachineParamList(idxMacchina); List list2Update = new List(); // cerco quello da aggiornare var trovato = dcList.Find(obj => obj.uid == uid); // se non trova --> crea ed aggiunge... if (trovato == null) { dcList.Add(new ObjItemDTO() { uid = uid }); trovato = dcList.Find(obj => obj.uid == uid); } // se trovato procedo if (trovato != null) { // aggiorno valore richiesto + dt richiesta trovato.reqValue = reqValue; trovato.lastRequest = DateTime.Now; list2Update.Add(trovato); MachineParamUpsert(idxMacchina, list2Update); // accodo in task 2 exe la richiesta di processing addTask4Machine(idxMacchina, Enums.taskType.setParameter, trovato.uid); // salvo ANCHE il valore di setup ASSOCIATO... System.Enum.TryParse(trovato.uid, out Enums.taskType currTask); //taskType currTask = (taskType)System.Enum.Parse(typeof(taskType), trovato.uid); addTask4Machine(idxMacchina, currTask, reqValue); answ = true; } return answ; } /// /// Effettua UPSERT elenco parametri correnti x IOB (se c'è UPDATE, se manca ADD) /// /// /// /// public bool MachineParamUpsert(string idxMacchina, List innovations) { bool answ = false; if (innovations != null) { Log.Info($"upsertCurrObjItems | idxMacchina: {idxMacchina} | {innovations.Count} innovations"); // leggo i valori attuali... List actValues = MachineParamList(idxMacchina); // per ogni valore passatomi faccio insert o update rispetto elenco valori correnti // in REDIS foreach (var item in actValues) { // cerco nelle innovazioni SE CI SIA il valore... var trovato = innovations.Find(obj => obj.uid == item.uid); // se non trovato nelle innovazioni... if (trovato == null) { // lo ri-aggiungo x non perderlo innovations.Add(item); Log.Trace($"innovations | add | item.uid: {item.uid} | item.value: {item.value}"); } // altrimenti aggiorno campo (non trasmesso) name e tengo il resto... else { trovato.name = item.name; Log.Info($"innovations | update | item.uid: {item.uid} | item.value: {item.value} --> {trovato.value} "); } } // serializzo e salvo string serVal = JsonConvert.SerializeObject(innovations); string currKey = RedHashMpIO($"CurrentParameters:{idxMacchina}"); RedisValue rawData = _redisDb.StringSet(currKey, serVal); } return answ; } /// /// Restitusice elenco KVP dei TASK SALVATI (da passare a IOB-WIN) per l'impianto indicato /// /// /// s /// public Dictionary mSavedTaskMacchina(string idxMacchina) { // hard coded dimensione vettore DatiMacchine Dictionary answ = new Dictionary(); // ORA recupero da memoria _redisConn... try { var currKey = (RedisKey)savedTaskHash(idxMacchina); answ = redisHashDictGet(currKey); } catch (Exception exc) { Log.Info($"Errore in recupero dati SAVED TASK x Redis mSavedTaskMacchina | idxMacchina {idxMacchina}{Environment.NewLine}{exc}"); } return answ; } /// /// Recupera un valore MSE x una macchina sub specifica /// /// /// /// /// public MappaStatoExplModel MseGetSub(string idxMacc, string idxMacchSub, bool forceDb) { Stopwatch stopWatch = new Stopwatch(); stopWatch.Start(); MappaStatoExplModel result = new MappaStatoExplModel(); // cerco in _redisConn... string currKey = $"{Constants.redisMseKeySingle}:{idxMacchSub}"; RedisValue rawData = _redisDb.StringGet(currKey); if (rawData.HasValue && !forceDb) { result = JsonConvert.DeserializeObject($"{rawData}"); stopWatch.Stop(); TimeSpan ts = stopWatch.Elapsed; Log.Debug($"Read from REDIS: {ts.TotalMilliseconds}ms"); } else { var rawResult = dbTabController.MseGetSub(idxMacc, idxMacchSub); if (rawResult != null && rawResult.Count > 0) { result = rawResult.FirstOrDefault(); } // serializzo e salvo... rawData = JsonConvert.SerializeObject(result); _redisDb.StringSet(currKey, rawData, UltraFastCache); stopWatch.Stop(); TimeSpan ts = stopWatch.Elapsed; Log.Debug($"Read from DB: {ts.TotalMilliseconds}ms"); } if (result == null) { result = new MappaStatoExplModel(); } return result; } /// /// Invio notifica dati invalidati x impianto /// /// public void NotifyDataInvalidated(string idxMacchina) { if (DataInvalidated != null) { // messaggio ReloadEventArgs rea = new ReloadEventArgs(idxMacchina); DataInvalidated.Invoke(this, rea); } } /// /// Invio notifica rilettura (con parametro) /// /// public void NotifyReloadRequest(string message) { if (ReloadRequest != null) { // messaggio ReloadEventArgs rea = new ReloadEventArgs(message); ReloadRequest.Invoke(this, rea); } } /// /// ODL da key /// /// /// /// public async Task OdlByIdx(int idxOdl, bool onlyUnused) { int rndWait = rnd.Next(0, 3); await Task.Delay(rndWait); string source = "DB"; Stopwatch sw = new Stopwatch(); sw.Start(); ODLExpModel result = new ODLExpModel(); // cerco in _redisConn... string currKey = $"{redisBaseKey}:ODL:{idxOdl}:{onlyUnused}"; RedisValue rawData = _redisDb.StringGet(currKey); #if false RedisValue rawData = await redisDb.StringGetAsync(currKey); #endif if (rawData.HasValue) { result = JsonConvert.DeserializeObject($"{rawData}"); source = "REDIS"; } else { var listRes = dbTabController.OdlByIdx(idxOdl, onlyUnused); #if false var listRes = await Task.FromResult(dbTabController.OdlByIdx(idxOdl, onlyUnused)); #endif result = listRes.FirstOrDefault(); // serializzo e salvo... rawData = JsonConvert.SerializeObject(result); _redisDb.StringSet(currKey, rawData, FastCache); #if false await redisDb.StringSetAsync(currKey, rawData, FastCache); #endif } if (result == null) { result = new ODLExpModel(); } sw.Stop(); #if false Log.Debug($"OdlByIdx | {idxOdl} | {source} | {sw.Elapsed.TotalMilliseconds}ms"); #endif string callName = $"OdlByIdx.{source}"; int numRec = esCollect.RecordCall(callName, sw.Elapsed.TotalMilliseconds); if (numRec >= nRecLog) { Log.Debug(esCollect.GetCallSum(callName, true)); } return result; } /// /// Clear operazione setup ODL (annullamento) /// /// /// /// public async Task OdlClearSetup(int idxODL, string idxMacchina) { bool answ = false; try { // inserisco evento answ = dbTabController.OdlClearSetup(idxODL, idxMacchina); await FlushOdlCache(); } catch (Exception exc) { string logMsg = $"Eccezione in OdlUpdate | idxODL: {idxODL} | idxMacchina: {idxMacchina}{Environment.NewLine}{exc}"; Log.Error(logMsg); } return answ; } /// /// ODL corrente macchina /// /// /// public async Task OdlCurrByMacc(string idxMacchina, bool forceDb) { // pausa random x evitare sovrapposizioni... int rndWait = rnd.Next(0, 3); await Task.Delay(rndWait); string source = "DB"; Stopwatch sw = new Stopwatch(); sw.Start(); ODLExpModel result = new ODLExpModel(); // se vuoto esco subito... if (!string.IsNullOrEmpty(idxMacchina)) { // cerco in _redisConn... string currKey = $"{redisBaseKey}:ODL:{idxMacchina}:CURR"; RedisValue rawData = _redisDb.StringGet(currKey); #if false RedisValue rawData = await redisDb.StringGetAsync(currKey); #endif if (rawData.HasValue && !forceDb) { result = JsonConvert.DeserializeObject($"{rawData}"); source = "REDIS"; } else { var listRes = dbTabController.OdlCurrByMacc(idxMacchina); #if false var listRes = await Task.FromResult(dbTabController.OdlCurrByMacc(idxMacchina)); #endif result = listRes.FirstOrDefault(); // serializzo e salvo... rawData = JsonConvert.SerializeObject(result); _redisDb.StringSet(currKey, rawData, FastCache); #if false await redisDb.StringSetAsync(currKey, rawData, FastCache); #endif } if (result == null) { result = new ODLExpModel(); } sw.Stop(); #if false Log.Debug($"OdlCurrByMacc | {source} | {idxMacchina} | {sw.Elapsed.TotalMilliseconds}ms"); #endif string callName = $"OdlCurrByMaccAsync.{source}"; int numRec = esCollect.RecordCall(callName, sw.Elapsed.TotalMilliseconds); if (numRec >= nRecLog) { Log.Debug(esCollect.GetCallSum(callName, true)); } } else { Log.Trace("idxMacchina vuoto!"); } return result; } /// /// Attrezzo stesso ODL dell'altra tavola /// /// /// /// /// public async Task OdlDividiDaAltraTavola(int idxODL, int matrOpr, string idxMacchinaTo) { bool answ = false; try { // inserisco evento answ = dbTabController.OdlDividiDaAltraTavola(idxODL, matrOpr, idxMacchinaTo); await FlushOdlCache(); } catch (Exception exc) { string logMsg = $"Eccezione in OdlDividiDaAltraTavola | idxODL: {idxODL} | matrOpr: {matrOpr} | idxMacchinaTo: {idxMacchinaTo}{Environment.NewLine}{exc}"; Log.Error(logMsg); } return answ; } /// /// Registro fine prod ODL /// /// /// /// /// public async Task OdlFineProd(int idxODL, string idxMacchina, DateTime dtRif) { bool answ = false; try { // inserisco evento answ = dbTabController.OdlFineProd(idxODL, idxMacchina, dtRif); await FlushOdlCache(); } catch (Exception exc) { string logMsg = $"Eccezione in OdlFineProd | idxODL: {idxODL} | idxMacchina: {idxMacchina} | dtRif: {dtRif}{Environment.NewLine}{exc}"; Log.Error(logMsg); } return answ; } /// /// Fix ODL per macchine SLAVE /// /// /// /// /// public async Task OdlFixMachineSlave(string idxMacchina, int numDayPrev, int doInsert) { bool answ = false; try { // inserisco evento answ = dbTabController.OdlFixMachineSlave(idxMacchina, numDayPrev, doInsert); await FlushOdlCache(); } catch (Exception exc) { string logMsg = $"Eccezione in ODLfixMachineSlave | idxMacchina: {idxMacchina} | numDayPrev: {numDayPrev} | doInsert: {doInsert}{Environment.NewLine}{exc}"; Log.Error(logMsg); } return answ; } /// /// Setup PODL Postumo /// /// /// /// /// /// /// /// public async Task OdlInizioSetup(int idxODL, int matrOpr, string idxMacchina, decimal tcRich, int pzPallet, string note) { bool answ = false; try { // inserisco evento answ = dbTabController.OdlInizioSetup(idxODL, matrOpr, idxMacchina, tcRich, pzPallet, note); await FlushOdlCache(); } catch (Exception exc) { string logMsg = $"Eccezione in OdlInizioSetup | matrOpr: {matrOpr} | idxODL: {idxODL} | idxMacchina: {idxMacchina}{Environment.NewLine}{exc}"; Log.Error(logMsg); } return answ; } /// /// Ultimo ODL data macchina /// /// /// /// public ODLModel OdlLastByMacc(string idxMacchina, bool forceDb) { string source = "DB"; Stopwatch sw = new Stopwatch(); sw.Start(); ODLModel result = new ODLModel(); // cerco in _redisConn... string currKey = $"{redisBaseKey}:ODL:{idxMacchina}:LAST"; RedisValue rawData = _redisDb.StringGet(currKey); if (rawData.HasValue && !forceDb) { result = JsonConvert.DeserializeObject($"{rawData}"); source = "REDIS"; } else { var results = dbTabController.OdlLastByMacc(idxMacchina); // riordino result = results.FirstOrDefault(); // serializzo e salvo... rawData = JsonConvert.SerializeObject(result); _redisDb.StringSet(currKey, rawData, UltraLongCache); } if (result == null) { result = new ODLModel(); } sw.Stop(); Log.Debug($"OdlLastByMacc | {source} | {sw.Elapsed.TotalMilliseconds}ms"); return result; } /// /// Elenco ODL data macchina e periodo /// /// /// /// /// public async Task> OdlListByMaccPeriodo(string idxMacchina, DateTime dtStart, DateTime dtEnd) { string source = "DB"; Stopwatch sw = new Stopwatch(); sw.Start(); List? result = new List(); // cerco in _redisConn... string currKey = $"{redisBaseKey}:ODL:{idxMacchina}:{dtStart:yyyyMMdd-HHmmss}:{dtEnd:yyyyMMdd-HHmmss}"; RedisValue rawData = await _redisDb.StringGetAsync(currKey); if (rawData.HasValue) { result = JsonConvert.DeserializeObject>($"{rawData}"); source = "REDIS"; } else { result = dbTabController.OdlListByMaccPeriodo(idxMacchina, dtStart, dtEnd); // riordino result = result.OrderByDescending(x => x.DataInizio).ToList(); // serializzo e salvo... rawData = JsonConvert.SerializeObject(result); await _redisDb.StringSetAsync(currKey, rawData, FastCache); } if (result == null) { result = new List(); } sw.Stop(); Log.Debug($"OdlListByMaccPeriodo | {source} | {sw.Elapsed.TotalMilliseconds}ms"); return result; } /// /// Riapertura ULTIMO ODL data macchina /// /// /// public async Task OdlReopenOdlMacc(string idxMacchina) { string source = "DB"; Stopwatch sw = new Stopwatch(); sw.Start(); ODLModel result = new ODLModel(); // cerco in _redisConn... string currKey = $"{redisBaseKey}:ODL:{idxMacchina}:LAST"; var results = await Task.FromResult(dbTabController.OdlReopenOdlMacc(idxMacchina)); // riordino result = results.FirstOrDefault(); // svuoto cache await FlushOdlCache(); if (result == null) { result = new ODLModel(); } sw.Stop(); Log.Debug($"OdlReopenOdlMacc | {source} | {sw.Elapsed.TotalMilliseconds}ms"); return result; } /// /// Setup ODL Postumo /// /// /// /// public async Task OdlSetupPostumo(int idxODL, string idxMacchina) { bool answ = false; try { // inserisco evento answ = await Task.FromResult(dbTabController.OdlSetupPostumo(idxODL, idxMacchina)); await FlushOdlCache(); } catch (Exception exc) { string logMsg = $"Eccezione in OdlSetupPostumo | macchina: {idxMacchina} | idxODL: {idxODL}{Environment.NewLine}{exc}"; Log.Error(logMsg); } return answ; } /// /// Setup ODL Postumo /// /// /// /// /// public async Task OdlSetupPromPostuma(int idxPromOdl, int matrOpr, string idxMacchina) { bool answ = false; try { // inserisco evento answ = await Task.FromResult(dbTabController.OdlSetupPromPostuma(idxPromOdl, matrOpr, idxMacchina)); await FlushOdlCache(); } catch (Exception exc) { string logMsg = $"Eccezione in OdlSetupPromPostuma | macchina: {idxMacchina} | idxPromOdl: {idxPromOdl} | MatrOpr: {matrOpr}{Environment.NewLine}{exc}"; Log.Error(logMsg); } return answ; } /// /// Split ODL /// /// /// /// /// /// /// /// /// /// public async Task OdlSplit(int idxODL, int matrOpr, string idxMacchina, decimal TCRich, int pzPallet, string note, bool startNewOdl, int qtyRich) { bool answ = false; try { // inserisco evento answ = await Task.FromResult(dbTabController.OdlSplit(idxODL, matrOpr, idxMacchina, TCRich, pzPallet, note, startNewOdl, qtyRich)); await FlushOdlCache(); } catch (Exception exc) { string logMsg = $"Eccezione in OdlSplit | macchina: {idxMacchina} | idxODL: {idxODL}{Environment.NewLine}{exc}"; Log.Error(logMsg); } return answ; } /// /// Update ODL (es: in setup x chiusura attrezzaggio) /// /// /// /// /// /// /// public async Task OdlUpdate(int idxODL, int matrOpr, decimal tCRichAttr, int pzPallet, string note) { bool answ = false; try { // inserisco evento answ = dbTabController.OdlUpdate(idxODL, matrOpr, tCRichAttr, pzPallet, note); await FlushOdlCache(); } catch (Exception exc) { string logMsg = $"Eccezione in OdlUpdate | idxODL: {idxODL} | matrOpr: {matrOpr} | tCRichAttr: {tCRichAttr} | pzPallet: {pzPallet} | note: {note}{Environment.NewLine}{exc}"; Log.Error(logMsg); } return answ; } /// /// Delete dell'oggetto opr serializzato /// /// /// public async Task OperatoreDeleteRedis(int matrOpr, Guid DevGuid) { string source = "REDIS"; Stopwatch sw = new Stopwatch(); sw.Start(); bool answ = false; // cerco in _redisConn... string currKey = $"{redisUserDataKey}:CurrOpr:{matrOpr}:CurrDevGuid:{DevGuid}"; RedisValue rawData = await _redisDb.StringGetAsync(currKey); if (rawData.HasValue) { var done = await ExecFlushRedisPatternAsync(currKey); if (done) { answ = true; } } sw.Stop(); Log.Debug($"OperatoreDeleteRedis | {source} | {sw.Elapsed.TotalMilliseconds}ms"); await Task.Delay(1); return answ; } /// /// Legge l'oggetto operatore+device loggato e restituisce la sua TTL /// /// /// /// public TimeSpan OperatoreGetGuidTTL(int matrOpr, Guid currDevGuid) { TimeSpan answ = new TimeSpan(); // cerco in _redisConn... string currKey = $"{redisUserDataKey}:CurrOpr:{matrOpr}:CurrDevGuid:{currDevGuid}"; answ = GetKeyTTL(currKey); return answ; } /// /// Legge l'oggetto operatore loggato /// /// /// public async Task OperatoreGetRedis(int matrOpr, Guid currDevGuid) { string source = "REDIS"; Stopwatch sw = new Stopwatch(); sw.Start(); string answ = ""; // cerco in _redisConn... string currKey = $"{redisUserDataKey}:CurrOpr:{matrOpr}:CurrDevGuid:{currDevGuid}"; RedisValue rawData = await _redisDb.StringGetAsync(currKey); if (rawData.HasValue) { answ = rawData; } if (answ == null) { answ = ""; } sw.Stop(); Log.Debug($"OperatoreGetRedis | {source} | {sw.Elapsed.TotalMilliseconds}ms"); await Task.Delay(1); return answ; } /// /// Log in operatore /// /// matricola operatore /// Auth Key /// public async Task OperatoreSearch(int matrOpr, string authKey) { string source = "DB"; Stopwatch sw = new Stopwatch(); sw.Start(); AnagOperatoriModel answ = null; answ = dbTabController.OperatoreSearch(matrOpr, authKey); if (answ == null) { answ = new AnagOperatoriModel(); } sw.Stop(); Log.Debug($"LoginOperatore | {source} | {sw.Elapsed.TotalMilliseconds}ms"); await Task.Delay(1); return answ; } /// /// legge l'hash dell'oggetto curr opr /// /// /// public async Task OperatoreSetRedis(int matrOpr, string currOpr, Guid currDevGuid) { setExpDays(); string source = "REDIS"; Stopwatch sw = new Stopwatch(); sw.Start(); string answ = ""; // cerco in _redisConn... string currKey = $"{redisUserDataKey}:CurrOpr:{matrOpr}:CurrDevGuid:{currDevGuid}"; //RedisValue rawData = await _redisDb.StringGetAsync(currKey); // serializzo e salvo... //rawData = JsonConvert.SerializeObject(currOpr); answ = currOpr; //var encrData = SteamCrypto.EncryptString(rawData, passPhrase); await _redisDb.StringSetAsync(currKey, currOpr, ConfigCache); if (answ == null) { answ = ""; } sw.Stop(); Log.Debug($"OperatoreSetRedis | {source} | {sw.Elapsed.TotalMilliseconds}ms"); await Task.Delay(1); return answ; } /// /// Stato prod macchina /// /// /// public async Task> PezziProdMacchina(string idxMacchina) { // setup parametri costanti string source = "DB"; Stopwatch sw = new Stopwatch(); sw.Start(); List result = new List(); // cerco in _redisConn... string currKey = $"{redisBaseKey}:PzProd:{idxMacchina}"; RedisValue rawData = await _redisDb.StringGetAsync(currKey); if (rawData.HasValue) { result = JsonConvert.DeserializeObject>($"{rawData}"); source = "REDIS"; } else { result = dbTabController.PezziProdMacchina(idxMacchina); // serializzo e salvo... rawData = JsonConvert.SerializeObject(result); await _redisDb.StringSetAsync(currKey, rawData, UltraFastCache); } if (result == null) { result = new List(); } sw.Stop(); Log.Debug($"PezziProdMacchina | {source} | {sw.Elapsed.TotalMilliseconds}ms"); return result; } /// /// Avvio setup ODL da PODL /// /// /// /// /// /// /// public async Task PODL_startSetup(PODLExpModel editRec, int matrOpr, decimal tcRich, int pzPallet, string note, DateTime dtEvent) { bool answ = false; try { // inserisco evento answ = dbTabController.PODL_startSetup(editRec, matrOpr, tcRich, pzPallet, note, dtEvent); await FlushOdlCache(); } catch (Exception exc) { string logMsg = $"Eccezione in PODL_startSetup | matrOpr: {matrOpr} | idxPODL: {editRec.IdxPromessa}{Environment.NewLine}{exc}"; Log.Error(logMsg); } return answ; } /// /// Recupero PODL da chiave /// /// /// public async Task PODLExp_getByKey(int idxPODL) { string source = "DB"; // pausa random x evitare sovrapposizioni... int rndWait = rnd.Next(0, 3); await Task.Delay(rndWait); Stopwatch sw = new Stopwatch(); sw.Start(); PODLExpModel result = new PODLExpModel(); // cerco in _redisConn... string currKey = $"{redisBaseKey}:PODL:{idxPODL}"; RedisValue rawData; rawData = _redisDb.StringGet(currKey); #if false if (doSync) { rawData = redisDb.StringGet(currKey); } else { rawData = await redisDb.StringGetAsync(currKey); } #endif if (rawData.HasValue) { result = JsonConvert.DeserializeObject($"{rawData}"); source = "REDIS"; } else { result = dbTabController.PODLExp_getByKey(idxPODL); // serializzo e salvo... rawData = JsonConvert.SerializeObject(result); _redisDb.StringSet(currKey, rawData, FastCache); #if false if (doSync) { result = dbTabController.PODLExp_getByKey(idxPODL); } else { result = await dbTabController.PODLExp_getByKeyAsync(idxPODL); } //result = await Task.FromResult(dbTabController.PODLExp_getByKey(idxPODL)); // serializzo e salvo... rawData = JsonConvert.SerializeObject(result); if (doSync) { redisDb.StringSet(currKey, rawData, FastCache); } else { await redisDb.StringSetAsync(currKey, rawData, FastCache); } #endif } if (result == null) { result = new PODLExpModel(); } sw.Stop(); #if false Log.Debug($"PODL_getByKey | {idxPODL} | {source} | {sw.Elapsed.TotalMilliseconds}ms"); #endif string callName = $"PODL_getByKey.{source}"; int numRec = esCollect.RecordCall(callName, sw.Elapsed.TotalMilliseconds); if (numRec >= nRecLog) { Log.Debug(esCollect.GetCallSum(callName, true)); } return result; } /// /// Elenco PODL in un istanza KIT dall'ID del parent /// /// IDX PODL parent /// public List POdlListByKitParent(int IdxPodlParent) { List? result = new List(); Stopwatch stopWatch = new Stopwatch(); stopWatch.Start(); string readType = "DB"; string currKey = $"{MP.Core.Utils.redisPOdlList}_kit:ByParent:{IdxPodlParent}"; // cerco in _redisConn dato valore sel idxMaccSel... RedisValue rawData = _redisDb.StringGet(currKey); if (rawData.HasValue) { result = JsonConvert.DeserializeObject>($"{rawData}"); readType = "REDIS"; } else { result = dbTabController.ListPODL_ByKitParent(IdxPodlParent); // serializzo e salvo... rawData = JsonConvert.SerializeObject(result); _redisDb.StringSet(currKey, rawData, LongCache); } if (result == null) { result = new List(); } stopWatch.Stop(); TimeSpan ts = stopWatch.Elapsed; Log.Debug($"POdlListByKitParent | Read from {readType}: {ts.TotalMilliseconds}ms"); return result; } /// /// Restituisce il contapezzi salvato per la macchina /// /// /// public async Task pzCounter(string idxMacchina) { int answ = -1; string rCall = ""; saveCallRec("getCounter"); try { rCall = _redisDb.StringGet(redHash($"PzCount:{idxMacchina}")); if (rCall != "" && rCall != null) { int.TryParse(rCall, out answ); } else { answ = await pzCounterTC(idxMacchina); // salvo in _redisConn... await saveCounter(idxMacchina, answ.ToString()); } } catch (Exception exc) { Log.Error($"Eccezione in pzCounter{Environment.NewLine}{exc}"); } return answ; } /// /// Restituisce il contapezzi come CONTEGGIO da TCRilevati per la macchina /// /// /// public async Task pzCounterTC(string idxMacchina) { int answ = -1; saveCallRec("getCounterTC"); DateTime dataRif = DateTime.Now; var datiProd = await StatoProdMacchinaAsync(idxMacchina, dataRif); if (datiProd != null) { answ = datiProd.PzTotODL; } return answ; } /// /// Restituisce elenco RC filtrato /// /// /// /// /// /// public async Task> RegControlliFiltAsync(string idxMacchina, int idxODL, DateTime dataFrom, DateTime dataTo, bool showMulti) { int rndWait = rnd.Next(0, 2); await Task.Delay(rndWait); // setup parametri costanti string source = "DB"; Stopwatch sw = new Stopwatch(); sw.Start(); List? result = new List(); // cerco in _redisConn... string currKey = $"{redisBaseKey}:RecContr:{idxMacchina}:{idxODL}:{dataFrom:yyyyyMMdd-HHmm}:{dataFrom:yyyyyMMdd-HHmm}:{showMulti}"; #if false RedisValue rawData = redisDb.StringGet(currKey); #endif RedisValue rawData = await _redisDb.StringGetAsync(currKey); if (rawData.HasValue) { result = JsonConvert.DeserializeObject>($"{rawData}"); source = "REDIS"; } else { result = dbTabController.RegControlliFilt(idxMacchina, idxODL, dataFrom, dataTo, showMulti); // serializzo e salvo... rawData = JsonConvert.SerializeObject(result); #if false redisDb.StringSet(currKey, rawData, UltraLongCache); #endif await _redisDb.StringSetAsync(currKey, rawData, UltraLongCache); } if (result == null) { result = new List(); } sw.Stop(); #if false Log.Debug($"RegControlliFiltAsync | {source} | {sw.Elapsed.TotalMilliseconds}ms"); #endif string callName = $"RegControlliFiltAsync.{source}"; int numRec = esCollect.RecordCall(callName, sw.Elapsed.TotalMilliseconds); if (numRec >= nRecLog) { Log.Debug(esCollect.GetCallSum(callName, true)); } return result; } /// /// Registra controllo /// /// /// /// /// /// /// public async Task RegControlliInsert(string idxMacchina, int matrOpr, bool esitoOk, string note, DateTime dataOra) { bool answ = false; try { // inserisco evento answ = dbTabController.RegControlliInsert(idxMacchina, matrOpr, esitoOk, note, dataOra); await FlushCache("RecContr"); } catch (Exception exc) { string logMsg = $"Eccezione in RegControlliInsertAsync | macchina: {idxMacchina} | DataOra: {dataOra} | MatrOpr: {matrOpr} | Qta {esitoOk} | Note: {note}{Environment.NewLine}{exc}"; Log.Error(logMsg); } return answ; } /// /// Restituisce elenco ULTIMI RC x macchina /// /// /// public async Task> RegControlliLast(string idxMacchina) { int rndWait = rnd.Next(0, 2); await Task.Delay(rndWait); // setup parametri costanti string source = "DB"; Stopwatch sw = new Stopwatch(); sw.Start(); List? result = new List(); // cerco in _redisConn... string currKey = $"{redisBaseKey}:RecContr:{idxMacchina}:LAST"; RedisValue rawData = _redisDb.StringGet(currKey); #if false RedisValue rawData = await redisDb.StringGetAsync(currKey); #endif if (rawData.HasValue) { result = JsonConvert.DeserializeObject>($"{rawData}"); source = "REDIS"; } else { result = dbTabController.RegControlliLast(idxMacchina); // serializzo e salvo... rawData = JsonConvert.SerializeObject(result); #if false await redisDb.StringSetAsync(currKey, rawData, UltraLongCache); #endif _redisDb.StringSet(currKey, rawData, UltraLongCache); } if (result == null) { result = new List(); } sw.Stop(); #if false Log.Debug($"RegControlliLast | {source} | {sw.Elapsed.TotalMilliseconds}ms"); #endif string callName = $"RegControlliLast.{source}"; int numRec = esCollect.RecordCall(callName, sw.Elapsed.TotalMilliseconds); if (numRec >= nRecLog) { Log.Debug(esCollect.GetCallSum(callName, true)); } return result; } /// /// Aggiunta record RegistroScarti /// /// /// /// /// /// /// public async Task> RegDichiarGetFilt(string idxMacchina, string tagCode, int matrOpr, int idxODL, DateTime dataFrom, DateTime dataTo) { // setup parametri costanti string source = "DB"; Stopwatch sw = new Stopwatch(); sw.Start(); List? result = new List(); // cerco in _redisConn... string currKey = $"{redisBaseKey}:RegDichiar:{idxMacchina}:{tagCode}:{matrOpr}:{idxODL}:{dataFrom:yyyyyMMdd-HHmm}:{dataTo:yyyyyMMdd-HHmm}"; RedisValue rawData = await _redisDb.StringGetAsync(currKey); if (rawData.HasValue) { result = JsonConvert.DeserializeObject>($"{rawData}"); source = "REDIS"; } else { result = dbTabController.RegDichiarGetFilt(idxMacchina, tagCode, matrOpr, idxODL, dataFrom, dataTo); // serializzo e salvo... rawData = JsonConvert.SerializeObject(result); await _redisDb.StringSetAsync(currKey, rawData, UltraLongCache); } if (result == null) { result = new List(); } sw.Stop(); Log.Debug($"RegDichiarGetFilt | {source} | {sw.Elapsed.TotalMilliseconds}ms"); return result; } /// /// Aggiunta record Registro Dichiarazioni /// /// /// public async Task RegDichiarInsert(RegistroDichiarazioniModel newRec) { bool answ = false; try { // inserisco evento answ = await dbTabController.RegDichiarInsert(newRec); // reset cache eventi/commenti await FlushCache("RegDichiar"); } catch (Exception exc) { string logMsg = $"Eccezione in RegDichiarInsertAsync | macchina: {newRec.IdxMacchina} | DtRec: {newRec.DtRec} | TagCode: {newRec.TagCode} | MatrOpr: {newRec.MatrOpr} | ValString {newRec.ValString}{Environment.NewLine}{exc}"; Log.Error(logMsg); } return answ; } /// /// Aggiunta record Registro Dichiarazioni /// /// /// public async Task RegDichiarUpdate(RegistroDichiarazioniModel newRec) { bool answ = false; try { // inserisco evento answ = await dbTabController.RegDichiarUpdate(newRec); // reset cache eventi/commenti await FlushCache("RegDichiar"); } catch (Exception exc) { string logMsg = $"Eccezione in RegDichiarUpdateAsync | macchina: {newRec.IdxMacchina} | DtRec: {newRec.DtRec} | TagCode: {newRec.TagCode} | MatrOpr: {newRec.MatrOpr} | ValString {newRec.ValString}{Environment.NewLine}{exc}"; Log.Error(logMsg); } return answ; } /// /// Restituisce elenco RS filtrato /// /// /// /// /// /// /// public async Task> RegScartiGetFilt(string idxMacchina, int idxODL, DateTime dataFrom, DateTime dataTo, bool showMulti) { // setup parametri costanti string source = "DB"; Stopwatch sw = new Stopwatch(); sw.Start(); List? result = new List(); // cerco in _redisConn... string currKey = $"{redisBaseKey}:RegScarti:{idxMacchina}:{idxODL}:{dataFrom:yyyyyMMdd-HHmm}:{dataTo:yyyyyMMdd-HHmm}:{showMulti}"; RedisValue rawData = await _redisDb.StringGetAsync(currKey); if (rawData.HasValue) { result = JsonConvert.DeserializeObject>($"{rawData}"); source = "REDIS"; } else { result = dbTabController.RegScartiGetFilt(idxMacchina, idxODL, dataFrom, dataTo, showMulti); // serializzo e salvo... rawData = JsonConvert.SerializeObject(result); await _redisDb.StringSetAsync(currKey, rawData, LongCache); } if (result == null) { result = new List(); } sw.Stop(); Log.Debug($"RegScartiGetFilt | {source} | {sw.Elapsed.TotalMilliseconds}ms"); return result; } /// /// Aggiunta record RegistroScarti /// /// /// public async Task RegScartiInsert(RegistroScartiModel newRec) { bool answ = false; try { // inserisco evento answ = dbTabController.RegScartiInsert(newRec); // reset cache eventi/commenti await FlushCache("RegScarti"); await FlushCache("RegScartiKit"); } catch (Exception exc) { string logMsg = $"Eccezione in RegScartiInsertAsync | macchina: {newRec.IdxMacchina} | DataOra: {newRec.DataOra} | Causale: {newRec.Causale} | MatrOpr: {newRec.MatrOpr} | Qta {newRec.Qta} | Note: {newRec.Note}{Environment.NewLine}{exc}"; Log.Error(logMsg); } return answ; } /// /// Elimina elenco RSK da parent /// /// /// public async Task RegScartiKitDelete(RegistroScartiModel ParentRec) { bool answ = false; try { // inserisco evento answ = dbTabController.RegScartiKitDelete(ParentRec); // reset cache eventi/commenti await FlushCache("RegScarti"); await FlushCache("RegScartiKit"); } catch (Exception exc) { string logMsg = $"Eccezione in RegScartiKitDelete | macchina: {ParentRec.IdxMacchina} | DataOra: {ParentRec.DataOra} | Causale: {ParentRec.Causale} | MatrOpr: {ParentRec.MatrOpr} | Qta {ParentRec.Qta} | Note: {ParentRec.Note}{Environment.NewLine}{exc}"; Log.Error(logMsg); } return answ; } /// /// Restituisce elenco RSK filtrato x parent /// /// /// public async Task> RegScartiKitGetFilt(RegistroScartiModel ParentRec) { // setup parametri costanti string source = "DB"; Stopwatch sw = new Stopwatch(); sw.Start(); List? result = new List(); // cerco in _redisConn... string currKey = $"{redisBaseKey}:RegScartiKit:{ParentRec.IdxMacchina}:{ParentRec.DataOra:yyyyyMMdd-HHmm}:{ParentRec.Causale}"; RedisValue rawData = await _redisDb.StringGetAsync(currKey); if (rawData.HasValue) { result = JsonConvert.DeserializeObject>($"{rawData}"); source = "REDIS"; } else { result = dbTabController.RegScartiKitGetFilt(ParentRec); // serializzo e salvo... rawData = JsonConvert.SerializeObject(result); await _redisDb.StringSetAsync(currKey, rawData, FastCache); } if (result == null) { result = new List(); } sw.Stop(); Log.Debug($"RegScartiKitGetFilt | {source} | {sw.Elapsed.TotalMilliseconds}ms"); return result; } /// /// Split record RegistroScarti --> RegistroScartiKit /// /// /// public async Task RegScartiKitSplit(RegistroScartiModel newRec) { bool answ = false; try { // inserisco evento answ = await dbTabController.RegScartiKitSplit(newRec); // reset cache eventi/commenti await FlushCache("RegScarti"); await FlushCache("RegScartiKit"); } catch (Exception exc) { string logMsg = $"Eccezione in RegScartiKitSplit | macchina: {newRec.IdxMacchina} | DataOra: {newRec.DataOra} | Causale: {newRec.Causale} | MatrOpr: {newRec.MatrOpr} | Qta {newRec.Qta} | Note: {newRec.Note}{Environment.NewLine}{exc}"; Log.Error(logMsg); } return answ; } /// /// Update qty record singolo articolo di un KIT Scarti /// /// /// public async Task RegScartiKitUpdateQty(RegistroScartiKitModel editRec) { bool answ = false; try { // aggiorno record answ = dbTabController.RegScartiKitUpdateQty(editRec); // reset cache eventi/commenti await FlushCache("RegScarti"); await FlushCache("RegScartiKit"); } catch (Exception exc) { string logMsg = $"Eccezione in RegScartiKitUpdateQty | macchina: {editRec.IdxMacchina} | DataOra: {editRec.DataOra} | Causale: {editRec.Causale} | MatrOpr: {editRec.MatrOpr} | Qta {editRec.Qta} | Note: {editRec.Note}{Environment.NewLine}{exc}"; Log.Error(logMsg); } return answ; } /// /// Resetta (rileggendo) i dati della macchina /// /// /// public async Task> ResetDatiMacchinaAsync(string idxMacchina) { Dictionary answ = new Dictionary(); // verifico il timeout che cambia a seconda che sia vero o falso insEnabled... int tOutShort = 0; int tOutLong = 0; ConfigGetVal("TmOut.MS.S", ref tOutShort); ConfigGetVal("TmOut.MS.L", ref tOutLong); int redDtMacTOut = tOutLong; // inizio con un bel reset... string currKey = $"{redisBaseKey}:MSFD"; await FlushCache(currKey); var rigaMSFD = await VMSFDGetByMaccAsync(idxMacchina); if (rigaMSFD != null) { // salvo 1:1 i valori... STATO answ.Add("IdxMicroStato", $"{rigaMSFD.IdxMicroStato}"); answ.Add("IdxStato", $"{rigaMSFD.IdxStato}"); answ.Add("CodArticolo", $"{rigaMSFD.CodArticolo}"); answ.Add("insEnabled", $"{rigaMSFD.InsEnabled}"); answ.Add("sLogEnabled", $"{rigaMSFD.SLogEnabled}"); answ.Add("pallet", $"{rigaMSFD.Pallet}"); answ.Add("CodArticolo_A", $"{rigaMSFD.CodArticoloA}"); answ.Add("CodArticolo_B", $"{rigaMSFD.CodArticoloB}"); answ.Add("TempoCicloBase", $"{rigaMSFD.TempoCicloBase}"); answ.Add("PzPalletProd", $"{rigaMSFD.PzPalletProd}"); answ.Add("MatrOpr", $"{rigaMSFD.MatrOpr}"); answ.Add("lastVal", $"{rigaMSFD.LastVal}"); answ.Add("TCBase", $"{rigaMSFD.TempoCicloBase}"); //...e SETUP answ.Add("CodMacc", rigaMSFD.Codmacchina); answ.Add("IdxFamIn", $"{rigaMSFD.IdxFamigliaIngresso}"); answ.Add("Multi", $"{rigaMSFD.Multi}"); answ.Add("BitFilt", $"{rigaMSFD.BitFilt}"); answ.Add("MaxVal", $"{rigaMSFD.MaxVal}"); answ.Add("BSR", $"{rigaMSFD.Bsr}"); answ.Add("ExplodeBit", $"{rigaMSFD.ExplodeBit}"); answ.Add("NumBit", $"{rigaMSFD.NumBit}"); answ.Add("IdxFamMacc", $"{rigaMSFD.IdxFamiglia}"); answ.Add("simplePallet", $"{rigaMSFD.SimplePallet}"); answ.Add("palletChange", $"{rigaMSFD.PalletChange}"); // cerco dati master/slave... var macSlave = await Macchine2Slave(); var mastList = macSlave .Where(x => x.IdxMacchina.Equals(idxMacchina, StringComparison.InvariantCultureIgnoreCase)) .ToList(); var slaveList = macSlave .Where(x => x.IdxMacchinaSlave.Equals(idxMacchina, StringComparison.InvariantCultureIgnoreCase)) .ToList(); string isMaster = mastList.Count > 0 ? "1" : "0"; string isSlave = slaveList.Count > 0 ? "1" : "0"; answ.Add("Master", isMaster); answ.Add("Slave", isSlave); try { redDtMacTOut = (answ["insEnabled"].ToLower() == "true") ? tOutShort : tOutLong; } catch (Exception exc) { Log.Info($"Eccezione in calcolo timeout dati macchina: idxMacchina{idxMacchina} | TShort: {tOutShort} | TLong {tOutLong}{Environment.NewLine}{exc}"); } // salvo in _redisConn! redisHashDictSet(currKey, answ, TimeSpan.FromSeconds(redDtMacTOut)); } return answ; } /// /// Reset della cache IO post operazioni come setup ODL... /// /// Indirizzo base da cui rimuovere memoria cache /// public async Task ResetIoCache(string baseMem) { // patterna a partire da cache IO... RedisValue pattern = new RedisValue($"{MpIoNS}:*"); if (!string.IsNullOrEmpty(baseMem)) { pattern = new RedisValue($"{MpIoNS}:{baseMem}:*"); } bool answ = await ExecFlushRedisPatternAsync(pattern); return answ; } /// /// Effettua reset microstato macchina /// /// public async Task resetMicrostatoMacchina(string idxMacchina) { // salvo microstato 0... MicroStatoMacchinaModel newRecMS = new MicroStatoMacchinaModel() { IdxMacchina = idxMacchina, InizioStato = DateTime.Now, IdxMicroStato = 0, Value = "FER" }; var result = dbTabController.MicroStatoMacchinaUpsert(newRecMS); // reset in _redisConn await ResetDatiMacchinaAsync(idxMacchina); } /// /// Effettua ricalcolo MSE x macchina indicata /// /// idx macchina da confermare /// Num massimo secondi di "vecchiaia" del dato /// public async Task RicalcMse(string idxMacchina, int maxAgeSec) { bool answ = false; answ = dbTabController.RicalcMse(idxMacchina, maxAgeSec); await FlushOdlCache(); await FlushCache(Constants.redisMseKey); await FlushCache(Constants.redisMacchine); return answ; } /// /// Esegue il ripristino stato precedente x una macchina che abbia una dichiarazione manuale (es Pausa pranzo) da cui "uscire" /// /// /// /// /// /// /// public async Task RipristinaStatoPrec(string idxMacchina, DateTime dtCurr, string valore, int idxStato = 0, int matrOpr = 0) { bool inserito = false; try { // inserisco evento inserito = await dbTabController.RipristinaStatoPrec(idxMacchina, dtCurr, valore, idxStato, matrOpr); // reset cache eventi/commenti await FlushCache("EvList"); await FlushCache("Commenti"); } catch (Exception exc) { string logMsg = $"Eccezione in fase di RipristinaStatoPrec | macchina: {idxMacchina} | dtCurr: {dtCurr} | valore: {valore} | idxStato {idxStato} | matrOpr {matrOpr}{Environment.NewLine}{exc}"; Log.Error(logMsg); } return inserito; } /// /// Processa registrazione di un counter x una data macchina IOB /// /// /// contapezzi /// public async Task saveCounter(string idxMacchina, string counter) { // registro conteggio impiego chiamate REDIS saveCallRec("saveCounter"); string answ = "0"; // inizio processing vero e proprio INPUT... if (!string.IsNullOrEmpty(idxMacchina)) { if (!string.IsNullOrEmpty(counter)) { int newCounter = -1; int.TryParse(counter, out newCounter); // se il conteggio è >= 0 SALVO come nuovo conteggio... if (newCounter >= 0) { string redKey = redHash($"PzCount:{idxMacchina}"); // verifico SE ci sia chiave in _redisConn (ALTRIMENTI rileggo da DB) string redVal = _redisDb.StringGet(redKey); if (!string.IsNullOrEmpty(redVal)) { // salvo in Redis nell'area corretta il valore richiesto _redisDb.StringSet(redKey, counter); // imposto risposta... answ = counter; } else { // rileggo da DB e salvo e poi restituisco questo... int currCount = await pzCounterTC(idxMacchina); _redisDb.StringSet(redKey, $"{currCount}"); // imposto risposta... answ = currCount.ToString(); } } } else { string errore = "Errore: parametro counter vuoto"; Log.Error(errore); answ = errore; } } else { string errore = "Errore: parametro macchina vuoto"; Log.Error(errore); answ = errore; } return answ; } /// /// Processa registrazione ODL corrente x macchina /// /// /// cod ODL in produzione, se 0 > vuoto /// public string saveCurrODL(string idxMacchina, int currIdxOdl) { // registro conteggio impiego chiamate REDIS saveCallRec("saveCurrODL"); int currOdlCacheDur = 500; ConfigGetVal("currOdlCacheDur", ref currOdlCacheDur); string answ = ""; // inizio processing vero e proprio INPUT... if (idxMacchina != null) { if (idxMacchina != "") { // se ODL fosse 0 USO DURATA CACHE 1/4... if (currIdxOdl == 0) { currOdlCacheDur = currOdlCacheDur / 4; } _redisDb.StringSet(redHash($"CurrODL:{idxMacchina}"), currIdxOdl, TimeSpan.FromSeconds(currOdlCacheDur)); // registro in risposta che è andato tutto bene... answ = "OK"; } else { string errore = $"Errore: parametri macchina vuoto (idxMacchina: {idxMacchina} | currIdxOdl: {currIdxOdl})"; Log.Error(errore); answ = errore; } } else { string errore = "Errore: mancano parametri macchina"; Log.Error(errore); answ = errore; } return answ; } /// /// Setup oggetto config con lettura da DB /// /// public void SetupConfig() { CurrConfig = ConfigGetAll(); } /// /// Restituisce elenco gruppi Scheda tecnica /// /// public async Task> ST_AnagGruppiList() { // setup parametri costanti string source = "DB"; Stopwatch sw = new Stopwatch(); sw.Start(); List? result = new List(); // cerco in _redisConn... string currKey = $"{redisBaseKey}:ST:AnagGruppiModel"; RedisValue rawData = await _redisDb.StringGetAsync(currKey); if (rawData.HasValue) { result = JsonConvert.DeserializeObject>($"{rawData}"); source = "REDIS"; } else { result = dbTabController.ST_AnagGruppiList(); // serializzo e salvo... rawData = JsonConvert.SerializeObject(result); await _redisDb.StringSetAsync(currKey, rawData, UltraLongCache); } if (result == null) { result = new List(); } sw.Stop(); Log.Debug($"ST_AnagGruppiList | {source} | {sw.Elapsed.TotalMilliseconds}ms"); return result; } public async Task ST_CheckCleanByOdl(int idxOdl) { bool answ = false; try { // inserisco evento answ = dbTabController.ST_CheckCleanByOdl(idxOdl); await FlushCache("ST"); } catch (Exception exc) { string logMsg = $"Eccezione in ST_CheckCleanByOdl | idxOdl: {idxOdl}{Environment.NewLine}{exc}"; Log.Error(logMsg); } return answ; } public async Task ST_CheckUpsert(int idxOdl, int idxST, int oggetto, int num, string valueRead, string extCode, bool checkOk, string userMod, bool forced) { bool answ = false; try { // inserisco evento answ = dbTabController.ST_CheckUpsert(idxOdl, idxST, oggetto, num, valueRead, extCode, checkOk, userMod, forced); await FlushCache("ST"); } catch (Exception exc) { string logMsg = $"Eccezione in ST_CheckUpsert | idxOdl: {idxOdl}{Environment.NewLine}{exc}"; Log.Error(logMsg); } return answ; } /// /// Dati deroga SchedaTecnica serializzati in REDIS /// public StCheckOverride ST_DerogaGet(string Utente, int IdxST) { StCheckOverride answ = new StCheckOverride() { IdxST = 0 }; string keyDerogaST = redHash($"DerogaSt:{Utente}:{IdxST:000}"); string rawData = _redisDb.StringGet(keyDerogaST); if (!string.IsNullOrEmpty(rawData)) { try { answ = JsonConvert.DeserializeObject(rawData); } catch (Exception exc) { Log.Error($"Eccezione in ST_DerogaSet | Utente: {Utente} | IdxST: {IdxST}{Environment.NewLine}{exc}"); } } return answ; } public bool ST_DerogaSet(StCheckOverride deroga) { bool fatto = false; try { string keyDerogaST = redHash($"DerogaSt:{deroga.Utente}:{deroga.IdxST:000}"); string rawData = JsonConvert.SerializeObject(deroga); _redisDb.StringSet(keyDerogaST, rawData, TimeSpan.FromMinutes(2)); fatto = true; } catch (Exception exc) { Log.Error($"Eccezione in ST_DerogaSet | Utente: {deroga.Utente} | IdxST: {deroga.IdxST}{Environment.NewLine}{exc}"); } return fatto; } /// /// Recupero Righe (Actual) della scheda tecnica da GRUPPO + ODL /// /// /// /// public async Task> STAR_byGrpOdl(string codGruppo, int idxODL) { // setup parametri costanti string source = "DB"; Stopwatch sw = new Stopwatch(); sw.Start(); List? result = new List(); // cerco in _redisConn... string currKey = $"{redisBaseKey}:STAR:{codGruppo}:{idxODL}"; RedisValue rawData = await _redisDb.StringGetAsync(currKey); //if (!string.IsNullOrEmpty($"{rawData}")) if (rawData.HasValue) { result = JsonConvert.DeserializeObject>($"{rawData}"); source = "REDIS"; } else { result = dbTabController.STAR_byGrpOdl(codGruppo, idxODL); // serializzo e salvo... rawData = JsonConvert.SerializeObject(result); await _redisDb.StringSetAsync(currKey, rawData, LongCache); } if (result == null) { result = new List(); } sw.Stop(); Log.Debug($"STAR_byGrpOdl | {source} | {sw.Elapsed.TotalMilliseconds}ms"); return result; } /// /// Recupero Righe (Actual) della scheda tecnica da GRUPPO + ODL /// /// /// /// /// public async Task> STAR_byGrpOdlLbl(string codGruppo, string label, int idxODL) { // setup parametri costanti string source = "DB"; Stopwatch sw = new Stopwatch(); sw.Start(); List? result = new List(); // cerco in _redisConn... string currKey = $"{redisBaseKey}:STAR:{codGruppo}:{label}:{idxODL}"; RedisValue rawData = await _redisDb.StringGetAsync(currKey); //if (!string.IsNullOrEmpty($"{rawData}")) if (rawData.HasValue) { result = JsonConvert.DeserializeObject>($"{rawData}"); source = "REDIS"; } else { result = dbTabController.STAR_byGrpOdlLbl(codGruppo, label, idxODL); // serializzo e salvo... rawData = JsonConvert.SerializeObject(result); await _redisDb.StringSetAsync(currKey, rawData, LongCache); } if (result == null) { result = new List(); } sw.Stop(); Log.Debug($"STAR_byGrpOdlLbl | {source} | {sw.Elapsed.TotalMilliseconds}ms"); return result; } /// /// Recupero Righe pending da ODL /// /// /// public List STAR_pendByOdl(int idxODL) { // setup parametri costanti string source = "DB"; Stopwatch sw = new Stopwatch(); sw.Start(); List? result = new List(); // cerco in _redisConn... string currKey = $"{redisBaseKey}:STAR:Pend:{idxODL}"; RedisValue rawData = _redisDb.StringGet(currKey); if (rawData.HasValue) { result = JsonConvert.DeserializeObject>($"{rawData}"); source = "REDIS"; } else { result = dbTabController.STAR_pendByOdl(idxODL); // serializzo e salvo... rawData = JsonConvert.SerializeObject(result); _redisDb.StringSet(currKey, rawData, TimeSpan.FromSeconds(5)); } if (result == null) { result = new List(); } sw.Stop(); Log.Debug($"STAR_pendByOdl | {source} | {sw.Elapsed.TotalMilliseconds}ms"); return result; } /// /// Stato macchina /// /// /// public StatoMacchineModel StatoMacchina(string idxMacchina) { // setup parametri costanti string source = "DB"; Stopwatch sw = new Stopwatch(); sw.Start(); StatoMacchineModel? result = new StatoMacchineModel(); // cerco in _redisConn... string currKey = $"{redisBaseKey}:StatoMacc:{idxMacchina}"; RedisValue rawData = _redisDb.StringGet(currKey); if (rawData.HasValue) { result = JsonConvert.DeserializeObject($"{rawData}"); source = "REDIS"; } else { result = dbTabController.StatoMacchina(idxMacchina); // serializzo e salvo... rawData = JsonConvert.SerializeObject(result); _redisDb.StringSet(currKey, rawData, TimeSpan.FromSeconds(2)); } if (result == null) { result = new StatoMacchineModel(); } sw.Stop(); Log.Debug($"StatoMacchina | {source} | {sw.Elapsed.TotalMilliseconds}ms"); return result; } /// /// Stato prod macchina (completo) /// /// /// /// public async Task StatoProdMacchinaAsync(string idxMacchina, DateTime dtReq) { int rndWait = rnd.Next(0, 2); await Task.Delay(rndWait); // setup parametri costanti string source = "DB"; Stopwatch sw = new Stopwatch(); sw.Start(); StatoProdModel? result = new StatoProdModel(); // cerco in _redisConn... string currKey = $"{redisBaseKey}:StatoProd:{idxMacchina}:{dtReq:HHmm}"; RedisValue rawData = await _redisDb.StringGetAsync(currKey); //if (!string.IsNullOrEmpty($"{rawData}")) if (rawData.HasValue) { result = JsonConvert.DeserializeObject($"{rawData}"); source = "REDIS"; } else { result = dbTabController.StatoProdMacchina(idxMacchina, dtReq); // serializzo e salvo... rawData = JsonConvert.SerializeObject(result); await _redisDb.StringSetAsync(currKey, rawData, UltraFastCache); } if (result == null) { result = new StatoProdModel(); } sw.Stop(); string callName = $"StatoProdMacchinaAsync.{source}"; int numRec = esCollect.RecordCall(callName, sw.Elapsed.TotalMilliseconds); if (numRec >= nRecLog || true) { Log.Debug(esCollect.GetCallSum(callName, true)); } return result; } /// /// Elenco Template KIT da ricerca /// /// /// /// public List TemplateKitFilt(string codParent, string codChild) { string source = "DB"; Stopwatch sw = new Stopwatch(); sw.Start(); List? result = new List(); // cerco in _redisConn... string currKey = $"{MP.Core.Utils.redisKitTempl}:{codParent}:{codChild}"; RedisValue rawData = _redisDb.StringGet(currKey); if (rawData.HasValue) { result = JsonConvert.DeserializeObject>($"{rawData}"); source = "REDIS"; } else { result = dbTabController.TemplateKitFilt(codParent, codChild); // serializzo e salvo... rawData = JsonConvert.SerializeObject(result); _redisDb.StringSet(currKey, rawData, LongCache); } if (result == null) { result = new List(); } sw.Stop(); Log.Debug($"TemplateKitFilt | {source} | {sw.Elapsed.TotalMilliseconds}ms"); return result; } /// /// Turno macchina /// /// public async Task TurnoMacchinaGet(string idxMacchina) { string source = "DB"; Stopwatch sw = new Stopwatch(); sw.Start(); TurniMaccModel? result = new TurniMaccModel(); // cerco in _redisConn... string currKey = $"{redisBaseKey}:TurniMacc:{idxMacchina}"; RedisValue rawData = await _redisDb.StringGetAsync(currKey); //if (!string.IsNullOrEmpty($"{rawData}")) if (rawData.HasValue) { result = JsonConvert.DeserializeObject($"{rawData}"); source = "REDIS"; } else { result = await Task.FromResult(dbTabController.TurnoMacchinaGet(idxMacchina)); // serializzo e salvo... rawData = JsonConvert.SerializeObject(result); await _redisDb.StringSetAsync(currKey, rawData, LongCache); } if (result == null) { result = new TurniMaccModel(); } sw.Stop(); Log.Debug($"TurnoMacchinaGet | {source} | {sw.Elapsed.TotalMilliseconds}ms"); return result; } /// /// Elenco turni macchina (all) /// /// public async Task> TurnoMacchinaGetAll() { string source = "DB"; Stopwatch sw = new Stopwatch(); sw.Start(); List? result = new List(); // cerco in _redisConn... string currKey = $"{redisBaseKey}:TurniMacc:All"; RedisValue rawData = await _redisDb.StringGetAsync(currKey); if (rawData.HasValue) { result = JsonConvert.DeserializeObject>($"{rawData}"); source = "REDIS"; } else { result = await Task.FromResult(dbTabController.TurnoMacchinaGetAll()); // serializzo e salvo... rawData = JsonConvert.SerializeObject(result); await _redisDb.StringSetAsync(currKey, rawData, LongCache); } if (result == null) { result = new List(); } sw.Stop(); Log.Debug($"TurnoMacchinaGetAll | {source} | {sw.Elapsed.TotalMilliseconds}ms"); return result; } /// /// Toggle stato turno /// /// /// /// public bool TurnoMacchinaToggle(string idxMacchina, int numTurno) { bool answ = dbTabController.TurnoMacchinaToggle(idxMacchina, numTurno); FlushCache("TurniMacc").ConfigureAwait(false); return answ; } /// /// OVERLOAD vecchio nome function per MachineParamUpsert: Effettua UPSERT elenco parametri /// correnti x IOB (se c'è UPDATE, se manca ADD) /// /// /// /// public bool upsertCurrObjItems(string idxMacchina, List innovations) { return MachineParamUpsert(idxMacchina, innovations); } /// /// Intera vista v_MSFD /// /// forza rilettura + save su _redisConn /// public async Task> VMSFDGetAll(bool doForce = false) { // setup parametri costanti string source = "DB"; Stopwatch sw = new Stopwatch(); sw.Start(); List result = new List(); // cerco in _redisConn... string currKey = $"{redisBaseKey}:MSFD:ALL"; RedisValue rawData = await _redisDb.StringGetAsync(currKey); if (rawData.HasValue && !doForce) { result = JsonConvert.DeserializeObject>($"{rawData}"); source = "REDIS"; } else { result = await dbIocController.VMSFDGetAllAsync(); // serializzo e salvo... rawData = JsonConvert.SerializeObject(result); await _redisDb.StringSetAsync(currKey, rawData, UltraFastCache); } if (result == null) { result = new List(); } sw.Stop(); Log.Debug($"VMSFDGetAll | {source} | {sw.Elapsed.TotalMilliseconds}ms"); return result; } /// /// Vista v_MSFD x singola macchina (da stored) - singolo record /// /// /// public async Task VMSFDGetByMaccAsync(string idxMacc) { // setup parametri costanti string source = "DB"; Stopwatch sw = new Stopwatch(); sw.Start(); VMSFDModel? result = null; // cerco in _redisConn... string currKey = $"{redisBaseKey}:MSFD:MACCH:{idxMacc}"; RedisValue rawData = await _redisDb.StringGetAsync(currKey); //if (!string.IsNullOrEmpty($"{rawData}")) if (rawData.HasValue) { result = JsonConvert.DeserializeObject($"{rawData}"); source = "REDIS"; } else { result = await dbIocController.VMSFDGetByMaccAsync(idxMacc); // serializzo e salvo... rawData = JsonConvert.SerializeObject(result); await _redisDb.StringSetAsync(currKey, rawData, UltraFastCache); } if (result == null) { result = new(); } sw.Stop(); Log.Debug($"VMSFDGetByMaccAsync | {source} | {sw.Elapsed.TotalMilliseconds}ms"); return result; } /// /// Vista v_MSFD delle machine MULTI filtrato x macchina (da stored) /// /// /// public async Task> VMSFDGetMultiByMacc(string idxMacc) { // setup parametri costanti string source = "DB"; Stopwatch sw = new Stopwatch(); sw.Start(); List? result = new List(); // cerco in _redisConn... string currKey = $"{redisBaseKey}:MSFD:MULTI:{idxMacc}"; RedisValue rawData = await _redisDb.StringGetAsync(currKey); //if (!string.IsNullOrEmpty($"{rawData}")) if (rawData.HasValue) { result = JsonConvert.DeserializeObject>($"{rawData}"); source = "REDIS"; } else { result = await dbIocController.VMSFDGetMultiByMaccAsync(idxMacc); // serializzo e salvo... rawData = JsonConvert.SerializeObject(result); await _redisDb.StringSetAsync(currKey, rawData, LongCache); } if (result == null) { result = new List(); } sw.Stop(); Log.Debug($"VMSFDGetMultiByMacc | {source} | {sw.Elapsed.TotalMilliseconds}ms"); return result; } public List VocabolarioGetAll() { // setup parametri costanti string source = "DB"; Stopwatch sw = new Stopwatch(); sw.Start(); List? result = new List(); // cerco in _redisConn... string currKey = $"{redisBaseKey}:Vocab"; RedisValue rawData = _redisDb.StringGet(currKey); if (rawData.HasValue) { result = JsonConvert.DeserializeObject>($"{rawData}"); source = "REDIS"; } else { result = dbTabController.VocabolarioGetAll(); // serializzo e salvo... rawData = JsonConvert.SerializeObject(result); _redisDb.StringSet(currKey, rawData, UltraLongCache); } if (result == null) { result = new List(); } sw.Stop(); Log.Debug($"VocabolarioGetAll | {source} | {sw.Elapsed.TotalMilliseconds}ms"); return result; } /// /// Elenco causali scarto /// /// public async Task> VSCS_getAll() { string source = "DB"; Stopwatch sw = new Stopwatch(); sw.Start(); List? result = new List(); // cerco in _redisConn... string currKey = $"{redisBaseKey}:VSCS"; RedisValue rawData = await _redisDb.StringGetAsync(currKey); if (rawData.HasValue) { result = JsonConvert.DeserializeObject>($"{rawData}"); source = "REDIS"; } else { result = await Task.FromResult(dbTabController.VSCS_getAll()); // serializzo e salvo... rawData = JsonConvert.SerializeObject(result); await _redisDb.StringSetAsync(currKey, rawData, LongCache); } if (result == null) { result = new List(); } sw.Stop(); Log.Debug($"VSCS_getAll | {source} | {sw.Elapsed.TotalMilliseconds}ms"); return result; } /// /// Elenco ultimi ODL x macchina /// /// Macchina /// /// public async Task> VSOdlGetLastByMacc(string idxMacchina, int numRec) { string source = "DB"; Stopwatch sw = new Stopwatch(); sw.Start(); List? result = new List(); // cerco in _redisConn... string currKey = $"{redisBaseKey}:VSODL:{idxMacchina}:{numRec}"; RedisValue rawData = await _redisDb.StringGetAsync(currKey); if (rawData.HasValue) { result = JsonConvert.DeserializeObject>($"{rawData}"); source = "REDIS"; } else { result = await Task.FromResult(dbTabController.VSOdlGetLastByMacc(idxMacchina, numRec)); // serializzo e salvo... rawData = JsonConvert.SerializeObject(result); await _redisDb.StringSetAsync(currKey, rawData, LongCache); } if (result == null) { result = new List(); } sw.Stop(); Log.Debug($"VSOdlGetLastByMacc | {source} | {sw.Elapsed.TotalMilliseconds}ms"); return result; } /// /// Elenco prossimi ODL/PODL x macchina /// /// Macchina /// /// /// public async Task> VSOdlGetUnused(string idxMacchina, bool showAll, int numDayAdd) { string source = "DB"; Stopwatch sw = new Stopwatch(); sw.Start(); List? result = new List(); // cerco in _redisConn... string currKey = $"{redisBaseKey}:VSODL:{idxMacchina}:ALL_{showAll}:{numDayAdd}"; RedisValue rawData = await _redisDb.StringGetAsync(currKey); if (rawData.HasValue && rawData.Length() > 2) { result = JsonConvert.DeserializeObject>($"{rawData}"); source = "REDIS"; } else { result = await Task.FromResult(dbTabController.VSOdlGetUnused(idxMacchina, showAll, numDayAdd)); // serializzo e salvo... rawData = JsonConvert.SerializeObject(result); await _redisDb.StringSetAsync(currKey, rawData, FastCache); } if (result == null) { result = new List(); } sw.Stop(); Log.Debug($"VSOdlGetUnused | {source} | {sw.Elapsed.TotalMilliseconds}ms"); return result; } #endregion Public Methods #region Protected Fields protected int expMinutes = 1; #endregion Protected Fields #region Protected Properties /// /// Durata cache data dal valore in config /// protected TimeSpan ConfigCache { get => TimeSpan.FromMinutes(expMinutes); } #endregion Protected Properties #region Protected Methods protected override void Dispose(bool disposing) { if (!_disposed) { if (disposing) { // Free managed resources here dbTabController.Dispose(); //dbIocController.Dispose(); dbInveController.Dispose(); CurrConfig.Clear(); connStrParams.Clear(); esCollect.Dispose(); } // Free unmanaged resources here _disposed = true; } // Call base class implementation. base.Dispose(disposing); } protected void setExpDays() { ConfigGetVal("TAB_dtTimerScadLogin", ref expMinutes); } #endregion Protected Methods #region Private Fields private static Logger Log = LogManager.GetCurrentClassLogger(); private bool _disposed = false; private string CodModulo = ""; private string CodModuloParam = ""; private string ConnStr = ""; private Dictionary connStrParams = new Dictionary(); private string DataBase = ""; private string DataSource = ""; /// /// gestore collezione statistiche esecuzione x logging /// private ExecStatsCollector esCollect = new ExecStatsCollector(); /// /// numero minimo di record per cui iniziare fase di log /// private int nRecLog = 10; private string redisBaseKey = "MP:TAB:Cache"; private string redisUserDataKey = "MP:TAB:Users"; /// /// Generatore random classe /// private Random rnd = new Random(); #endregion Private Fields #region Private Properties private static Controllers.MpInveController dbInveController { get; set; } = null!; private static Controllers.MpIocController dbIocController { get; set; } = null!; private static Controllers.MpTabController dbTabController { get; set; } = null!; #endregion Private Properties #region Private Methods /// /// Esegue flush memoria _redisConn dato pat2Flush, metodo sincrono /// /// /// private bool ExecFlushRedisPattern(RedisValue pat2Flush) { bool answ = false; var masterEndpoint = _redisConn.GetEndPoints() .Where(ep => _redisConn.GetServer(ep).IsConnected && !_redisConn.GetServer(ep).IsReplica) .FirstOrDefault(); // sepattern è "*" elimino intero DB... if (masterEndpoint != null && (pat2Flush.Equals(new RedisValue("*")) || pat2Flush == RedisValue.Null)) { _redisConn.GetServer(masterEndpoint).FlushDatabase(database: _redisDb.Database); } else { var server = _redisConn.GetServer(masterEndpoint); var keys = server.Keys(database: _redisDb.Database, pattern: pat2Flush, pageSize: 1000); var batch = new List(); foreach (var key in keys) { batch.Add(key); // Flush in batches of 1000 if (batch.Count >= 1000) { foreach (var item in batch) _redisDb.KeyDelete(item); batch.Clear(); } } // Flush remaining keys foreach (var item in batch) _redisDb.KeyDelete(item); } answ = true; #if false var listEndpoints = redisConn.GetEndPoints(); foreach (var endPoint in listEndpoints) { //var server = redisConnAdmin.GetServer(listEndpoints[0]); var server = redisConn.GetServer(endPoint); if (server != null) { var keyList = server.Keys(redisDb.Database, pattern); foreach (var item in keyList) { redisDb.KeyDelete(item); } answ = true; } } #endif // notifico update ai client in ascolto x reset cache NotifyReloadRequest($"FlushRedisCache | {pat2Flush}"); return answ; } /// /// Esegue flush memoria _redisConn dato pat2Flush in async /// /// /// private async Task ExecFlushRedisPatternAsync(RedisValue pat2Flush) { bool answ = false; var masterEndpoint = _redisConn.GetEndPoints() .Where(ep => _redisConn.GetServer(ep).IsConnected && !_redisConn.GetServer(ep).IsReplica) .FirstOrDefault(); // se pattern è "*" elimino intero DB... if (masterEndpoint != null && (pat2Flush.Equals(new RedisValue("*")) || pat2Flush == RedisValue.Null)) { _redisConn.GetServer(masterEndpoint).FlushDatabase(database: _redisDb.Database); } else { var server = _redisConn.GetServer(masterEndpoint); var keys = server.Keys(database: _redisDb.Database, pattern: pat2Flush, pageSize: 1000); var deleteTasks = new List(); foreach (var key in keys) { deleteTasks.Add(_redisDb.KeyDeleteAsync(key)); if (deleteTasks.Count >= 1000) { await Task.WhenAll(deleteTasks); deleteTasks.Clear(); } } if (deleteTasks.Count > 0) { await Task.WhenAll(deleteTasks); } } answ = true; #if false var listEndpoints = redisConn.GetEndPoints(); foreach (var endPoint in listEndpoints) { //var server = redisConnAdmin.GetServer(listEndpoints[0]); var server = redisConn.GetServer(endPoint); if (server != null) { var keyList = server.Keys(redisDb.Database, pat2Flush); foreach (var item in keyList) { await redisDb.KeyDeleteAsync(item); } answ = true; } } #endif // notifico update ai client in ascolto x reset cache NotifyReloadRequest($"FlushRedisCache | {pat2Flush}"); return answ; } /// /// Hash dati EXE TASK x la macchina specificata /// /// /// private string exeTaskHash(string idxMacchina) { return RedHashMpIO($"ExeTask:{idxMacchina}"); } /// /// Restitusice elenco KVP dei TASK (da passare a IOB-WIN) per l'impianto indicato /// /// /// private Dictionary mTaskMacchina(string idxMacchina) { // hard coded dimensione vettore DatiMacchine Dictionary answ = new Dictionary(); // ORA recupero da memoria _redisConn... try { var currKey = (RedisKey)exeTaskHash(idxMacchina); answ = redisHashDictGet(currKey); } catch (Exception exc) { Log.Info(string.Format("Errore in recupero dati EXE TASK x Redis mTaskMacchina - idxMacchina {2}:{0}{1}", Environment.NewLine, exc, idxMacchina)); } return answ; } private string redHash(string keyName) { string result = keyName; try { result = $"{CodModulo}:{DataSource}:{DataBase}:{keyName}".Replace("\\", "_"); } catch (Exception exc) { Log.Error($"Errore in redHash{Environment.NewLine}{exc}"); } return result; } #if false protected string RedHashMpIO(string keyName) { string result = keyName; try { result = $"{MpIoNS}:{keyName}".Replace("\\", "_"); } catch (Exception exc) { Log.Error($"Errore in RedHashMpIO{Environment.NewLine}{exc}"); } return result; } #endif private string redHashParam(string keyName) { string result = keyName; try { result = $"{CodModuloParam}:{DataSource}:{DataBase}:{keyName}".Replace("\\", "_"); } catch (Exception exc) { Log.Error($"Errore in redHashParam{Environment.NewLine}{exc}"); } return result; } /// /// Recupero HashSet _redisConn come Dictionary /// /// /// private Dictionary redisHashDictGet(RedisKey currKey) { Dictionary answ = new Dictionary(); try { answ = _redisDb .HashGetAll(currKey) .ToDictionary(x => $"{x.Name}", x => $"{x.Value}"); } catch (Exception exc) { Log.Info($"Errore redisHashDictGet | currKey: {currKey}{Environment.NewLine}{exc}"); } return answ; } /// /// Salvataggio Dictionary come HashSet Redis /// /// /// private bool redisHashDictSet(RedisKey currKey, Dictionary dict) { bool fatto = false; try { HashEntry[] data2ins = new HashEntry[dict.Count]; int i = 0; foreach (KeyValuePair kvp in dict) { data2ins[i] = new HashEntry(kvp.Key, kvp.Value); i++; } // salvo! _redisDb.HashSet(currKey, data2ins); fatto = true; } catch (Exception exc) { Log.Error($"Eccezione in redisHashDictSet | currKey: {currKey}{Environment.NewLine}{exc}"); } return fatto; } /// /// Salvataggio Dictionary come HashSet Redis /// /// /// /// private bool redisHashDictSet(RedisKey currKey, Dictionary dict, TimeSpan ttl) { bool fatto = false; try { HashEntry[] data2ins = new HashEntry[dict.Count]; int i = 0; foreach (KeyValuePair kvp in dict) { data2ins[i] = new HashEntry(kvp.Key, kvp.Value); i++; } // salvo! _redisDb.HashSet(currKey, data2ins); _redisDb.KeyExpire(currKey, ttl); fatto = true; } catch (Exception exc) { Log.Error($"Eccezione in redisHashDictSet | currKey: {currKey}{Environment.NewLine}{exc}"); } return fatto; } /// /// registra su REDIS eventuale superamento numero limite di call x il metodo in oggetto /// /// private void saveCallRec(string callCountKey) { // conto la richiesta nel contatore REDIS long nCall = _redisDb.StringIncrement(redHash($"COUNT:pCall:{callCountKey}")); //... se == nCall2Log scrivo su log e resetto int nCall2Log = 10; ConfigGetVal("nCall2Log", ref nCall2Log); if (nCall >= nCall2Log) { // loggo Log.Info($"{callCountKey}: {nCall} call received"); // resetto! _redisDb.StringSet(redHash($"COUNT:pCall:{callCountKey}"), "0"); } } /// /// Hash dati SAVED (EXE) TASK x la macchina specificata x poter ripristinare in caso di /// perdita valore WRITE /// /// /// private string savedTaskHash(string idxMacchina) { return RedHashMpIO($"SavedTask:{idxMacchina}"); } #endregion Private Methods } }