From 6b49cb29fe697943d8ef8d6cc3fda32db739a496 Mon Sep 17 00:00:00 2001 From: Samuele Locatelli Date: Thu, 28 May 2026 18:49:10 +0200 Subject: [PATCH] Ancora updaate caching e gestione oggetti --- MP.Data/Controllers/MpSpecController.cs | 62 ++++--- MP.Data/Services/TabDataService.cs | 2 +- MP.SPEC/Components/DossiersFilter.razor | 24 +-- MP.SPEC/Components/DossiersFilter.razor.cs | 47 +++--- MP.SPEC/Components/ListODL.razor.cs | 6 +- MP.SPEC/Components/ParamsFilter.razor.cs | 4 +- MP.SPEC/Data/MpDataService.cs | 166 +++++++++++++------ MP.SPEC/MP.SPEC.csproj | 2 +- MP.SPEC/Pages/Articoli.razor | 9 +- MP.SPEC/Pages/DOSS.razor | 25 +-- MP.SPEC/Pages/DOSS.razor.cs | 6 +- MP.SPEC/Pages/RepStop.razor.cs | 4 +- MP.SPEC/Resources/ChangeLog.html | 2 +- MP.SPEC/Resources/VersNum.txt | 2 +- MP.SPEC/Resources/manifest.xml | 2 +- MP.SPEC/appsettings.Production.json | 1 + MP.SPEC/appsettings.json | 1 + Refactor_Plan.md | 184 ++++++--------------- 18 files changed, 281 insertions(+), 268 deletions(-) diff --git a/MP.Data/Controllers/MpSpecController.cs b/MP.Data/Controllers/MpSpecController.cs index 63e33058..dd60d20d 100644 --- a/MP.Data/Controllers/MpSpecController.cs +++ b/MP.Data/Controllers/MpSpecController.cs @@ -2124,22 +2124,18 @@ namespace MP.Data.Controllers /// /// /// - public List ParametriGetFilt(string IdxMacchina) + public async Task> ParametriGetFiltAsync(string IdxMacchina) { - List dbResult = new List(); - using (var dbCtx = new MoonPro_FluxContext(_configuration)) - { - dbResult = dbCtx - .DbSetFluxLog - .AsNoTracking() - .Where(x => (IdxMacchina == "*" || x.IdxMacchina == IdxMacchina)) - .Take(1000) - .Select(i => i.CodFlux) - .Distinct() - .OrderBy(x => x) - .ToList(); - } - return dbResult; + using var dbCtx = new MoonPro_FluxContext(_configuration); + return await dbCtx + .DbSetFluxLog + .AsNoTracking() + .Where(x => (IdxMacchina == "*" || x.IdxMacchina == IdxMacchina)) + .Take(1000) + .Select(i => i.CodFlux) + .Distinct() + .OrderBy(x => x) + .ToListAsync(); } /// @@ -2205,6 +2201,24 @@ namespace MP.Data.Controllers .FirstOrDefaultAsync() ?? new(); } + /// + /// Dizionario associazione ODL/PODL + /// + /// + /// + public async Task> PODL_getDictOdlPodl(List missingIds) + { + if (missingIds == null || !missingIds.Any()) + return new Dictionary(); + + using var dbCtx = new MoonProContext(options); + return await dbCtx + .DbSetPODL + .AsNoTracking() + .Where(x => missingIds.Contains(x.IdxOdl)) + .ToDictionaryAsync(x => x.IdxOdl, x => x.IdxPromessa); + } + /// /// Avvio setup ODL da PODL /// @@ -2451,18 +2465,14 @@ namespace MP.Data.Controllers /// /// /// - public StatoMacchineModel StatoMacchina(string idxMacchina) + public async Task StatoMacchinaAsync(string idxMacchina) { - StatoMacchineModel dbResult = new StatoMacchineModel(); - using (var dbCtx = new MoonProContext(options)) - { - dbResult = dbCtx - .DbSetStatoMacc - .Where(x => x.IdxMacchina == idxMacchina) - .AsNoTracking() - .FirstOrDefault(); - } - return dbResult; + using var dbCtx = new MoonProContext(options); + return await dbCtx + .DbSetStatoMacc + .Where(x => x.IdxMacchina == idxMacchina) + .AsNoTracking() + .FirstOrDefaultAsync(); } /// diff --git a/MP.Data/Services/TabDataService.cs b/MP.Data/Services/TabDataService.cs index f16614b2..2b6f631d 100644 --- a/MP.Data/Services/TabDataService.cs +++ b/MP.Data/Services/TabDataService.cs @@ -3417,7 +3417,7 @@ namespace MP.Data.Services result = new StatoMacchineModel(); } sw.Stop(); - Log.Debug($"StatoMacchina | {source} | {sw.Elapsed.TotalMilliseconds}ms"); + Log.Debug($"StatoMacchinaAsync | {source} | {sw.Elapsed.TotalMilliseconds}ms"); return result; } diff --git a/MP.SPEC/Components/DossiersFilter.razor b/MP.SPEC/Components/DossiersFilter.razor index 4c5528a4..93ef3275 100644 --- a/MP.SPEC/Components/DossiersFilter.razor +++ b/MP.SPEC/Components/DossiersFilter.razor @@ -5,13 +5,13 @@
@**@ @if (selMacchina != "*") - { - - } - @if (selArticolo != "*") - { - - } + { + + } + @if (selArticolo != "*") + { + + }
}
@@ -34,7 +34,7 @@
- @if (ListArticoli != null) { @@ -50,7 +50,7 @@
- @if (ListMacchine != null) { @@ -67,14 +67,14 @@
- +
- +
@@ -82,7 +82,7 @@
- +
diff --git a/MP.SPEC/Components/DossiersFilter.razor.cs b/MP.SPEC/Components/DossiersFilter.razor.cs index 3f4f0d11..a061c8c7 100644 --- a/MP.SPEC/Components/DossiersFilter.razor.cs +++ b/MP.SPEC/Components/DossiersFilter.razor.cs @@ -30,26 +30,11 @@ namespace MP.SPEC.Components { if (!SelFilterDossier.CodArticolo.Equals(value)) { - SelFilterDossier.CurrPage = 1; SelFilterDossier.CodArticolo = value; - StateHasChanged(); - Task.Delay(1); - reportChange(); } } } - private bool filtActive - { - get => selMacchina != "*" || selArticolo != "*"; - } - protected void resetMacchina() - { - selMacchina = "*"; - } - protected void resetArticolo() - { - selArticolo = "*"; - } + protected DateTime selDtMax { get @@ -62,7 +47,6 @@ namespace MP.SPEC.Components if (!SelFilterDossier.DtEnd.Equals(value)) { SelFilterDossier.DtEnd = value; - reportChange(); } } } @@ -79,7 +63,6 @@ namespace MP.SPEC.Components if (!SelFilterDossier.DtStart.Equals(value)) { SelFilterDossier.DtStart = value; - reportChange(); } } } @@ -94,11 +77,7 @@ namespace MP.SPEC.Components { if (!SelFilterDossier.IdxMacchina.Equals(value)) { - SelFilterDossier.CurrPage = 1; SelFilterDossier.IdxMacchina = value; - StateHasChanged(); - Task.Delay(1); - reportChange(); } } } @@ -115,7 +94,6 @@ namespace MP.SPEC.Components if (!SelFilterDossier.MaxRecord.Equals(value)) { SelFilterDossier.MaxRecord = value; - reportChange(); } } } @@ -128,8 +106,6 @@ namespace MP.SPEC.Components protected override async Task OnInitializedAsync() { - SelFilterDossier = new SelectDossierParams(); - SelFilterDossier.MaxRecord = 1000; DateTime dtEnd = SelFilterDossier.DtEnd; DateTime dtStart = dtEnd.Subtract(SelFilterDossier.DtStart).TotalDays < 15 ? SelFilterDossier.DtStart : dtEnd.AddDays(-14); ListMacchine = await MDService.MacchineWithFluxAsync(dtStart, dtEnd); @@ -137,6 +113,16 @@ namespace MP.SPEC.Components await FilterChanged.InvokeAsync(SelFilterDossier); } + protected void resetArticolo() + { + selArticolo = "*"; + } + + protected void resetMacchina() + { + selMacchina = "*"; + } + protected void toggleParams() { showEditPar = !showEditPar; @@ -147,21 +133,28 @@ namespace MP.SPEC.Components #region Private Fields private List? ListArticoli = null; + private List? ListMacchine = null; #endregion Private Fields #region Private Properties + private bool filtActive + { + get => selMacchina != "*" || selArticolo != "*"; + } + private bool showEditPar { get; set; } = false; #endregion Private Properties #region Private Methods - private void reportChange() + private Task ReportChangeAsync() { - FilterChanged.InvokeAsync(SelFilterDossier); + SelFilterDossier.CurrPage = 1; + return FilterChanged.InvokeAsync(SelFilterDossier); } private void toggleShowParams() diff --git a/MP.SPEC/Components/ListODL.razor.cs b/MP.SPEC/Components/ListODL.razor.cs index dac1a05d..55e93867 100644 --- a/MP.SPEC/Components/ListODL.razor.cs +++ b/MP.SPEC/Components/ListODL.razor.cs @@ -398,6 +398,9 @@ namespace MP.SPEC.Components _podlLocalCache.Clear(); if (SearchRecords != null) { + var listIdx = SearchRecords.Select(x => x.IdxOdl).ToList(); + _podlLocalCache = await MDService.PODL_getDictOdlPodl(listIdx); +#if false // 1. Popolo la cache locale in parallelo sfruttando la velocità di FusionCache var tasks = SearchRecords.Select(async odl => { @@ -413,7 +416,8 @@ namespace MP.SPEC.Components var infoSalvate = await Task.WhenAll(tasks); // 2. Trasformazione dei risultati in un dizionario per l'accesso immediato (O(1)) nell'HTML - _podlLocalCache = infoSalvate.ToDictionary(x => x.IdxOdl, x => x.podl); + _podlLocalCache = infoSalvate.ToDictionary(x => x.IdxOdl, x => x.podl); +#endif } } diff --git a/MP.SPEC/Components/ParamsFilter.razor.cs b/MP.SPEC/Components/ParamsFilter.razor.cs index f2507145..ad7246bb 100644 --- a/MP.SPEC/Components/ParamsFilter.razor.cs +++ b/MP.SPEC/Components/ParamsFilter.razor.cs @@ -109,7 +109,7 @@ namespace MP.SPEC.Components SelFilter.CurrPage = 1; SelFilter.IdxMacchina = value; SelFilter.CodFlux = "*"; - ListFlux = MDService.ParametriGetFilt(selMacchina).Result; + ListFlux = MDService.ParametriGetFiltAsync(selMacchina).Result; StateHasChanged(); Task.Delay(1); reportChange(); @@ -182,7 +182,7 @@ namespace MP.SPEC.Components DateTime dtStart = SelFilter.dtMin != null ? (DateTime)SelFilter.dtMin : DateTime.Now.AddMonths(-1); DateTime dtEnd = SelFilter.dtMax != null ? (DateTime)SelFilter.dtMax : DateTime.Today.AddDays(1); ListMacchine = await MDService.MacchineWithFluxAsync(dtStart, dtEnd); - ListFlux = await MDService.ParametriGetFilt(selMacchina); + ListFlux = await MDService.ParametriGetFiltAsync(selMacchina); var configData = await MDService.ConfigGetAllAsync(); var currRec = configData.FirstOrDefault(x => x.Chiave == "numOreAnticipoSnapshot"); diff --git a/MP.SPEC/Data/MpDataService.cs b/MP.SPEC/Data/MpDataService.cs index 844322fd..01c92078 100644 --- a/MP.SPEC/Data/MpDataService.cs +++ b/MP.SPEC/Data/MpDataService.cs @@ -28,6 +28,7 @@ namespace MP.SPEC.Data _cache = cache; // Verifica conf trace... traceEnabled = _configuration.GetValue("Otel:EnableTracing", false); + slowLogThresh = _configuration.GetValue("ServerConf:slowLogThresh", 1); Log.Info($"MpDataService | INIT | Trace enabled: {traceEnabled}"); // setup compoenti REDIS @@ -389,7 +390,10 @@ namespace MP.SPEC.Data } activity?.SetTag("data.source", source); activity?.Stop(); - LogTrace($"ArticoloDelEnabled | Cod: {codArticolo} | {source} | {activity?.Duration.TotalMilliseconds}ms"); + if (activity?.Duration.TotalMilliseconds > slowLogThresh) + { + LogTrace($"ArticoloDelEnabled | Cod: {codArticolo} | {source} | {activity?.Duration.TotalMilliseconds}ms"); + } return !usato; } @@ -480,8 +484,10 @@ namespace MP.SPEC.Data activity?.SetTag("data.source", source); activity?.Stop(); - - LogTrace($"ConfigTryGet Read from {source}: {activity?.Duration.TotalMilliseconds}ms"); + if (activity?.Duration.TotalMilliseconds > slowLogThresh) + { + LogTrace($"ConfigTryGet | {keyName} | {source} | {activity?.Duration.TotalMilliseconds}ms"); + } return value ?? ""; } @@ -501,8 +507,10 @@ namespace MP.SPEC.Data activity?.SetTag("data.source", source); activity?.Stop(); - - LogTrace($"ConfigTryGetAsync | {keyName} | {source} | {activity?.Duration.TotalMilliseconds}ms"); + if (activity?.Duration.TotalMilliseconds > slowLogThresh) + { + LogTrace($"ConfigTryGetAsync | {keyName} | {source} | {activity?.Duration.TotalMilliseconds}ms"); + } return value ?? ""; } @@ -1754,35 +1762,16 @@ namespace MP.SPEC.Data ///
/// * = tutte, altrimenti solo x una data idxMaccSel /// - public async Task> ParametriGetFilt(string IdxMacchina) + public async Task> ParametriGetFiltAsync(string IdxMacchina) { - using var activity = ActivitySource.StartActivity("ParametriGetFilt"); - List? result = new List(); - string source = "DB"; string currKey = $"{Utils.redisFluxByMac}:{IdxMacchina}"; - // cerco in redis dato valore sel idxMaccSel... - RedisValue rawData = redisDb.StringGet(currKey); - if (rawData.HasValue) - { - result = JsonConvert.DeserializeObject>($"{rawData}"); - source = "REDIS"; - } - else - { - result = await Task.FromResult(dbController.ParametriGetFilt(IdxMacchina)); - // serializzo e salvo... - rawData = JsonConvert.SerializeObject(result); - redisDb.StringSet(currKey, rawData, getRandTOut(redisLongTimeCache)); - } - if (result == null) - { - result = new List(); - } - activity?.SetTag("data.source", source); - activity?.SetTag("result.count", result.Count); - activity?.Stop(); - LogTrace($"ParametriGetFilt | Read from {source}: {activity?.Duration.TotalMilliseconds}ms"); - return result; + return await GetOrFetchAsync( + operationName: "ParametriGetFiltAsync", + cacheKey: currKey, + expiration: getRandTOut(redisShortTimeCache), + fetchFunc: async () => await dbController.ParametriGetFiltAsync(IdxMacchina) ?? new(), + tagList: [Utils.redisFluxByMac] + ); } /// @@ -1885,6 +1874,75 @@ namespace MP.SPEC.Data ); } + /// + /// Restituisce dizionario ODL/PODL data lista IdxOdl + /// + /// + /// + public async Task> PODL_getDictOdlPodl(List idxOdlList) + { + if (idxOdlList == null || !idxOdlList.Any()) + return new Dictionary(); + + var distinctIds = idxOdlList.Distinct().ToList(); + + var resultDictionary = new Dictionary(); + var missingIds = new List(); + + // STEP 1: Controllo rapido in FusionCache (L1/Memory cache) + foreach (var id in distinctIds) + { + var cacheKey = $"val:{id}"; + var cachedValue = await _cache.TryGetAsync(cacheKey); + + if (cachedValue.HasValue) + { + resultDictionary[id] = cachedValue.Value; + } + else + { + // ID non presente in cache, andrà cercato tramite il servizio EF + missingIds.Add(id); + } + } + + // STEP 2: Se ci sono cache miss, interroghiamo il servizio EF Core + if (missingIds.Any()) + { + // Riceviamo direttamente un Dictionary ottimizzato da EF Core + Dictionary dbResults = await dbController.PODL_getDictOdlPodl(missingIds); + + // STEP 3: Scriviamo i risultati in cache e li uniamo al dizionario finale + foreach (var kvp in dbResults) + { + var id = kvp.Key; + var targetValue = kvp.Value; + + resultDictionary[id] = targetValue; + + // Salvataggio atomico e globale su FusionCache + var cacheKey = $"val:{id}"; + await _cache.SetAsync(cacheKey, targetValue, TimeSpan.FromMinutes(30)); + } + + // STEP 4 [Altamente Consigliato]: Cache Penetration Protection + // Se un ID era tra i "missing" ma NON è presente nei risultati del DB, significa che non esiste. + // Salviamo un valore sentinella (es. 0 o -1) per evitare di ricontrollare il DB al prossimo giro. + foreach (var id in missingIds) + { + if (!dbResults.ContainsKey(id)) + { + resultDictionary[id] = 0; // Imposta un default per l'output corrente + + var cacheKey = $"val:{id}"; + await _cache.SetAsync(cacheKey, 0, TimeSpan.FromMinutes(2)); // Scadenza breve per i record inesistenti + } + } + } + + return resultDictionary; + } + /// /// Effettua il task di eliminazione PODL KIT + istanze + riattivazione PODL originali disattivate tramite stored /// @@ -2200,15 +2258,25 @@ namespace MP.SPEC.Data /// /// /// - public StatoMacchineModel StatoMacchina(string idxMacchina) + public async Task StatoMacchinaAsync(string idxMacchina) { - using var activity = ActivitySource.StartActivity("StatoMacchina"); + string currKey = $"{Utils.redisStatoMacch}:{idxMacchina}"; + + return await GetOrFetchAsync( + operationName: "StatoMacchinaAsync", + cacheKey: currKey, + expiration: getRandTOut(redisLongTimeCache), + fetchFunc: async () => await dbController.StatoMacchinaAsync(idxMacchina) ?? new(), + tagList: [Utils.redisStatoMacch] + ); +#if false + using var activity = ActivitySource.StartActivity("StatoMacchinaAsync"); // setup parametri costanti string source = "DB"; StatoMacchineModel? result = new StatoMacchineModel(); // cerco in redisConn... string currKey = $"{Utils.redisStatoMacch}:{idxMacchina}"; - RedisValue rawData = redisDb.StringGet(currKey); + RedisValue rawData = await redisDb.StringGetAsync(currKey); if (rawData.HasValue) { result = JsonConvert.DeserializeObject($"{rawData}"); @@ -2219,7 +2287,7 @@ namespace MP.SPEC.Data result = dbController.StatoMacchina(idxMacchina); // serializzo e salvo... rawData = JsonConvert.SerializeObject(result); - redisDb.StringSet(currKey, rawData, TimeSpan.FromSeconds(1)); + await redisDb.StringSetAsync(currKey, rawData, TimeSpan.FromSeconds(1)); } if (result == null) { @@ -2227,8 +2295,9 @@ namespace MP.SPEC.Data } activity?.SetTag("data.source", source); activity?.Stop(); - LogTrace($"StatoMacchina | {source} | {activity?.Duration.TotalMilliseconds}ms"); - return result; + LogTrace($"StatoMacchinaAsync | {source} | {activity?.Duration.TotalMilliseconds}ms"); + return result; +#endif } /// @@ -2259,23 +2328,15 @@ namespace MP.SPEC.Data /// public async Task> TemplateKitFiltAsync(string codParent, string codChild) { - using var activity = ActivitySource.StartActivity("TemplateKitFiltAsync"); - string source = "DB"; string currKey = $"{Utils.redisKitTempl}:{codParent}:{codChild}"; - var result = await GetOrFetchAsync( + return await GetOrFetchAsync( operationName: "TemplateKitFiltAsync", cacheKey: currKey, expiration: getRandTOut(redisLongTimeCache), fetchFunc: async () => await dbController.TemplateKitFiltAsync(codParent, codChild) ?? new List(), tagList: [Utils.redisKitTempl] ); - - activity?.SetTag("data.source", source); - activity?.SetTag("result.count", result.Count); - activity?.Stop(); - LogTrace($"TemplateKitFiltAsync | {source} | {activity?.Duration.TotalMilliseconds}ms"); - return result; } /// @@ -2649,6 +2710,11 @@ namespace MP.SPEC.Data } } + /// + /// Soglia minima (ms) per log timing in console + /// + private double slowLogThresh = 0; + /// /// Implementa gestione recupero cache da memoria o da obj esterno + cache memoria + tracking attività /// @@ -2669,7 +2735,11 @@ namespace MP.SPEC.Data activity?.SetTag("data.source", source); activity?.Stop(); - LogTrace($"{operationName} | {source} | {activity?.Duration.TotalMilliseconds:F4} ms"); + // se supero la soglia loggo... + if (activity?.Duration.TotalMilliseconds > slowLogThresh) + { + LogTrace($"{operationName} | {source} | {activity?.Duration.TotalMilliseconds:F4} ms"); + } return result; } bool fromDb = false; diff --git a/MP.SPEC/MP.SPEC.csproj b/MP.SPEC/MP.SPEC.csproj index 374536c4..37b640a7 100644 --- a/MP.SPEC/MP.SPEC.csproj +++ b/MP.SPEC/MP.SPEC.csproj @@ -5,7 +5,7 @@ enable enable MP.SPEC - 8.16.2605.2816 + 8.16.2605.2818 1800a78a-6ff1-40f9-b490-87fb8bfc1394 en diff --git a/MP.SPEC/Pages/Articoli.razor b/MP.SPEC/Pages/Articoli.razor index 6d484868..b6acc65c 100644 --- a/MP.SPEC/Pages/Articoli.razor +++ b/MP.SPEC/Pages/Articoli.razor @@ -116,7 +116,14 @@ { foreach (var item in ListTipoArt) { - + if (item.value.Equals("KIT")) + { + + } + else + { + + } } } diff --git a/MP.SPEC/Pages/DOSS.razor b/MP.SPEC/Pages/DOSS.razor index 202c48f5..f6ac1afa 100644 --- a/MP.SPEC/Pages/DOSS.razor +++ b/MP.SPEC/Pages/DOSS.razor @@ -6,16 +6,21 @@

DOSSIERS

-
- @if (isFiltering) - { - - filtro x macchina / periodo - } - else - { - - } +
+
+
max rec: @currFilter.MaxRecord
+
+ @if (isFiltering) + { + + filtro x macchina / periodo + } + else + { + + } +
+
diff --git a/MP.SPEC/Pages/DOSS.razor.cs b/MP.SPEC/Pages/DOSS.razor.cs index 7e7198e4..7b0eaccc 100644 --- a/MP.SPEC/Pages/DOSS.razor.cs +++ b/MP.SPEC/Pages/DOSS.razor.cs @@ -1,9 +1,8 @@ +using EgwCoreLib.Razor; using Microsoft.AspNetCore.Components; using Microsoft.JSInterop; using MP.Data.DbModels; -using MP.SPEC.Components; using MP.SPEC.Data; -using EgwCoreLib.Razor; namespace MP.SPEC.Pages { @@ -43,7 +42,6 @@ namespace MP.SPEC.Pages isLoading = true; isFiltering = true; // fix pagina - await Task.Delay(1); var modFilter = currFilter; modFilter.CurrPage = 1; currFilter = modFilter; @@ -71,7 +69,7 @@ namespace MP.SPEC.Pages #region Private Properties - private SelectDossierParams currFilter { get; set; } = new SelectDossierParams(); + private SelectDossierParams currFilter = new SelectDossierParams() { MaxRecord = 200, CurrPage = 1 }; private int currPage { diff --git a/MP.SPEC/Pages/RepStop.razor.cs b/MP.SPEC/Pages/RepStop.razor.cs index 20317090..846538ff 100644 --- a/MP.SPEC/Pages/RepStop.razor.cs +++ b/MP.SPEC/Pages/RepStop.razor.cs @@ -136,7 +136,7 @@ namespace MP.SPEC.Pages foreach (var idxMacc in CurrMachSel) { DateTime adesso = DateTime.Now.Floor(TimeSpan.FromSeconds(1)); - var rigaStato = MDService.StatoMacchina(idxMacc); + var rigaStato = await MDService.StatoMacchinaAsync(idxMacc); string valData = $"SPEC | FRep.Fine | {MService.DomainName}\\{MService.UserName}"; // chiamo stored @@ -175,7 +175,7 @@ namespace MP.SPEC.Pages // se conferma ciclo x ogni macchina e registro foreach (var idxMacc in CurrMachSel) { - var rigaStato = MDService.StatoMacchina(idxMacc); + var rigaStato = await MDService.StatoMacchinaAsync(idxMacc); // preparo info utente x Value... string valData = $"SPEC | FRep.Inizio | {MService.DomainName}\\{MService.UserName}"; diff --git a/MP.SPEC/Resources/ChangeLog.html b/MP.SPEC/Resources/ChangeLog.html index cd4875b2..83fcea16 100644 --- a/MP.SPEC/Resources/ChangeLog.html +++ b/MP.SPEC/Resources/ChangeLog.html @@ -1,6 +1,6 @@ Modulo MAPOSPEC -

Versione: 8.16.2605.2816

+

Versione: 8.16.2605.2818


Note di rilascio:
  • diff --git a/MP.SPEC/Resources/VersNum.txt b/MP.SPEC/Resources/VersNum.txt index d0d2d8ea..dc9f3309 100644 --- a/MP.SPEC/Resources/VersNum.txt +++ b/MP.SPEC/Resources/VersNum.txt @@ -1 +1 @@ -8.16.2605.2816 +8.16.2605.2818 diff --git a/MP.SPEC/Resources/manifest.xml b/MP.SPEC/Resources/manifest.xml index 964f1191..7314d35a 100644 --- a/MP.SPEC/Resources/manifest.xml +++ b/MP.SPEC/Resources/manifest.xml @@ -1,6 +1,6 @@ - 8.16.2605.2816 + 8.16.2605.2818 https://nexus.steamware.net/repository/SWS/MP-SPEC/stable/LAST/MP.SPEC.zip https://nexus.steamware.net/repository/SWS/MP-SPEC/stable/LAST/ChangeLog.html false diff --git a/MP.SPEC/appsettings.Production.json b/MP.SPEC/appsettings.Production.json index 1424dd3f..f4ebc6a0 100644 --- a/MP.SPEC/appsettings.Production.json +++ b/MP.SPEC/appsettings.Production.json @@ -29,6 +29,7 @@ "cacheCheckArtUsato": 2, "redisShortTimeCache": 10, "redisLongTimeCache": 600, + "slowLogThresh": 200, "MpIoBaseUrl": "http://localhost/MP/IO/", "MpIoNS": "MoonPro:SQL2016DEV:MoonPro", "BasePathOdlReturn": "\\\\iis01\\W$\\Files\\ODL", diff --git a/MP.SPEC/appsettings.json b/MP.SPEC/appsettings.json index ff3e5c10..683abe14 100644 --- a/MP.SPEC/appsettings.json +++ b/MP.SPEC/appsettings.json @@ -70,6 +70,7 @@ "cacheCheckArtUsato": "2", "redisShortTimeCache": 5, "redisLongTimeCache": 120, + "slowLogThresh": 1, "MpIoBaseUrl": "http://localhost:20967/", "MpIoNS": "MoonPro:SQL2016DEV:MoonPro", "BasePathOdlReturn": "\\\\iis01\\ODL\\ftpdata\\syncfolder", diff --git a/Refactor_Plan.md b/Refactor_Plan.md index 59363611..9bf60fed 100644 --- a/Refactor_Plan.md +++ b/Refactor_Plan.md @@ -3,143 +3,67 @@ ## Obiettivo Migrare la logica di caching manuale (Redis + DB) verso l'utilizzo di `IFusionCache` per implementare un approccio multi-layer (Memory + Redis + DB), standardizzando l'accesso ai dati. -## Analisi dello stato attuale -- **Classe target**: `MP.SPEC\Data\MpDataService.cs` -- **Pattern attuale**: Molti metodi utilizzano manualmente `redisDb.StringGetAsync` e `redisDb.StringSetAsync` con serializzazione JSON manuale. -- **Metodo Standard**: `GetOrFetchAsync(string operationName, string cacheKey, Func> fetchFunc, TimeSpan expiration, params string[] tags)`. - ## Strategia di Migrazione +- **Metodo Standard**: `GetOrFetchAsync(string operationName, string cacheKey, Func> fetchFunc, TimeSpan expiration, params string[] tagList)`. +- **Invalidazione**: Utilizzare i tag tramite `FlushCacheByTagsAsync`. -### 1. Identificazione Metodi Target -Andrò a mappare tutti i metodi in `MpDataService.cs` che: -- Utilizzano `redisDb` direttamente per la lettura/scrittura. -- Gestiscono manualmente la serializzazione/deserializzazione con `JsonConvert`. -- Gestiscono manualmente il fallback dal Redis al DB. +## Stato Avanzamento -### 2. Classificazione Metodi -I metodi verranno suddivisi in: -- **Lettura (Cache-aside)**: Metodi che recuperano dati. Questi saranno i candidati principali per `GetOrFetchAsync`. -- **Scrittura/Invalidazione**: Metodi che aggiornano il DB e devono invalidare la cache (es. `AnagGruppiUpsert`, `ArticoliUpdateRecord`). Questi dovranno utilizzare `_cache.RemoveByTagAsync` o `_cache.RemoveAsync`. +### Fase 1: Analisi e Mapping (Completata) -### 3. Piano di Implementazione (Step-by-Step) +### Fase 2: Refactoring Metodi di Lettura (Cache-aside) -#### Fase 1: Analisi e Mapping -- [ ] Identificare ogni occorrenza di `redisDb.StringGet` / `StringGetAsync` in `MpDataService.cs`. -- [ ] Verificare se la chiave di cache utilizzata è gestita tramite `Utils.redis...`. +#### ✅ Completati (Migrati con `GetOrFetchAsync`) +- `ActionGetReq` +- `AnagEventiGeneralAsync` +- `AnagStatiCommAsync` +- `AnagTipoArtLvAsync` +- `ArticleWithDossierAsync` +- `ArticoliGetByTipoAsync` +- `ArticoliGetSearchAsync` +- `ConfigGetAllAsync` +- `DossiersGetLastFiltAsync` +- `ElencoAziendeAsync` +- `ElencoGruppiFaseAsync` +- `ElencoLinkAsync` +- `FluxLogGetLastFiltAsync` +- `FluxLogParetoAsync` +- `OperatoriGetFiltAsync` +- `POdlGetByOdlAsync` +- `POdlListGetFiltAsync` +- `TksScoreAsync` +- `WipKitFiltAsync` +- `MacchineRecipeArchiveAsync` +- `MacchineRecipeConfAsync` -#### Fase 2: Refactoring Metodi di Lettura -- [x] `ActionGetReq` (Completato) -- [x] `TemplateKitFiltAsync` -- [x] `AnagTipoArtLvAsync` -- [x] `ElencoLinkAsync` -- [x] `ConfigGetAllAsync` -- [x] `DossiersGetLastFiltAsync` -- [x] `ElencoGruppiFaseAsync` -- [x] `IstKitFiltAsync` -- [x] `ListGiacenzeAsync` -- [x] `MacchineWithFluxAsync` -- [x] `POdlListGetFiltAsync` -- [x] `TksScoreAsync` -- [x] `WipKitFiltAsync` -- [x] `POdlGetByOdlAsync` -- [x] `FluxLogGetLastFiltAsync` -- [x] `FluxLogParetoAsync` -- [x] `OperatoriGetFiltAsync` -- [x] `MacchineRecipeArchiveAsync` -- [x] `MacchineRecipeConfAsync` -- [ ] `AnagEventiGeneral` -- [ ] `AnagEventiGetByMacch` -- [ ] `AnagKeyValGetAll` -- [ ] `AnagStatiComm` -- [ ] `AnagTipoArtLvAsync` -- [ ] `ArticleWithDossier` -- [ ] `ConfigGetAll` -- [ ] `DbDedupStats` -- [ ] `ElencoRepartiDTO` -- [ ] `ExpiryReloadParamGet` -- [ ] `IobInfo` -- [ ] `ListPODL_ByCodArt` -- [ ] `MacchineGetFilt` -- [ ] `MacchineRecipeArchive` -- [ ] `MacchineRecipeConf` -- [ ] `MachIobConf` -- [ ] `MseGetAll` -- [ ] `OdlByBatch` -- [ ] `OdlGetCurrentAsync` -- [ ] `OdlListGetFilt` -- [ ] `OperatoriGetFilt` -- [ ] `ParametriGetFilt` -- [ ] `POdlGetByKey` -- [ ] `POdlListByKitParent` -- [ ] `ProcFLStats` -- [ ] `StatoMacchina` -- [ ] `TagConfGetKey` -- [ ] `VocabolarioGetAll` +#### ⏳ In corso / Da Migrare +- `AnagEventiGetByMacch` +- `AnagKeyValGetAll` +- `ConfigGetAll` (Sincrono) +- `ConfigTryGet` (Sincrono) +- `ConfigTryGetAsync` +- `DbDedupStats` +- `ElencoRepartiDTO` +- `ExpiryReloadParamGet` +- `IobInfo` +- `ListPODL_ByCodArt` +- `MacchineGetFilt` +- `MachIobConf` +- `MachIobConfVal` +- `MseGetAll` +- `OdlByBatch` +- `OdlGetCurrentAsync` +- `OdlListGetFilt` +- `OperatoriGetFilt` (Sincrono) +- `ParametriGetFilt` +- `POdlGetByKey` +- `POdlListByKitParent` +- `ProcFLStats` +- `StatoMacchina` +- `TagConfGetKey` +- `VocabolarioGetAll` -#### Fase 3: Refactoring Metodi di Scrittura e Invalidazione -- [ ] `AnagGruppiDelete` -- [ ] `AnagGruppiUpsert` -- [ ] `ArticoliDeleteRecord` -- [ ] `ArticoliUpdateRecord` -- [ ] `ConfigResetCache` -- [ ] `DossiersDeleteRecord` -- [ ] `DossiersTakeParamsSnapshotLast` -- [ ] `IstKitDelete` -- [ ] `IstKitInsertByWKS` -- [ ] `IstKitUpsert` -- [ ] `PodlIstKitDelete` -- [ ] `POdlDoSetup` -- [ ] `POdlUpdateRecipe` -- [ ] `POdlUpdateRecord` -- [ ] `RecipeSetByPODL` -- [ ] `TemplateKitDelete` -- [ ] `TemplateKitUpsert` Fase 2: Refactoring Metodi di Lettura -- [x] `ActionGetReq` (Completato) -- [x] `TemplateKitFiltAsync` -- [x] `AnagTipoArtLvAsync` -- [x] `ElencoLinkAsync` -- [x] `ConfigGetAllAsync` -- [x] `DossiersGetLastFiltAsync` -- [x] `ElencoGruppiFaseAsync` -- [x] `IstKitFiltAsync` -- [x] `ListGiacenzeAsync` -- [x] `MacchineWithFluxAsync` -- [x] `POdlListGetFiltAsync` -- [x] `TksScoreAsync` -- [x] `WipKitFiltAsync` -- [x] `POdlGetByOdlAsync` -- [x] `FluxLogGetLastFiltAsync` -- [x] `FluxLogParetoAsync` -- [ ] `AnagEventiGeneral` -- [ ] `AnagEventiGetByMacch` -- [ ] `AnagKeyValGetAll` -- [ ] `AnagStatiComm` -- [ ] `AnagTipoArtLvAsync` -- [ ] `ArticleWithDossier` -- [ ] `ConfigGetAll` -- [ ] `DbDedupStats` -- [ ] `ElencoRepartiDTO` -- [ ] `ExpiryReloadParamGet` -- [ ] `IobInfo` -- [ ] `ListPODL_ByCodArt` -- [ ] `MacchineGetFilt` -- [ ] `MacchineRecipeArchive` -- [ ] `MacchineRecipeConf` -- [ ] `MachIobConf` -- [ ] `MseGetAll` -- [ ] `OdlByBatch` -- [ ] `OdlGetCurrentAsync` -- [ ] `OdlListGetFilt` -- [ ] `OperatoriGetFilt` -- [ ] `ParametriGetFilt` -- [ ] `POdlGetByKey` -- [ ] `POdlListByKitParent` -- [ ] `ProcFLStats` -- [ ] `StatoMacchina` -- [ ] `TagConfGetKey` -- [ ] `VocabolarioGetAll` - -#### Fase 3: Refactoring Metodi di Scrittura e Invalidazione +### Fase 3: Refactoring Metodi di Scrittura e Invalidazione - [ ] `AnagGruppiDelete` - [ ] `AnagGruppiUpsert` - [ ] `ArticoliDeleteRecord`