diff --git a/MP.Data/Controllers/MpSpecController.cs b/MP.Data/Controllers/MpSpecController.cs
index cb8d41ef..5c39a619 100644
--- a/MP.Data/Controllers/MpSpecController.cs
+++ b/MP.Data/Controllers/MpSpecController.cs
@@ -164,9 +164,9 @@ namespace MP.Data.Controllers
/// Elenco Gruppi tipo Azienda
///
///
- public List AnagGruppiAziende()
+ public Task> AnagGruppiAziendeAsync()
{
- return AnagGruppiGetTipo("AZIENDA");
+ return AnagGruppiGetTipoAsync("AZIENDA");
}
///
@@ -241,6 +241,26 @@ namespace MP.Data.Controllers
return dbResult;
}
+ ///
+ /// Gruppi x tipo modalità Async
+ ///
+ ///
+ ///
+ public async Task> AnagGruppiGetTipoAsync(string tipoGruppo)
+ {
+ List dbResult = new List();
+ using (var dbCtx = new MoonProContext(options))
+ {
+ dbResult = await dbCtx
+ .DbSetAnagGruppi
+ .Where(x => x.TipoGruppo == tipoGruppo)
+ .AsNoTracking()
+ .OrderBy(x => x.CodGruppo)
+ .ToListAsync();
+ }
+ return dbResult;
+ }
+
///
/// Elenco Gruppi tipo REPARTO (x associazione Macchine-Operatori)
///
diff --git a/MP.SPEC/Components/CmpTop.razor.cs b/MP.SPEC/Components/CmpTop.razor.cs
index c7d26602..593b6a6a 100644
--- a/MP.SPEC/Components/CmpTop.razor.cs
+++ b/MP.SPEC/Components/CmpTop.razor.cs
@@ -1,12 +1,9 @@
-using Amazon.Runtime.Internal.Endpoints.StandardLibrary;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Authorization;
-using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.JSInterop;
using MP.AppAuth.Services;
using MP.SPEC.Data;
using MP.SPEC.Extensions;
-using System;
namespace MP.SPEC.Components
{
@@ -56,6 +53,7 @@ namespace MP.SPEC.Components
protected async Task FlushCache()
{
await MDService.FlushRedisCache();
+ await MDService.FlushCacheAsync();
await ForceReload();
// rimando a pagina corrente
NavManager.NavigateTo(NavManager.Uri, true);
diff --git a/MP.SPEC/Data/MpDataService.cs b/MP.SPEC/Data/MpDataService.cs
index 8370b7cf..6cc2b305 100644
--- a/MP.SPEC/Data/MpDataService.cs
+++ b/MP.SPEC/Data/MpDataService.cs
@@ -306,7 +306,7 @@ namespace MP.SPEC.Data
return await GetOrFetchAsync(
operationName: "AnagStatiCommAsync",
cacheKey: Utils.redisStatoCom,
- expiration: TimeSpan.FromMinutes(5),
+ expiration: TimeSpan.FromMinutes(redisLongTimeCache),
fetchFunc: async () =>
await dbController.AnagStatiCommAsync() ?? new List()
);
@@ -633,6 +633,7 @@ namespace MP.SPEC.Data
{
bool fatto = false;
await _cache.ClearAsync();
+ _configData.Clear();
fatto = true;
return fatto;
}
@@ -648,6 +649,7 @@ namespace MP.SPEC.Data
{
await _cache.RemoveByTagAsync(item);
}
+ _configData.Clear();
fatto = true;
return fatto;
}
@@ -659,6 +661,7 @@ namespace MP.SPEC.Data
{
bool fatto = false;
await _cache.RemoveByTagAsync(tag);
+ _configData.Clear();
fatto = true;
return fatto;
}
@@ -1198,14 +1201,14 @@ namespace MP.SPEC.Data
/// Restitusice elenco aziende
///
///
- public List ElencoAziende()
+ public async Task> ElencoAziendeAsync()
{
- using var activity = ActivitySource.StartActivity("ElencoAziende");
+ using var activity = ActivitySource.StartActivity("ElencoAziendeAsync");
string source = "DB";
- var listAz = dbController.AnagGruppiAziende();
+ var listAz = await dbController.AnagGruppiAziendeAsync();
activity?.SetTag("data.source", source);
activity?.Stop();
- LogTrace($"ElencoAziende | Read from {source}: {activity?.Duration.TotalMilliseconds}ms");
+ LogTrace($"ElencoAziendeAsync | Read from {source}: {activity?.Duration.TotalMilliseconds}ms");
return listAz;
}
diff --git a/MP.SPEC/MP.SPEC.csproj b/MP.SPEC/MP.SPEC.csproj
index 66b09440..26cb8e72 100644
--- a/MP.SPEC/MP.SPEC.csproj
+++ b/MP.SPEC/MP.SPEC.csproj
@@ -5,7 +5,7 @@
enable
enable
MP.SPEC
- 8.16.2605.2708
+ 8.16.2605.2709
1800a78a-6ff1-40f9-b490-87fb8bfc1394
en
diff --git a/MP.SPEC/Pages/Articoli.razor.cs b/MP.SPEC/Pages/Articoli.razor.cs
index 008bbc19..accea5f3 100644
--- a/MP.SPEC/Pages/Articoli.razor.cs
+++ b/MP.SPEC/Pages/Articoli.razor.cs
@@ -176,7 +176,7 @@ namespace MP.SPEC.Pages
{
selAzienda = "*";
}
- ListAziende = MDService.ElencoAziende();
+ ListAziende = await MDService.ElencoAziendeAsync();
ListTipoArt = await MDService.AnagTipoArtLV();
}
diff --git a/MP.SPEC/Pages/PODL.razor.cs b/MP.SPEC/Pages/PODL.razor.cs
index 23054a1a..aaf0d96c 100644
--- a/MP.SPEC/Pages/PODL.razor.cs
+++ b/MP.SPEC/Pages/PODL.razor.cs
@@ -129,7 +129,7 @@ namespace MP.SPEC.Pages
protected override async Task OnInitializedAsync()
{
await getReparto();
- ListAziende = MDService.ElencoAziende();
+ ListAziende = await MDService.ElencoAziendeAsync();
var allGruppiData = MDService.ElencoGruppiFase();
if (allGruppiData != null)
{
diff --git a/MP.SPEC/Resources/ChangeLog.html b/MP.SPEC/Resources/ChangeLog.html
index 59e7e6d9..ff33fc09 100644
--- a/MP.SPEC/Resources/ChangeLog.html
+++ b/MP.SPEC/Resources/ChangeLog.html
@@ -1,6 +1,6 @@
Modulo MAPOSPEC
- Versione: 8.16.2605.2708
+ Versione: 8.16.2605.2709
Note di rilascio:
-
diff --git a/MP.SPEC/Resources/VersNum.txt b/MP.SPEC/Resources/VersNum.txt
index 933735f6..0dfa7efa 100644
--- a/MP.SPEC/Resources/VersNum.txt
+++ b/MP.SPEC/Resources/VersNum.txt
@@ -1 +1 @@
-8.16.2605.2708
+8.16.2605.2709
diff --git a/MP.SPEC/Resources/manifest.xml b/MP.SPEC/Resources/manifest.xml
index 02e7a70d..dcbc0eb7 100644
--- a/MP.SPEC/Resources/manifest.xml
+++ b/MP.SPEC/Resources/manifest.xml
@@ -1,6 +1,6 @@
-
- 8.16.2605.2708
+ 8.16.2605.2709
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/refactor_spec.md b/refactor_spec.md
new file mode 100644
index 00000000..2b8a587c
--- /dev/null
+++ b/refactor_spec.md
@@ -0,0 +1,63 @@
+# Refactoring Plan: MpDataService Cache Layer Upgrade
+
+## Objective
+Migrate all data access methods in `MpDataService.cs` to use the unified multi-level cache stack (IMemoryCache via `IFusionCache` + Redis + DB) using the `GetOrFetchAsync` pattern.
+
+## Current State
+- Some methods use a manual "Redis + DB" approach (checking `redisDb.StringGet`, deserializing, and then `StringSet` on miss).
+- Some methods use the new `GetOrFetchAsync` pattern (Memory + Redis + DB).
+- `GetOrFetchAsync` leverages `IFusionCache`, which handles the multi-level complexity and provides better resiliency (fail-safe).
+
+## Target Pattern: `GetOrFetchAsync`
+All read methods should be refactored to:
+1. Use `GetOrFetchAsync` to abstract cache management.
+2. Define a `cacheKey` (typically matching the existing Redis key).
+3. Provide an `expiration` (TimeSpan).
+4. Provide a `fetchFunc` that calls the `dbController` method.
+
+## Proposed Work Items
+
+### 1. Analysis & Categorization
+Identify all methods in `MpDataService.cs` that currently implement manual Redis caching.
+
+**Candidates for Refactoring (Redis + DB -> Multi-level):**
+- `AnagEventiGeneral` (Lines 166-195)
+- `AnagEventiGetByMacch` (Lines 201-230)
+- `AnagKeyValGetAll` (Lines 273-302)
+- `AnagTipoArtLV` (Lines 347-375)
+- `ArticleWithDossier` (Lines 381-410)
+- `ConfigGetAll` (Lines 907-936)
+- `ConfigGetAllAsync` (Lines 943-970)
+- `DbDedupStats` (Lines 1046-1067)
+- `ElencoGruppiFase` (Lines 1216-1249)
+- `ElencoRepartiDTO` (Lines 1267-1303)
+- `FluxLogGetLastFilt` (Lines 1569-1605)
+- `FluxLogPareto` (Lines 1609-1640)
+- `MacchineRecipeArchive` (Lines 2100-2128)
+- `MacchineRecipeConf` (Lines 2131-2163)
+- `MacchineWithFlux` (Lines 2171-2200)
+- `OdlByBatch` (Lines 2308-2336)
+- `OdlListAll` (Lines 2490-2499) - *Currently no cache, needs addition?*
+- `OdlListGetFilt` (Lines 2513-2542)
+- `OperatoriGetFilt` (Lines 2549-2577)
+- `ParametriGetFilt` (Lines 2585-2614)
+- `POdlGetByKey` (Lines 2658-2697)
+- `POdlGetByOdl` (Lines 2705-2744)
+- `POdlListByKitParent` (Lines 2770-2800)
+- `POdlListGetFilt` (Lines 2812-2841)
+- `TksScore` (Lines 3343-3372)
+- `VocabolarioGetAll` (Lines 3445-3477)
+- `WipKitFilt` (Lines 3543-3570)
+
+### 2. Implementation Steps
+For each candidate method:
+1. **Convert to Async**: If the method is synchronous (e.g., `AnagEventiGeneral`), convert it to `Task` to match the `GetOrFetchAsync` signature.
+2. **Map Keys**: Ensure the `cacheKey` passed to `GetOrFetchAsync` is identical to the old Redis key to prevent cache fragmentation.
+3. **Set Expiration**: Use appropriate `TimeSpan` (e.g., `redisLongTimeCache` or `redisShortTimeCache` converted to `TimeSpan`).
+4. **Cleanup**: Remove manual `JsonConvert` logic and `redisDb.StringGet/Set` calls.
+5. **Verify Tracing**: Ensure `ActivitySource` and `LogTrace` are preserved or integrated within the `GetOrFetchAsync` wrapper.
+
+### 3. Validation
+- Ensure all refactored methods are still called correctly by consumers.
+- Verify that `GetOrFetchAsync` correctly hits Memory first, then Redis, then DB.
+- Confirm that `LogTrace` still reports the correct source (MEMORY, REDIS, or DB).