using MP.Data; using MP.Data.Conf; using MP.Data.DatabaseModels; using MP.Data.DTO; using MP.Data.MgModels; using Newtonsoft.Json; using NLog; using StackExchange.Redis; using System.Data; using System.Diagnostics; namespace MP.IOC.Data { public class MpDataService : IDisposable { #region Public Constructors public MpDataService(IConfiguration configuration, ILogger logger) { _logger = logger; _logger.LogInformation("Starting MpDataService INIT"); _configuration = configuration; // setup compoenti REDIS redisConn = ConnectionMultiplexer.Connect(_configuration.GetConnectionString("Redis")); redisConnAdmin = ConnectionMultiplexer.Connect(_configuration.GetConnectionString("RedisAdmin")); redisDb = redisConn.GetDatabase(); BroadastMsgPipe = new MessagePipe(redisConn, Constants.BROADCAST_M_PIPE); // leggo cache lungo periodo int.TryParse(_configuration.GetValue("ServerConf:redisLongTimeCache"), out redisLongTimeCache); _logger.LogInformation("Redis INIT"); // conf DB string connStr = _configuration.GetConnectionString("Mp.Data"); if (string.IsNullOrEmpty(connStr)) { _logger.LogError("DbController: ConnString empty!"); } else { SpecDbController = new MP.Data.Controllers.MpSpecController(configuration); IocDbController = new MP.Data.Controllers.MpIocController(configuration); _logger.LogInformation("DbControllers INIT OK"); } // conf mongo... connStr = _configuration.GetConnectionString("mdbConnString"); if (string.IsNullOrEmpty(connStr)) { _logger.LogError("MongoController: ConnString empty!"); } else { mongoController = new MP.Data.Controllers.MpMongoController(configuration); _logger.LogInformation("MongoController INIT OK"); } } #endregion Public Constructors #region Public Properties public static MP.Data.Controllers.MpIocController IocDbController { get; set; } = null!; public static MP.Data.Controllers.MpMongoController mongoController { get; set; } = null!; public static MP.Data.Controllers.MpSpecController SpecDbController { get; set; } = null!; public MessagePipe BroadastMsgPipe { get; set; } = null!; /// /// Dizionario dei tag configurati per IOB /// public Dictionary> currTagConf { get; set; } = new Dictionary>(); #endregion Public Properties #region Public Methods /// /// Recupera eventuali azioni richieste /// /// public async Task ActionGetReq() { Stopwatch stopWatch = new Stopwatch(); stopWatch.Start(); DisplayAction? result = null; // cerco in redis... RedisValue rawData = await redisDb.StringGetAsync(Utils.redisActionReq); if (!string.IsNullOrEmpty($"{rawData}")) { result = JsonConvert.DeserializeObject($"{rawData}"); stopWatch.Stop(); TimeSpan ts = stopWatch.Elapsed; Log.Debug($"ActionGetReq Read from REDIS: {ts.TotalMilliseconds}ms"); } if (result == null) { result = new DisplayAction(); } return result; } /// /// Salva richiesta azione /// /// /// public bool ActionSetReq(DisplayAction? act2save) { bool fatto = false; Stopwatch stopWatch = new Stopwatch(); stopWatch.Start(); // cerco in redis... string rawData = JsonConvert.SerializeObject(act2save); // invio broadcast + salvo in redis BroadastMsgPipe.saveAndSendMessage(Utils.redisActionReq, rawData); stopWatch.Stop(); TimeSpan ts = stopWatch.Elapsed; Log.Debug($"ActionSetReq REDIS send to broadcast + Write cache: {ts.TotalMilliseconds}ms"); return fatto; } /// /// Aggiunge un PARAMETRO OPZIONALE all'elenco di quelli salvati (in modalità upsert) /// /// /// /// /// public bool AddOptPar4Machine(string idxMacchina, string taskKey, string taskVal) { bool answ = false; RedisKey currHash = Utils.OptParHash(idxMacchina); try { // leggo task attuali... var currVal = mOptParMacchina(idxMacchina); currVal[taskKey] = taskVal; answ = RedisSetHashDict(currHash, currVal); } catch (Exception exc) { Log.Error($"Eccezione in addOptPar4Machine{Environment.NewLine}{exc}"); } return answ; } public async Task> AnagStatiComm() { Stopwatch stopWatch = new Stopwatch(); stopWatch.Start(); List? result = new List(); // cerco in redis... RedisValue rawData = await redisDb.StringGetAsync(Utils.redisStatoCom); if (!string.IsNullOrEmpty($"{rawData}")) { result = JsonConvert.DeserializeObject>($"{rawData}"); stopWatch.Stop(); TimeSpan ts = stopWatch.Elapsed; Log.Debug($"AnagStatiComm Read from REDIS: {ts.TotalMilliseconds}ms"); } else { result = await Task.FromResult(SpecDbController.AnagStatiComm()); // serializzo e salvo... rawData = JsonConvert.SerializeObject(result); await redisDb.StringSetAsync(Utils.redisStatoCom, rawData, getRandTOut(redisLongTimeCache)); stopWatch.Stop(); TimeSpan ts = stopWatch.Elapsed; Log.Debug($"AnagStatiComm Read from DB: {ts.TotalMilliseconds}ms"); } if (result == null) { result = new List(); } return result; } public async Task> AnagTipoArtLV() { Stopwatch stopWatch = new Stopwatch(); stopWatch.Start(); string source = "DB"; List? result = new List(); // cerco in redis... RedisValue rawData = await redisDb.StringGetAsync(Utils.redisTipoArt); if (!string.IsNullOrEmpty($"{rawData}")) { result = JsonConvert.DeserializeObject>($"{rawData}"); source = "REDIS"; } else { result = await Task.FromResult(SpecDbController.AnagTipoArtLV()); // serializzo e salvo... rawData = JsonConvert.SerializeObject(result); await redisDb.StringSetAsync(Utils.redisTipoArt, rawData, getRandTOut(redisLongTimeCache)); } stopWatch.Stop(); TimeSpan ts = stopWatch.Elapsed; Log.Debug($"AnagTipoArtLV Read from {source}: {ts.TotalMilliseconds}ms"); if (result == null) { result = new List(); } return result; } /// /// Elenco Codice articolo con dati dossier gestiti /// /// public async Task> ArticleWithDossier() { List? result = new List(); Stopwatch stopWatch = new Stopwatch(); stopWatch.Start(); string readType = "DB"; string currKey = Utils.redisArtByDossier; // cerco in redis dato valore sel macchina... RedisValue rawData = redisDb.StringGet(currKey); if (rawData.HasValue) { result = JsonConvert.DeserializeObject>($"{rawData}"); readType = "REDIS"; } else { result = await Task.FromResult(SpecDbController.ArticleWithDossier()); // serializzo e salvo... rawData = JsonConvert.SerializeObject(result); redisDb.StringSet(currKey, rawData, getRandTOut(redisLongTimeCache)); } if (result == null) { result = new List(); } stopWatch.Stop(); TimeSpan ts = stopWatch.Elapsed; Log.Debug($"ArticleWithDossier | Read from {readType}: {ts.TotalMilliseconds}ms"); return result; } /// /// Eliminazione record selezionato /// /// /// public async Task ArticoliDeleteRecord(AnagArticoli currRec) { bool fatto = await SpecDbController.ArticoliDeleteRecord(currRec); await resetCacheArticoli(); return fatto; } /// /// Restitusice elenco articoli cercati /// /// /// /// public async Task> ArticoliGetSearch(int numRecord, string azienda, string searchVal) { List? result = new List(); Stopwatch stopWatch = new Stopwatch(); stopWatch.Start(); string readType = "DB"; string sKey = string.IsNullOrEmpty(searchVal) ? "***" : searchVal; string currKey = $"{Utils.redisArtList}:{azienda}:{sKey}"; // cerco in redis dato valore sel macchina... RedisValue rawData = redisDb.StringGet(currKey); if (rawData.HasValue) { result = JsonConvert.DeserializeObject>($"{rawData}"); readType = "REDIS"; } else { result = await Task.FromResult(SpecDbController.ArticoliGetSearch(numRecord, azienda, searchVal)); // serializzo e salvo... rawData = JsonConvert.SerializeObject(result); redisDb.StringSet(currKey, rawData, getRandTOut(redisLongTimeCache / 5)); } if (result == null) { result = new List(); } stopWatch.Stop(); TimeSpan ts = stopWatch.Elapsed; Log.Debug($"ArticoliGetSearch | Read from {readType}: {ts.TotalMilliseconds}ms"); return result; } /// /// Aggiornamento record selezionato /// /// /// public async Task ArticoliUpdateRecord(AnagArticoli currRec) { bool fatto = await SpecDbController.ArticoliUpdateRecord(currRec); await resetCacheArticoli(); return fatto; } /// /// Verifica se sia possiubile cancellare articolo dato suo CodArt cercando su redis o su /// tab veto da DB /// /// /// public bool ArticoloDelEnabled(object CodArt) { bool answ = false; string codArticolo = $"{CodArt}"; int cacheCheckArtUsato = 1; int.TryParse(_configuration.GetValue("ServerConf:cacheCheckArtUsato"), out cacheCheckArtUsato); TimeSpan TTLCache = getRandTOut(cacheCheckArtUsato); // cerco in cache redis... string redKeyArtUsed = $"{Utils.redKeyArtUsed}:{codArticolo}"; string redKeyTabCheckArt = Utils.redKeyTabCheckArt; var rawData = redisDb.StringGet(redKeyArtUsed); if (!string.IsNullOrEmpty(rawData)) { bool.TryParse(rawData, out answ); } else { // controllo non sia stato mai prodotto sennò non posso cancellare... try { // cerco in cache se ci sia la tabella con gli articoli impiegati... var rawTable = redisDb.StringGet(redKeyTabCheckArt); List? artList = new List(); if (!string.IsNullOrEmpty(rawTable)) { artList = JsonConvert.DeserializeObject>($"{rawTable}"); } // rileggo... if (artList == null || artList.Count == 0) { artList = new List(); var tabArticoli = SpecDbController.ArticoliGetUsed(); var codList = tabArticoli.Select(x => x.CodArticolo); foreach (string cod in codList) { artList.Add(cod); } // SE fosse vuoto aggiungo comunque il cado "ND"... if (artList.Count == 0) { artList.Add("ND"); } // salvo rawTable = JsonConvert.SerializeObject(artList); redisDb.StringSet(redKeyTabCheckArt, rawTable, TTLCache); } // cerco nella tabella: se ci fosse --> disabilitato delete bool usato = false; if (artList != null && artList.Count > 0) { usato = artList.Contains(codArticolo); } answ = !usato; redisDb.StringSet(redKeyArtUsed, $"{answ}", TTLCache); } catch { } } return answ; } public string CalcRecipe(RecipeModel currRecipe) { return mongoController.CalcRecipe(currRecipe); } public async Task> ConfigGetAll() { Stopwatch stopWatch = new Stopwatch(); stopWatch.Start(); List? result = new List(); // cerco in redis... RedisValue rawData = await redisDb.StringGetAsync(Utils.redisConfKey); if (!string.IsNullOrEmpty($"{rawData}")) { result = JsonConvert.DeserializeObject>($"{rawData}"); stopWatch.Stop(); TimeSpan ts = stopWatch.Elapsed; Log.Debug($"ConfigGetAll Read from REDIS: {ts.TotalMilliseconds}ms"); } else { result = await Task.FromResult(SpecDbController.ConfigGetAll()); // serializzo e salvo... rawData = JsonConvert.SerializeObject(result); await redisDb.StringSetAsync(Utils.redisConfKey, rawData, getRandTOut(redisLongTimeCache)); stopWatch.Stop(); TimeSpan ts = stopWatch.Elapsed; Log.Debug($"ConfigGetAll Read from DB: {ts.TotalMilliseconds}ms"); } if (result == null) { result = new List(); } return result; } /// /// Reset dati cache config /// /// public async Task ConfigResetCache() { await redisDb.StringSetAsync(Utils.redisConfKey, ""); } /// /// Update chiave config /// /// public async Task ConfigUpdate(ConfigModel updRec) { return await Task.FromResult(SpecDbController.ConfigUpdate(updRec)); } /// /// Elenco completo valori DatiMacchine /// /// public async Task> DatiMacchineGetAll() { List? result = new List(); Stopwatch stopWatch = new Stopwatch(); stopWatch.Start(); string readType = "DB"; string currKey = $"{Utils.redisBaseAddr}:TabDatiMacchine:ALL"; // cerco in redis dato valore sel macchina... RedisValue rawData = redisDb.StringGet(currKey); if (rawData.HasValue) { result = JsonConvert.DeserializeObject>($"{rawData}"); readType = "REDIS"; } else { result = await Task.FromResult(SpecDbController.DatiMacchineGetAll()); // serializzo e salvo... rawData = JsonConvert.SerializeObject(result); redisDb.StringSet(currKey, rawData, getRandTOut(redisLongTimeCache)); } if (result == null) { result = new List(); } stopWatch.Stop(); TimeSpan ts = stopWatch.Elapsed; Log.Debug($"DatiMacchineGetAll | Read from {readType}: {ts.TotalMilliseconds}ms"); return result; } /// /// Dispose del connettore ai dati /// public void Dispose() { // Clear database controller SpecDbController.Dispose(); mongoController.Dispose(); redisConn.Dispose(); } /// /// Eliminazione di un dossier /// /// record dossier da eliminare /// public async Task DossiersDeleteRecord(DossierModel selRecord) { bool result = false; Stopwatch stopWatch = new Stopwatch(); stopWatch.Start(); result = await SpecDbController.DossiersDeleteRecord(selRecord); // elimino cache redis... RedisValue pattern = new RedisValue($"{Utils.redisDossByMac}:*"); bool answ = await RedisFlushPatternAsync(pattern); stopWatch.Stop(); TimeSpan ts = stopWatch.Elapsed; Log.Debug($"DossiersDeleteRecord | IdxMacchina {selRecord.IdxMacchina} | DtRif {selRecord.DtRif} | IdxODL {selRecord.IdxODL} | {ts.TotalMilliseconds}ms"); return result; } /// /// Elenco ultimi n record DOssiers (che contengono ad esempio "salvataggi" di FLuxLog) dato /// macchina (ordinato x data registrazione) /// /// * = tutte, altrimenti solo x una data macchina /// Data minima per estrazione records /// Data Massima per estrazione records /// public async Task> DossiersGetLastFilt(string IdxMacchina, string CodArticolo, DateTime DtStart, DateTime DtEnd) { List? result = new List(); Stopwatch stopWatch = new Stopwatch(); stopWatch.Start(); string readType = "DB"; string currKey = $"{Utils.redisDossByMac}:{IdxMacchina}:{CodArticolo}:{DtStart:yyyyMMddHHmm}:{DtEnd:yyyyMMddHHmm}"; // cerco in redis dato valore sel macchina... RedisValue rawData = redisDb.StringGet(currKey); if (rawData.HasValue) { result = JsonConvert.DeserializeObject>($"{rawData}"); readType = "REDIS"; } else { result = await Task.FromResult(SpecDbController.DossiersGetLastFilt(IdxMacchina, CodArticolo, DtStart, DtEnd)); // serializzo e salvo... rawData = JsonConvert.SerializeObject(result); redisDb.StringSet(currKey, rawData, getRandTOut(redisLongTimeCache / 5)); } if (result == null) { result = new List(); } stopWatch.Stop(); TimeSpan ts = stopWatch.Elapsed; Log.Debug($"DossiersGetLastFilt | Read from {readType}: {ts.TotalMilliseconds}ms"); return result; } /// /// Inserimento nuovo record dossier /// /// /// public async Task DossiersInsert(DossierModel currDoss) { // aggiorno record sul DB bool answ = await SpecDbController.DossiersInsert(currDoss); return answ; } /// /// Effettua salvataggio snapshot parametri (con stored) + svuota eventuale cache redis /// /// macchina /// NUm massimo secondi per recuperare dati correnti /// DataOra riferimento x cui prendere valori antecedenti /// public async Task DossiersTakeParamsSnapshotLast(string IdxMacchina, DateTime dtMin, DateTime dtMax) { bool answ = false; await Task.Delay(1); Log.Info($"Richiesta snapshot per macchina {IdxMacchina} | periodo {dtMin} --> {dtMax}"); // chiamo stored x salvare parametri SpecDbController.DossiersTakeParamsSnapshotLast(IdxMacchina, dtMin, dtMax); // elimino cache redis... RedisValue pattern = new RedisValue($"{Utils.redisDossByMac}:*"); answ = await RedisFlushPatternAsync(pattern); Log.Info($"Svuotata cache dossier | {pattern}"); return answ; } /// /// Update valore dossier /// /// /// public async Task DossiersUpdateValore(DossierModel currDoss) { // aggiorno record sul DB bool answ = await SpecDbController.DossiersUpdateValore(currDoss); return answ; } /// /// Restitusice elenco aziende /// /// public Task> ElencoAziende() { return Task.FromResult(SpecDbController.AnagGruppiAziende()); } /// /// Restitusice elenco fasi /// /// public Task> ElencoGruppiFase() { List result = new List(); Stopwatch stopWatch = new Stopwatch(); stopWatch.Start(); string readType = "DB"; string currKey = $"{Utils.redisAnagGruppi}"; // cerco in redis dato valore sel macchina... RedisValue rawData = redisDb.StringGet(currKey); if (rawData.HasValue) { var rawResult = JsonConvert.DeserializeObject>($"{rawData}"); if (rawResult != null) { result = rawResult; } readType = "REDIS"; } else { result = SpecDbController.AnagGruppiFase(); // serializzo e salvo... rawData = JsonConvert.SerializeObject(result); redisDb.StringSet(currKey, rawData, getRandTOut(redisLongTimeCache / 5)); } if (result == null) { result = new List(); } stopWatch.Stop(); TimeSpan ts = stopWatch.Elapsed; Log.Debug($"ElencoGruppiFase | Read from {readType}: {ts.TotalMilliseconds}ms"); return Task.FromResult(result); } public Task> ElencoLink() { return Task.FromResult(SpecDbController.ElencoLink()); } /// /// Aggiunta record EventList /// /// /// public async Task EvListInsert(EventListModel newRec) { return await SpecDbController.EvListInsert(newRec); } /// /// Imposta in redis la scadenza della pagina x il reload /// /// /// public DateTime ExpiryReloadParamGet() { DateTime dtRif = DateTime.Now; string currKey = $"{Utils.redisParamPageExp}"; RedisValue rawData = redisDb.StringGet(currKey); if (rawData.HasValue) { dtRif = JsonConvert.DeserializeObject($"{rawData}"); } return dtRif; } /// /// Imposta in redis la scadenza della pagina x il reload /// /// /// public bool ExpiryReloadParamSet(DateTime expTime) { bool fatto = false; string currKey = $"{Utils.redisParamPageExp}"; string rawData = JsonConvert.SerializeObject(expTime); fatto = redisDb.StringSet(currKey, rawData); return fatto; } public async Task FlushRedisCache() { await Task.Delay(1); RedisValue pattern = Utils.RedValue("*"); bool answ = await RedisFlushPatternAsync(pattern); // rileggo vocabolario.,.. ObjVocabolario = VocabolarioGetAll(); return answ; } public async Task FlushRedisKey(string redKey) { await Task.Delay(1); RedisValue pattern = Utils.RedValue(redKey); bool answ = await RedisFlushPatternAsync(pattern); return answ; } public List FluxLogDtoGetByFlux(string Valore) { List answ = new List(); DossierFluxLogDTO? result = JsonConvert.DeserializeObject(Valore); if (result != null) { if (result.ODL != null) { answ = result .ODL .OrderBy(x => x.CodFlux) .ToList(); // inizializzo SE necessario foreach (var item in answ) { item.ValoreEdit = String.IsNullOrEmpty(item.ValoreEdit) ? item.Valore : item.ValoreEdit; } } } return answ; } /// /// Elenco ultimi n record flux log dato macchina e flusso (ordinato x data registrazione) /// /// Data massima x eventi /// Data minima x eventi /// * = tutte, altrimenti solo x una data macchina /// *=tutti, altrimenti solo selezionato /// numero massimo record da restituire /// public async Task> FluxLogGetLastFilt(DateTime DtMax, DateTime DtMin, string IdxMacchina, string CodFlux, int MaxRec, double redisCacheSec) { List? result = new List(); Stopwatch stopWatch = new Stopwatch(); stopWatch.Start(); string readType = "DB"; string currKey = $"{Utils.redisFluxLogFilt}:{IdxMacchina}:{CodFlux}:{MaxRec}:{DtMax:yyyyMMddHHmm}:{DtMin:yyyyMMddHHmm}"; // cerco in redis dato valore sel macchina... RedisValue rawData = redisDb.StringGet(currKey); if (rawData.HasValue) { result = JsonConvert.DeserializeObject>($"{rawData}"); readType = "REDIS"; } else { result = await Task.FromResult(SpecDbController.FluxLogGetLastFilt(DtMax, DtMin, IdxMacchina, CodFlux, MaxRec)); // serializzo e salvo... rawData = JsonConvert.SerializeObject(result); if (string.IsNullOrEmpty(canCacheParametri)) { canCacheParametri = await tryGetConfig("SPEC_ParametriEnableRedisCache"); } if (canCacheParametri != "false") { redisDb.StringSet(currKey, rawData, TimeSpan.FromSeconds(redisCacheSec)); } } if (result == null) { result = new List(); } stopWatch.Stop(); TimeSpan ts = stopWatch.Elapsed; Log.Debug($"FluxLogGetLastFilt | Read from {readType}: {ts.TotalMilliseconds}ms"); return result; } /// /// Init ricetta /// /// /// /// /// public RecipeModel InitRecipe(string confPath, int idxPODL, Dictionary CalcArgs) { return mongoController.InitRecipe(confPath, idxPODL, CalcArgs); } /// /// Restituisce il valore booleano se la macchina sia abilitata all'input /// /// /// public bool IobInsEnab(string idxMacchina) { bool answ = Convert.ToBoolean(mDatiMacchinaVal(idxMacchina, "insEnabled")); return answ; } /// /// /// id odl da cercare /// public async Task> ListGiacenze(int IdxOdl) { List? result = new List(); Stopwatch stopWatch = new Stopwatch(); stopWatch.Start(); string readType = "DB"; string currKey = $"{Utils.redisGiacenzaList}:{IdxOdl}"; // cerco in redis dato valore sel macchina... RedisValue rawData = redisDb.StringGet(currKey); if (rawData.HasValue) { result = JsonConvert.DeserializeObject>($"{rawData}"); readType = "REDIS"; } else { result = await Task.FromResult(SpecDbController.ListGiacenze(IdxOdl)); // serializzo e salvo... rawData = JsonConvert.SerializeObject(result); redisDb.StringSet(currKey, rawData, TimeSpan.FromSeconds(redisShortTimeCache)); } if (result == null) { result = new List(); } stopWatch.Stop(); TimeSpan ts = stopWatch.Elapsed; Log.Debug($"ListGiacenze | Read from {readType}: {ts.TotalMilliseconds}ms"); return result; } /// /// Elenco completo valori Macchine 2 Slave /// /// public List Macchine2SlaveGetAll() { List? result = new List(); Stopwatch stopWatch = new Stopwatch(); stopWatch.Start(); string readType = "DB"; string currKey = $"{Utils.redisBaseAddr}:M2STab"; // cerco in redis dato valore sel macchina... RedisValue rawData = redisDb.StringGet(currKey); if (rawData.HasValue) { result = JsonConvert.DeserializeObject>($"{rawData}"); readType = "REDIS"; } else { result = IocDbController.Macchine2Slave(); // serializzo e salvo... rawData = JsonConvert.SerializeObject(result); redisDb.StringSet(currKey, rawData, getRandTOut(redisLongTimeCache)); } if (result == null) { result = new List(); } stopWatch.Stop(); TimeSpan ts = stopWatch.Elapsed; Log.Debug($"Macchine2SlaveGetAll | Read from {readType}: {ts.TotalMilliseconds}ms"); return result; } /// /// Elenco di tutte le macchine gestite /// /// /// public async Task> MacchineGetFilt(string codGruppo) { List? result = new List(); Stopwatch stopWatch = new Stopwatch(); stopWatch.Start(); string readType = "DB"; string keyGrp = codGruppo != "*" ? codGruppo : "ALL"; string currKey = $"{Utils.redisMacList}:{keyGrp}"; // cerco in redis dato valore sel macchina... RedisValue rawData = redisDb.StringGet(currKey); if (rawData.HasValue) { result = JsonConvert.DeserializeObject>($"{rawData}"); readType = "REDIS"; } else { result = await Task.FromResult(SpecDbController.MacchineGetFilt(codGruppo)); // serializzo e salvo... rawData = JsonConvert.SerializeObject(result); redisDb.StringSet(currKey, rawData, getRandTOut(redisLongTimeCache)); } if (result == null) { result = new List(); } stopWatch.Stop(); TimeSpan ts = stopWatch.Elapsed; Log.Debug($"MacchineGetAll | Read from {readType}: {ts.TotalMilliseconds}ms"); return result; } /// /// Verifica se la macchina abbia un codice PATH ricette associato /// /// /// public async Task MacchineRecipeArchive(string idxMacchina) { string? result = ""; Stopwatch stopWatch = new Stopwatch(); stopWatch.Start(); string readType = "DB"; string currKey = $"{Utils.redisMacRecipePath}:{idxMacchina}"; // cerco in redis dato valore sel macchina... RedisValue rawData = redisDb.StringGet(currKey); if (rawData.HasValue) { result = JsonConvert.DeserializeObject($"{rawData}"); readType = "REDIS"; } else { //recupero elenco macchine... var machineList = await MacchineGetFilt("*"); var currMach = machineList.Where(x => x.IdxMacchina == idxMacchina).FirstOrDefault(); result = currMach != null ? currMach.RecipeArchivePath : null; // serializzo e salvo... rawData = JsonConvert.SerializeObject(result); redisDb.StringSet(currKey, rawData, getRandTOut(redisLongTimeCache)); } stopWatch.Stop(); TimeSpan ts = stopWatch.Elapsed; Log.Debug($"MacchineRecipeArchive | Read from {readType}: {ts.TotalMilliseconds}ms"); return result ?? ""; } /// /// Verifica se la macchina abbia un codice CONF ricetta associato /// /// /// public async Task MacchineRecipeConf(string idxMacchina) { string? result = ""; Stopwatch stopWatch = new Stopwatch(); stopWatch.Start(); string readType = "DB"; string currKey = $"{Utils.redisMacRecipeConf}:{idxMacchina}"; // cerco in redis dato valore sel macchina... RedisValue rawData = redisDb.StringGet(currKey); if (rawData.HasValue) { result = JsonConvert.DeserializeObject($"{rawData}"); readType = "REDIS"; } else { //recupero elenco macchine... var machineList = await MacchineGetFilt("*"); var currMach = machineList.Where(x => x.IdxMacchina == idxMacchina).FirstOrDefault(); result = currMach != null ? currMach.RecipePath : null; // serializzo e salvo... rawData = JsonConvert.SerializeObject(result); redisDb.StringSet(currKey, rawData, getRandTOut(redisLongTimeCache)); } stopWatch.Stop(); TimeSpan ts = stopWatch.Elapsed; Log.Debug($"MacchineRecipeConf | Read from {readType}: {ts.TotalMilliseconds}ms"); return result ?? ""; } /// /// Elenco id Macchine che abbiano dati FLuxLog, nel periodo indicato /// /// /// /// public async Task> MacchineWithFlux(DateTime dtStart, DateTime dtEnd) { List? result = new List(); Stopwatch stopWatch = new Stopwatch(); stopWatch.Start(); string readType = "DB"; string currKey = $"{Utils.redisMacByFlux}:{dtStart:yyyyMMddHHmm}:{dtEnd:yyyyMMddHHmm}"; // cerco in redis dato valore sel macchina... RedisValue rawData = redisDb.StringGet(currKey); if (rawData.HasValue) { result = JsonConvert.DeserializeObject>($"{rawData}"); readType = "REDIS"; } else { result = await SpecDbController.MacchineWithFlux(dtStart, dtEnd); // serializzo e salvo... rawData = JsonConvert.SerializeObject(result); redisDb.StringSet(currKey, rawData, getRandTOut(redisLongTimeCache)); } if (result == null) { result = new List(); } stopWatch.Stop(); TimeSpan ts = stopWatch.Elapsed; Log.Debug($"MacchineWithFlux | Read from {readType}: {ts.TotalMilliseconds}ms"); return result; } /// /// Restituisce valore di una singola chiave del dizionario DatiMacchina /// /// /// /// public string mDatiMacchinaVal(string idxMacchina, string chiave) { string answ = ""; try { answ = mDatiMacchine(idxMacchina)[chiave]; } catch { } return answ; } /// /// Restitusice elenco KVP dei campi DatiMacchine + StatoMacchine per l'impianto indicato /// /// /// public Dictionary mDatiMacchine(string idxMacchina) { // hard coded dimensione vettore DatiMacchine Dictionary answ = new Dictionary(); // ORA recupero da memoria redis... try { var currHash = Utils.dtMaccHash(idxMacchina); answ = RedisGetHashDict(currHash); // se è vuoto... leggo da DB e popolo! if (answ.Count == 0) { answ = ResetDatiMacchina(idxMacchina); } } catch (Exception exc) { Log.Error($"Errore in compilazione dati Macchine x Redis - idxMacchina {idxMacchina}:{Environment.NewLine}{exc}"); } return answ; } /// /// Restitusice elenco KVP dei TASK (da passare a IOB-WIN) per l'impianto indicato /// /// /// public Dictionary mOptParMacchina(string idxMacchina) { // hard coded dimensione vettore DatiMacchine Dictionary answ = new Dictionary(); // ORA recupero da memoria redis... try { RedisKey currHash = Utils.OptParHash(idxMacchina); answ = RedisGetHashDict(currHash); } catch (Exception exc) { Log.Error($"Errore in compilazione dati OPT PARAM x Redis - idxMacchina {idxMacchina}{Environment.NewLine}{exc}"); } return answ; } /// /// Elenco ODL dato batch selezionato /// /// Batch richiesto /// public async Task> OdlByBatch(string BatchSel) { List? result = new List(); Stopwatch stopWatch = new Stopwatch(); stopWatch.Start(); string readType = "DB"; string currKey = Utils.redisOdlByBatch; // cerco in redis dato valore sel macchina... RedisValue rawData = redisDb.StringGet(currKey); if (rawData.HasValue) { result = JsonConvert.DeserializeObject>($"{rawData}"); readType = "REDIS"; } else { result = await Task.FromResult(SpecDbController.OdlByBatch(BatchSel)); // serializzo e salvo... rawData = JsonConvert.SerializeObject(result); redisDb.StringSet(currKey, rawData, getRandTOut(redisLongTimeCache)); } if (result == null) { result = new List(); } stopWatch.Stop(); TimeSpan ts = stopWatch.Elapsed; Log.Debug($"OdlByBatch | Read from {readType}: {ts.TotalMilliseconds}ms"); return result; } /// /// ODL da chiave /// /// /// public ODLExpModel OdlByKey(int IdxOdl) { ODLExpModel? result = new ODLExpModel(); Stopwatch stopWatch = new Stopwatch(); stopWatch.Start(); string readType = "DB"; result = SpecDbController.OdlByKey(IdxOdl); stopWatch.Stop(); TimeSpan ts = stopWatch.Elapsed; Log.Debug($"OdlByKey | Read from {readType}: {ts.TotalMilliseconds}ms"); return result; } /// /// Effettua chiusura dell'ODL indicato, andand /// /// idx odl da chiudere /// idx macchina /// matricola operatore /// indica se confermare i pezzi priam di chiudere ODL public async Task ODLClose(int idxOdl, string idxMacchina, int matrOpr, bool confPezzi) { bool fatto = false; await Task.Delay(1); // recupero dati x conf modalità conferma var configData = await ConfigGetAll(); if (configData != null) { bool confRett = false; var currRec = configData.FirstOrDefault(x => x.Chiave == "confRett"); if (currRec != null) { bool.TryParse(currRec.Valore, out confRett); } int modoConfProd = 0; currRec = configData.FirstOrDefault(x => x.Chiave == "modoConfProd"); if (currRec != null) { int.TryParse(currRec.Valore, out modoConfProd); } // chiamo metodo conferma! fatto = await SpecDbController.ODLClose(idxOdl, idxMacchina, matrOpr, confPezzi, confRett, modoConfProd); } return fatto; } /// /// Record ODL da chaive /// /// public async Task OdlGetByKey(int IdxOdl) { await Task.Delay(1); var dbResult = SpecDbController.OdlGetByKey(IdxOdl); return dbResult; } /// /// ODL correnti (tutti) /// /// /// public List OdlGetCurrent() { List? dbResult = new List(); Stopwatch stopWatch = new Stopwatch(); stopWatch.Start(); string readType = "DB"; string currKey = $"{Utils.redisOdlCurrByMac}"; // cerco in redis dato valore sel macchina... RedisValue rawData = redisDb.StringGet(currKey); if (rawData.HasValue) { try { dbResult = JsonConvert.DeserializeObject>($"{rawData}"); } catch { } readType = "REDIS"; } else { dbResult = SpecDbController.OdlGetCurrent().Select(x => x.IdxMacchina).Distinct().ToList(); rawData = JsonConvert.SerializeObject(dbResult); redisDb.StringSet(currKey, rawData, TimeSpan.FromSeconds(3)); } if (dbResult == null) { dbResult = new List(); } stopWatch.Stop(); TimeSpan ts = stopWatch.Elapsed; Log.Debug($"OdlGetCurrent | Read from {readType}: {ts.TotalMilliseconds}ms"); return dbResult; } /// /// elenco TUTTI gli ODL /// /// /// public List OdlListAll() { List? result = new List(); Stopwatch stopWatch = new Stopwatch(); stopWatch.Start(); string readType = "DB"; result = SpecDbController.OdlListAll(); stopWatch.Stop(); TimeSpan ts = stopWatch.Elapsed; Log.Debug($"OdlListAll | Read from {readType}: {ts.TotalMilliseconds}ms"); return result; } /// /// Elenco ODL filtrati x stato, articolo, KeyRich (che contiene stato) /// /// Stato ODL: true=in corso/completato /// Cod articolo /// KeyRich (parziale) da cercare (es cod stato x yacht) /// Reparto selezionato /// Macchina selezionata /// Data inizio /// Data fine /// public async Task> OdlListGetFilt(bool inCorso, string codArt, string keyRichPart, string Reparto, string IdxMacchina, DateTime startDate, DateTime endDate) { List? result = new List(); Stopwatch stopWatch = new Stopwatch(); stopWatch.Start(); string readType = "DB"; string currKey = $"{Utils.redisOdlList}:{inCorso}:{codArt}:{keyRichPart}:{Reparto}:{IdxMacchina}:{startDate:yyyyMMdd_HHmmss}:{endDate:yyyyMMdd_HHmmss}"; // cerco in redis dato valore sel macchina... RedisValue rawData = redisDb.StringGet(currKey); if (rawData.HasValue) { result = JsonConvert.DeserializeObject>($"{rawData}"); readType = "REDIS"; } else { result = await Task.FromResult(SpecDbController.ListODLFilt(inCorso, codArt, keyRichPart, Reparto, IdxMacchina, startDate, endDate)); // serializzo e salvo... rawData = JsonConvert.SerializeObject(result); redisDb.StringSet(currKey, rawData, TimeSpan.FromSeconds(redisShortTimeCache)); } if (result == null) { result = new List(); } stopWatch.Stop(); TimeSpan ts = stopWatch.Elapsed; Log.Debug($"OdlListGetFilt | Read from {readType}: {ts.TotalMilliseconds}ms"); return result; } /// /// Elenco di tutti i parametri filtrati x macchina /// /// * = tutte, altrimenti solo x una data macchina /// public async Task> ParametriGetFilt(string IdxMacchina) { List? result = new List(); Stopwatch stopWatch = new Stopwatch(); stopWatch.Start(); string readType = "DB"; string currKey = $"{Utils.redisFluxByMac}:{IdxMacchina}"; // cerco in redis dato valore sel macchina... RedisValue rawData = redisDb.StringGet(currKey); if (rawData.HasValue) { result = JsonConvert.DeserializeObject>($"{rawData}"); readType = "REDIS"; } else { result = await Task.FromResult(SpecDbController.ParametriGetFilt(IdxMacchina)); // serializzo e salvo... rawData = JsonConvert.SerializeObject(result); redisDb.StringSet(currKey, rawData, getRandTOut(redisLongTimeCache)); } if (result == null) { result = new List(); } stopWatch.Stop(); TimeSpan ts = stopWatch.Elapsed; Log.Debug($"ParametriGetFilt | Read from {readType}: {ts.TotalMilliseconds}ms"); return result; } /// /// Eliminazione record selezionato /// /// /// public async Task POdlDeleteRecord(PODLExpModel currRec) { var dbResult = await SpecDbController.PODLDeleteRecord(currRec); // elimino cache redis... await POdlFlushCache(); await Task.Delay(1); return dbResult; } /// /// Avvio fase setup per il record selezionato /// /// /// public async Task POdlDoSetup(PODLExpModel currRec) { var dbResult = await SpecDbController.PODL_startSetup(currRec, 0, 1, 1, "", DateTime.Now); // elimino cache redis... await POdlFlushCache(); await Task.Delay(1); return dbResult; } /// /// Recupero PODL da chiave /// /// /// public async Task POdlGetByKey(int idxPODL) { PODLModel result = new PODLModel(); if (idxPODL != 0) { Stopwatch stopWatch = new Stopwatch(); stopWatch.Start(); string readType = "DB"; string currKey = $"{Utils.redisPOdlByPOdl}:{idxPODL}"; // cerco in redis dato valore sel macchina... RedisValue rawData = redisDb.StringGet(currKey); if (rawData.HasValue) { var rawResult = JsonConvert.DeserializeObject($"{rawData}"); if (rawResult != null) { result = rawResult; readType = "REDIS"; } } else { result = await SpecDbController.PODL_getByKey(idxPODL); // serializzo e salvo... rawData = JsonConvert.SerializeObject(result); redisDb.StringSet(currKey, rawData, getRandTOut(redisLongTimeCache)); } if (result == null) { result = new PODLModel(); } stopWatch.Stop(); TimeSpan ts = stopWatch.Elapsed; Log.Trace($"POdlGetByKey | Read from {readType}: {ts.TotalMilliseconds}ms"); } else { Log.Debug("Errore IdxPODL = 0"); } return result; } /// /// Recupero PODL da IdxODL /// /// /// public PODLModel POdlGetByOdl(int idxODL) { PODLModel result = new PODLModel(); if (idxODL != 0) { Stopwatch stopWatch = new Stopwatch(); stopWatch.Start(); string readType = "DB"; string currKey = $"{Utils.redisPOdlByOdl}:{idxODL}"; // cerco in redis dato valore sel macchina... RedisValue rawData = redisDb.StringGet(currKey); if (rawData.HasValue) { var rawResult = JsonConvert.DeserializeObject($"{rawData}"); if (rawResult != null) { result = rawResult; } readType = "REDIS"; } else { result = SpecDbController.PODL_getByOdl(idxODL); // serializzo e salvo... rawData = JsonConvert.SerializeObject(result); redisDb.StringSet(currKey, rawData, getRandTOut(redisLongTimeCache)); } if (result == null) { result = new PODLModel(); } stopWatch.Stop(); TimeSpan ts = stopWatch.Elapsed; Log.Trace($"POdlGetByOdl | Read from {readType}: {ts.TotalMilliseconds}ms"); } else { Log.Debug("Errore IdxODL = 0"); } return result; } /// /// Elenco PODL non avviati filtrati x articolo, KeyRich (che contiene stato) /// /// Solo lanciati (1) o ancora disponibili (0) /// KeyRich (parziale) da cercare (es cod stato x yacht) /// Macchina /// Gruppo /// Data inizio /// Data fine /// public async Task> POdlListGetFilt(bool lanciato, string keyRichPart, string idxMacchina, string codGruppo, DateTime startDate, DateTime endDate) { List? result = new List(); Stopwatch stopWatch = new Stopwatch(); stopWatch.Start(); string readType = "DB"; string currKey = $"{Utils.redisPOdlList}:{codGruppo}:{idxMacchina}:{keyRichPart}:{lanciato}:{startDate:yyyyMMdd_HHmmss}:{endDate:yyyyMMdd_HHmmss}"; // cerco in redis dato valore sel macchina... RedisValue rawData = redisDb.StringGet(currKey); if (rawData.HasValue) { result = JsonConvert.DeserializeObject>($"{rawData}"); readType = "REDIS"; } else { result = await Task.FromResult(SpecDbController.ListPODLFilt(lanciato, keyRichPart, idxMacchina, codGruppo, startDate, endDate)); // serializzo e salvo... rawData = JsonConvert.SerializeObject(result); redisDb.StringSet(currKey, rawData, TimeSpan.FromSeconds(redisShortTimeCache)); } if (result == null) { result = new List(); } stopWatch.Stop(); TimeSpan ts = stopWatch.Elapsed; Log.Debug($"POdlListGetFilt | Read from {readType}: {ts.TotalMilliseconds}ms"); return result; } /// /// Aggiornamento record selezionato /// /// /// public async Task POdlUpdateRecord(PODLModel currRec) { var dbResult = await SpecDbController.PODLUpdateRecord(currRec); // elimino cache redis... await POdlFlushCache(); return dbResult; } /// /// Ricerca ricetta su MongoDB dato PODL /// /// /// public async Task RecipeGetByPODL(int idxPODL) { RecipeModel? result = null; Stopwatch stopWatch = new Stopwatch(); stopWatch.Start(); string readType = "MongoDB"; result = await mongoController.RecipeGetByPODL(idxPODL); stopWatch.Stop(); TimeSpan ts = stopWatch.Elapsed; Log.Debug($"RecipeGetByPODL | Read from {readType}: {ts.TotalMilliseconds}ms"); return result; } /// /// Salva ricetta su MongoDB /// /// /// public async Task RecipeSetByPODL(RecipeModel currRecord) { bool answ = false; answ = await mongoController.RecipeSetByPODL(currRecord); if (answ) { await POdlFlushCache(); } return answ; } /// /// Effettua conteggio chaivi REDIS dato pattern ricerca /// /// /// public int RedisCountKey(string keyPattern) { int num = 0; keyPattern = (string.IsNullOrEmpty(keyPattern) ? "**" : keyPattern); try { var listEndpoints = redisConnAdmin.GetEndPoints(); foreach (var endPoint in listEndpoints) { var server = redisConnAdmin.GetServer(endPoint); foreach (RedisKey item in server.Keys(pattern: keyPattern, database: redisDb.Database, pageSize: 250, cursor: 0L)) { num++; } } } catch (Exception arg) { Log.Error($"Eccezione in RedisCountKey{Environment.NewLine}{arg}"); } return num; } /// /// Esegue eliminazione memoria redis keyVal /// /// /// public bool RedisDelKey(string keyVal) { bool answ = false; var listEndpoints = redisConnAdmin.GetEndPoints(); foreach (var endPoint in listEndpoints) { var server = redisConnAdmin.GetServer(endPoint); if (server != null) { redisDb.KeyDelete((RedisKey)keyVal); answ = true; } } return answ; } /// /// Esegue flush memoria redis dato keyVal /// /// /// public bool RedisFlushPattern(string pattern) { bool answ = false; var listEndpoints = redisConnAdmin.GetEndPoints(); foreach (var endPoint in listEndpoints) { //var server = redisConnAdmin.GetServer(listEndpoints[0]); var server = redisConnAdmin.GetServer(endPoint); if (server != null) { var keyList = server.Keys(redisDb.Database, pattern); foreach (var item in keyList) { redisDb.KeyDelete(item); } answ = true; } } return answ; } /// /// Esegue flush memoria redis dato keyVal, async /// /// /// public async Task RedisFlushPatternAsync(RedisValue pattern) { bool answ = false; var listEndpoints = redisConnAdmin.GetEndPoints(); foreach (var endPoint in listEndpoints) { var server = redisConnAdmin.GetServer(endPoint); if (server != null) { var keyList = server.Keys(redisDb.Database, pattern); foreach (var item in keyList) { await redisDb.KeyDeleteAsync(item); } answ = true; } } return answ; } public KeyValuePair[] RedisGetHash(RedisKey redKey) { HashEntry[] rawData = redisDb.HashGetAll(redKey); var result = rawData.Where(x => !x.Name.IsNull).Select(x => new KeyValuePair($"{x.Name}", $"{x.Value}")).ToArray(); return result; } public async Task[]> RedisGetHashAsync(string redKey) { HashEntry[] rawData = await redisDb.HashGetAllAsync(redKey); var result = rawData.Where(x => !x.Name.IsNull).Select(x => new KeyValuePair($"{x.Name}", $"{x.Value}")).ToArray(); return result; } public Dictionary RedisGetHashDict(RedisKey hashKey) { HashEntry[] rawData = redisDb.HashGetAll(hashKey); var result = rawData.Where(x => !x.Name.IsNull).ToDictionary(x => x.Name.ToString(), x => x.Value.ToString()); return result; } public string RedisGetHashField(RedisKey key, string hashField) { string result = ""; try { RedisValue hashField2 = hashField; result = redisDb.HashGet(key, hashField2).ToString(); } catch (Exception exc) { Log.Error($"Errore in RedisGetHashField{Environment.NewLine}{exc}"); } return result; } public bool RedisHashPresent(RedisKey key) { bool result = false; try { result = redisDb.HashGetAll(key).Length != 0; } catch (Exception arg) { Log.Error($"Errore in redHashPresent per la key {key}{Environment.NewLine}{arg}"); } return result; } public bool RedisHashPresentSz(string key) { return RedisHashPresent((RedisKey)key); } public bool RedisKeyPresent(RedisKey key) { bool result = false; try { result = redisDb.KeyExists(key); } catch (Exception arg) { Log.Error($"Errore in redKeyPresent per la key {key}:{Environment.NewLine}{arg}"); } return result; } public bool RedisKeyPresentSz(string key) { bool result = false; try { RedisKey key2 = key; result = RedisKeyPresent(key2); } catch { } return result; } public bool RedisSetHash(RedisKey redKey, KeyValuePair[] valori, double expireSeconds = -1.0) { bool answ = false; answ = RedisSetHash(redKey, valori); if (expireSeconds > 0.0) { redisDb.KeyExpire(redKey, DateTime.Now.AddSeconds(expireSeconds)); } return answ; } public bool RedisSetHash(RedisKey redKey, KeyValuePair[] valori) { bool answ = false; HashEntry[] redHash = valori.Select(x => new HashEntry(x.Key, x.Value)).ToArray(); redisDb.HashSet(redKey, redHash); answ = true; return answ; } public bool RedisSetHashDict(RedisKey redKey, Dictionary valori, double expireSeconds = -1.0) { bool answ = false; answ = RedisSetHashDict(redKey, valori); if (expireSeconds > 0.0) { redisDb.KeyExpire(redKey, DateTime.Now.AddSeconds(expireSeconds)); } return answ; } public bool RedisSetHashDict(RedisKey redKey, Dictionary valori) { bool answ = false; HashEntry[] redHash = valori.Select(x => new HashEntry(x.Key, x.Value)).ToArray(); redisDb.HashSet(redKey, redHash); answ = true; return answ; } public bool RedisSetKey(string valKey, string redVal) { bool answ = redisDb.StringSet(Utils.RedKeyHash(valKey), redVal); return answ; } public bool RedisSetKey(RedisKey valKey, string redVal, int TTL_sec) { bool answ = redisDb.StringSet(Utils.RedKeyHash(valKey), redVal, TimeSpan.FromSeconds(TTL_sec)); return answ; } /// /// Restitusice elenco KVP dei campi DatiMacchine + StatoMacchine per l'impianto indicato /// /// /// public Dictionary ResetDatiMacchina(string idxMacc) { var currHash = Utils.dtMaccHash(idxMacc); // inizio con un bel reset... RedisFlushPattern($"{currHash}"); Dictionary? result = new Dictionary(); Stopwatch stopWatch = new Stopwatch(); stopWatch.Start(); string readType = "DB"; var dbResults = IocDbController.VMSFDGetByMacc(idxMacc); // converto in formato dizionario... if (dbResults != null && dbResults.Count > 0) { var rowResult = dbResults[0]; // salvo 1:1 i valori... STATO result.Add("IdxMicroStato", $"{rowResult.IdxMicroStato}"); result.Add("IdxStato", $"{rowResult.IdxStato}"); result.Add("CodArticolo", $"{rowResult.CodArticolo}"); result.Add("insEnabled", $"{rowResult.InsEnabled}"); result.Add("sLogEnabled", $"{rowResult.SLogEnabled}"); result.Add("pallet", $"{rowResult.Pallet}"); result.Add("CodArticolo_A", $"{rowResult.CodArticoloA}"); result.Add("CodArticolo_B", $"{rowResult.CodArticoloB}"); result.Add("TempoCicloBase", $"{rowResult.TempoCicloBase}"); result.Add("PzPalletProd", $"{rowResult.PzPalletProd}"); result.Add("MatrOpr", $"{rowResult.MatrOpr}"); result.Add("lastVal", $"{rowResult.LastVal}"); result.Add("TCBase", $"{rowResult.TempoCicloBase}"); //...e SETUP result.Add("CodMacc", $"{rowResult.Codmacchina}"); result.Add("IdxFamIn", $"{rowResult.IdxFamigliaIngresso}"); result.Add("Multi", $"{rowResult.Multi}"); result.Add("BitFilt", $"{rowResult.BitFilt}"); result.Add("MaxVal", $"{rowResult.MaxVal}"); result.Add("BSR", $"{rowResult.Bsr}"); result.Add("ExplodeBit", $"{rowResult.ExplodeBit}"); result.Add("NumBit", $"{rowResult.NumBit}"); result.Add("IdxFamMacc", $"{rowResult.IdxFamiglia}"); result.Add("simplePallet", $"{rowResult.SimplePallet}"); result.Add("palletChange", $"{rowResult.PalletChange}"); } // cerco info Master/slave... var m2sTab = Macchine2SlaveGetAll(); string isMaster = m2sTab.Where(x => x.IdxMacchina == idxMacc).Count() > 0 ? "1" : "0"; string isSlave = m2sTab.Where(x => x.IdxMacchinaSlave == idxMacc).Count() > 0 ? "1" : "0"; result.Add("Master", isMaster); result.Add("Slave", isSlave); // durata cache in secondi dal valore insEnabled... double numSecCache = 60 * ((result["insEnabled"].ToLower() == "true") ? redisShortTimeCache / 4 : redisShortTimeCache); // ...e salvo... RedisSetHashDict(currHash, result, numSecCache); if (result == null) { result = new Dictionary(); } stopWatch.Stop(); TimeSpan ts = stopWatch.Elapsed; Log.Debug($"GetCurrMSFDMacc | Read from {readType}: {ts.TotalMilliseconds}ms"); return result; } /// /// Resetta (rileggendo) i dati della State Machine ingressi nel formato /// key: cState_nVal (current MICRO-STATE + "_" + new Value) /// value: iTipoEv_nState (IdxTipoEv da trasmettere + New MICRO-STATE) /// /// /// public KeyValuePair[] resetSMI(int idxFamIn) { var currHash = Utils.hSMI(idxFamIn); // leggo da DB... var tabSMI = IocDbController.StateMachineIngressi(idxFamIn); KeyValuePair[] answ = new KeyValuePair[tabSMI.Count]; // salvo tutti i valori StateMachineIngressi... int i = 0; string key = ""; string val = ""; foreach (var item in tabSMI) { key = string.Format("{0}_{1}", item.IdxMicroStato, item.ValoreIngresso); val = string.Format("{0}_{1}", item.IdxTipoEvento, item.NextIdxMicroStato); answ[i] = new KeyValuePair(key, val); i++; } // verifico il timeout (default 60 sec...) var sTOutSmi = tryGetConfig("TmOut.SMI").Result; int tOut = 60; if (!string.IsNullOrEmpty(sTOutSmi)) { int.TryParse(sTOutSmi, out tOut); } // salvo in redis! RedisSetHash(currHash, answ, tOut); return answ; } /// /// scrive un evento di keepalive sulla tabella /// /// /// /// public void ScriviKeepAlive(string IdxMacchina, DateTime oraMacchina) { string nomeVar = string.Format("KeepAlive:{0}", IdxMacchina); // cerco se ho keep alive in redis, bool keyPresent = false; DateTime adesso = DateTime.Now; var currKey = Utils.RedKeyHash(nomeVar); try { keyPresent = RedisKeyPresent(currKey); } catch { } // se NON presente salvo in REDIS con TTL 10 sec e sul DB... if (!keyPresent) { RedisSetKey(currKey, adesso.ToString("s"), 10); try { Log.Trace($"Scrittura keep alive! IdxMacchina: {IdxMacchina}"); // effettuo scrittura sul DB IocDbController.KeepAliveUpsert(IdxMacchina, DateTime.Now, oraMacchina); } catch (Exception exc) { Log.Error($"Errore in scrittura keep alive!{Environment.NewLine}oraMacchina: {oraMacchina} - IdxMacchina: {IdxMacchina}{Environment.NewLine}{exc}"); } } } /// /// Restitusice elenco KVP dei campi della State Machine ingressi nel formato /// key: cState_nVal (current MICRO-STATE + "_" + new Value) /// value: iTipoEv_nState (IdxTipoEv da trasmettere + New MICRO-STATE /// /// /// public KeyValuePair[] StateMachInByKey(int idxFamIn) { // hard coded dimensione vettore DatiMacchine KeyValuePair[] answ = new KeyValuePair[1]; // iniziualizzo con un valore... 0/0 answ[0] = new KeyValuePair("0", "0"); // ORA recupero da memoria redis... try { var currHash = Utils.hSMI(idxFamIn); answ = RedisGetHash(currHash); // se è vuoto... leggo da DB e popolo! if (answ.Length == 0) { answ = resetSMI(idxFamIn); } } catch (Exception exc) { Log.Error($"Errore in compilazione State Machine Ingressi x Redis:{Environment.NewLine}{exc}"); } return answ; } /// /// Statistiche ODL calcolate (da stored stp_STAT_ODL) /// /// public Task> StatOdl(int IdxOdl) { return SpecDbController.OdlStart(IdxOdl); } /// /// restituisce il valore da REDIS associato al tag richeisto /// /// Chiave in cui cercare il valore /// public string TagConfGetKey(string redKey) { string outVal = ""; // cerco in REDIS la conf x l'IOB var rawData = redisDb.StringGet(redKey); if (!string.IsNullOrEmpty(rawData)) { outVal = $"{rawData}"; } return outVal; } /// /// Elenco setup dei tag conf correnti /// /// public Task>> TagsGetAll() { return Task.FromResult(currTagConf); } /// /// Esegue traduzione dato vocabolario da Lingua + Lemma /// /// /// /// public string Traduci(string lemma, string lingua) { string answ = $"[{lemma}]"; // verifico se ho qualcosa nell'obj vocabolario... if (ObjVocabolario == null || ObjVocabolario.Count == 0) { // inizializzo il vocabolario... ObjVocabolario = VocabolarioGetAll(); } var record = ObjVocabolario.Where(x => x.Lingua == lingua && x.Lemma == lemma).FirstOrDefault(); if (record != null) { answ = record.Traduzione; } return answ; } /// /// Restituisce valore della stringa (SE disponibile) /// /// /// public async Task tryGetConfig(string keyName) { string answ = ""; // preselezione valori var configData = await ConfigGetAll(); var currRec = configData.FirstOrDefault(x => x.Chiave == keyName); if (currRec != null) { answ = currRec.Valore; } return answ; } public async Task updateDossierValue(DossierModel currDoss, FluxLogDTO editFL) { bool answ = false; // recupero intero set valori dossier deserializzando... var fluxLogList = FluxLogDtoGetByFlux(currDoss.Valore); await Task.Delay(1); // se tutto ok if (fluxLogList != null) { // da provare...!!!! // elimino vecchio record var currRec = fluxLogList.FirstOrDefault(x => x.CodFlux == editFL.CodFlux && x.dtEvento == editFL.dtEvento); if (currRec != null) { fluxLogList.Remove(currRec); // aggiungo nuovo fluxLogList.Add(editFL); } // serializzo nuovamente valore DossierFluxLogDTO? result = new DossierFluxLogDTO(); var ODLflux = result.ODL.ToList(); foreach (var item in fluxLogList) { ODLflux.Add(item); } DossierFluxLogDTO updatedResult = new DossierFluxLogDTO() { ODL = ODLflux }; string rawVal = JsonConvert.SerializeObject(updatedResult); currDoss.Valore = rawVal; // aggiorno record sul DB await SpecDbController.DossiersUpdateValore(currDoss); } return answ; } /// /// Restituisce il valore SPECIFICATO per la state machine ingressi /// value: iTipoEv_nState (IdxTipoEv da trasmettere + New MICRO-STATE) /// /// /// /// /// public string ValoreSMI(int idxFamIn, int idxMicroStato, int valoreIn) { var currHash = Utils.hSMI(idxFamIn); string field = $"{idxMicroStato}_{valoreIn}"; return RedisGetHashField(currHash, field); } /// /// Elenco completo tabella Vocabolario /// /// public List VocabolarioGetAll() { Stopwatch stopWatch = new Stopwatch(); stopWatch.Start(); List? result = new List(); string source = "REDIS"; // cerco in redis... RedisValue rawData = redisDb.StringGet(Utils.redisVocabolario); if (!string.IsNullOrEmpty($"{rawData}")) { result = JsonConvert.DeserializeObject>($"{rawData}"); } else { result = SpecDbController.VocabolarioGetAll(); // serializzo e salvo... rawData = JsonConvert.SerializeObject(result); redisDb.StringSet(Utils.redisVocabolario, rawData, getRandTOut(redisLongTimeCache / 5)); source = "DB"; } stopWatch.Stop(); TimeSpan ts = stopWatch.Elapsed; Log.Debug($"VocabolarioGetAll Read from {source}: {ts.TotalMilliseconds}ms"); if (result == null) { result = new List(); } return result; } #endregion Public Methods #region Protected Fields protected Random rand = new Random(); #endregion Protected Fields #region Protected Properties protected string canCacheParametri { get; set; } = ""; #endregion Protected Properties #region Protected Methods /// /// Restituisce un timeout dai minuti richiesti + tempo random 1..60 sec /// /// /// protected TimeSpan getRandTOut(double stdMinutes) { double rndValue = stdMinutes + (double)rand.Next(1, 60) / 60; return TimeSpan.FromMinutes(rndValue); } #endregion Protected Methods #region Private Fields private static IConfiguration _configuration = null!; private static ILogger _logger = null!; private static Logger Log = LogManager.GetCurrentClassLogger(); /// /// Oggetto vocabolario x uso continuo traduzione /// private List ObjVocabolario = new List(); /// /// Oggetto per connessione a REDIS /// private ConnectionMultiplexer redisConn = null!; /// /// Oggetto per connessione a REDIS modalità admin (ex flux dati) /// private ConnectionMultiplexer redisConnAdmin = null!; /// /// Oggetto DB redis da impiegare x chiamate R/W /// private IDatabase redisDb = null!; private int redisLongTimeCache = 5; private int redisShortTimeCache = 2; #endregion Private Fields #region Private Methods private async Task POdlFlushCache() { bool answ = false; RedisValue pattern = new RedisValue($"{Utils.redisXdlData}:*"); answ = await RedisFlushPatternAsync(pattern); pattern = new RedisValue($"{Utils.redisPOdlByOdl}:*"); answ = await RedisFlushPatternAsync(pattern); pattern = new RedisValue($"{Utils.redisPOdlByPOdl}:*"); answ = await RedisFlushPatternAsync(pattern); pattern = new RedisValue($"{Utils.redisPOdlList}:*"); answ = await RedisFlushPatternAsync(pattern); return answ; } private async Task resetCacheArticoli() { RedisValue pattern = new RedisValue($"{Utils.redisArtByDossier}:*"); await RedisFlushPatternAsync(pattern); pattern = new RedisValue($"{Utils.redisArtList}:*"); await RedisFlushPatternAsync(pattern); } #endregion Private Methods } }