diff --git a/Directory.Packages.props b/Directory.Packages.props index f5b8b499..71c44dc1 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -24,10 +24,11 @@ + - + @@ -41,7 +42,7 @@ - + @@ -49,5 +50,8 @@ + + + \ No newline at end of file diff --git a/MP.Data/MP.Data.csproj b/MP.Data/MP.Data.csproj index c1717ce8..1a30d9e0 100644 --- a/MP.Data/MP.Data.csproj +++ b/MP.Data/MP.Data.csproj @@ -48,6 +48,9 @@ + + + diff --git a/MP.Data/Services/IOC/IIocService.cs b/MP.Data/Services/IOC/IIocService.cs index 8e7f6a76..1eedf50d 100644 --- a/MP.Data/Services/IOC/IIocService.cs +++ b/MP.Data/Services/IOC/IIocService.cs @@ -24,6 +24,12 @@ namespace MP.Data.Services.IOC /// Task CheckCambiaStatoBatchAsync(tipoInputEvento tipoInput, string IdxMacchina, DateTime InizioStato, int IdxTipo, string CodArt, string Value, int MatrOpr, string pallet); + /// + /// Esegue clear dell'intera cache fusion in blocco + /// + /// + Task ClearFusionCache(); + /// /// Aggiunta record MicroStato + EventList /// diff --git a/MP.Data/Services/IOC/IocService.cs b/MP.Data/Services/IOC/IocService.cs index 93856041..c3a8369e 100644 --- a/MP.Data/Services/IOC/IocService.cs +++ b/MP.Data/Services/IOC/IocService.cs @@ -1,5 +1,4 @@ -using Microsoft.Extensions.Caching.Memory; -using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using MP.Core.Objects; using MP.Data.DbModels; @@ -12,6 +11,7 @@ using System.Collections.Generic; using System.Globalization; using System.Linq; using System.Threading.Tasks; +using ZiggyCreatures.Caching.Fusion; using static MP.Core.Objects.Enums; namespace MP.Data.Services.IOC @@ -25,7 +25,8 @@ namespace MP.Data.Services.IOC IConnectionMultiplexer redis, IIocRepository repo, IServiceScopeFactory scopeFactory, - Microsoft.Extensions.Caching.Memory.IMemoryCache cache) : base(config, redis) + //Microsoft.Extensions.Caching.Memory.IMemoryCache cache + IFusionCache cache) : base(config, redis) { _className = "IocServ"; int.TryParse(config.GetValue("ServerConf:redisLongTimeCache"), out redisLongTimeCache); @@ -46,6 +47,15 @@ namespace MP.Data.Services.IOC return success; } + /// + public async Task ClearFusionCache() + { + bool fatto = false; + await _cache.ClearAsync(); + fatto = true; + return fatto; + } + /// public async Task EvListMicroStatoInsertAsync(MicroStatoMacchinaModel newRecMsm, EventListModel newRecEv) { @@ -268,12 +278,12 @@ namespace MP.Data.Services.IOC private static Logger Log = LogManager.GetCurrentClassLogger(); - private readonly Microsoft.Extensions.Caching.Memory.IMemoryCache _cache; + private readonly IFusionCache _cache; + private readonly string _className; private readonly IIocRepository _repo; private readonly IServiceScopeFactory _scopeFactory; - private readonly System.Threading.SemaphoreSlim _semaphore = new System.Threading.SemaphoreSlim(1, 1); /// /// Provider CultureInfo x parse valori(es dataora) @@ -406,8 +416,6 @@ namespace MP.Data.Services.IOC else { result = await _repo.ConfigGetAllAsync(); - //result = await Task.FromResult(SpecDbController.ConfigGetAllAsync()); - // serializzo e salvo... rawData = JsonConvert.SerializeObject(result); await _redisDb.StringSetAsync(MP.Data.Utils.redisConfKey, rawData, getRandTOut(redisLongTimeCache)); } @@ -417,7 +425,7 @@ namespace MP.Data.Services.IOC result = new List(); } return result; - }, TimeSpan.FromMinutes(10)); + }, TimeSpan.FromMinutes(1)); } /// @@ -460,15 +468,15 @@ namespace MP.Data.Services.IOC /// private async Task GetOrFetchAsync(string cacheKey, Func> fetchFunc, TimeSpan expiration) { - if (_cache.TryGetValue(cacheKey, out T? cachedValue)) - { - return cachedValue!; - } - - // se non trovato procedo as usual... - T newValue = await fetchFunc(); - _cache.Set(cacheKey, newValue, expiration); - return newValue; + // GetOrSetAsync di Fusion cache: + // - TryGetValue, se mancasse crea un lock solo per QUELLA key + // - Esegue fetchFunc (la logica Redis + DB) + // - Salva in memoria e rilascia il lock + return await _cache.GetOrSetAsync( + cacheKey, + async ct => await fetchFunc(), + options => options.SetDuration(expiration) + ); } /// @@ -543,7 +551,7 @@ namespace MP.Data.Services.IOC await _redisDb.StringSetAsync(currKey, rawData, getRandTOut(redisLongTimeCache * 10)); } return result; - }, TimeSpan.FromMinutes(5)); + }, TimeSpan.FromMinutes(15)); } private async Task> ListSlaveAsync() @@ -565,7 +573,7 @@ namespace MP.Data.Services.IOC await _redisDb.StringSetAsync(currKey, rawData, getRandTOut(redisLongTimeCache * 10)); } return result; - }, TimeSpan.FromMinutes(5)); + }, TimeSpan.FromMinutes(15)); } /// @@ -596,7 +604,7 @@ namespace MP.Data.Services.IOC result = new List(); } return result; - }, TimeSpan.FromMinutes(15)); + }, TimeSpan.FromMinutes(30)); } /// @@ -1022,7 +1030,7 @@ namespace MP.Data.Services.IOC result = new StatoProdModel(); } return result; - }, TimeSpan.FromSeconds(10)); + }, TimeSpan.FromSeconds(3)); } /// diff --git a/MP.Data/Services/Utils/IStatsDetailService.cs b/MP.Data/Services/Utils/IStatsDetailService.cs index 364a44a4..751f003b 100644 --- a/MP.Data/Services/Utils/IStatsDetailService.cs +++ b/MP.Data/Services/Utils/IStatsDetailService.cs @@ -41,7 +41,6 @@ namespace MP.Data.Services.Utils //Task>> GetParetoStatsDayAsync(); Task> GetParetoStatsDayAsync(); - /// /// Recupera il range di periodi valido per le chiamate di dettaglio. /// Utilizza la cache automaticamente. @@ -58,6 +57,12 @@ namespace MP.Data.Services.Utils /// List GetTimeSeriesData(List rawData, bool showCount); + /// + /// Forza il reset della cache REDIS x i dati + /// + /// + Task ResetCache(); + /// /// Inserisce o aggiorna in batch le statistiche di dettaglio nel database. /// Opzionalmente elimina i record precedenti nel periodo specificato. diff --git a/MP.Data/Services/Utils/StatsDetailService.cs b/MP.Data/Services/Utils/StatsDetailService.cs index 1c3088e4..75738f4d 100644 --- a/MP.Data/Services/Utils/StatsDetailService.cs +++ b/MP.Data/Services/Utils/StatsDetailService.cs @@ -125,6 +125,12 @@ namespace MP.Data.Services.Utils return series; } + /// + public async Task ResetCache() + { + await ClearCacheAsync($"{_redisBaseKey}:*"); + } + /// public async Task UpsertManyAsync(List listRecords, bool removeOld) { @@ -227,7 +233,6 @@ namespace MP.Data.Services.Utils return result; } - #endregion Protected Methods #region Private Fields diff --git a/MP.IOC/Components/Pages/CallStats.razor b/MP.IOC/Components/Pages/CallStats.razor index 65d92366..58742912 100644 --- a/MP.IOC/Components/Pages/CallStats.razor +++ b/MP.IOC/Components/Pages/CallStats.razor @@ -2,7 +2,14 @@
-

Current Stats

+
+
+

Current Stats

+
+
+ +
+
@@ -85,17 +92,17 @@
# giorni -
-
- -
- } +
+ +
+ } - + } - } - + + } + diff --git a/MP.IOC/Components/Pages/CallStats.razor.cs b/MP.IOC/Components/Pages/CallStats.razor.cs index 97225431..427f7037 100644 --- a/MP.IOC/Components/Pages/CallStats.razor.cs +++ b/MP.IOC/Components/Pages/CallStats.razor.cs @@ -3,6 +3,7 @@ using MP.Core.DTO; using MP.Data; using MP.Data.DbModels.Utils; using MP.Data.DTO; +using MP.Data.Services.IOC; using MP.Data.Services.Utils; namespace MP.IOC.Components.Pages @@ -101,6 +102,9 @@ namespace MP.IOC.Components.Pages [Inject] private IStatsDetailService SDetService { get; set; } = null!; + [Inject] + private IIocService IocService { get; set; } = null!; + #endregion Private Properties #region Private Methods @@ -110,6 +114,13 @@ namespace MP.IOC.Components.Pages return currStatSel != null && currStatSel.Title == curKey ? "active" : ""; } + private async Task DoForceReload() + { + await SDetService.ResetCache(); + await IocService.ClearFusionCache(); + DoReset(); + } + private void DoReset() { currStatSel = null; diff --git a/MP.IOC/MP.IOC.csproj b/MP.IOC/MP.IOC.csproj index 69a7a795..ec21f95d 100644 --- a/MP.IOC/MP.IOC.csproj +++ b/MP.IOC/MP.IOC.csproj @@ -4,7 +4,7 @@ net8.0 enable enable - 8.16.2605.1112 + 8.16.2605.1119 diff --git a/MP.IOC/Program.cs b/MP.IOC/Program.cs index e77a427d..8a3df56f 100644 --- a/MP.IOC/Program.cs +++ b/MP.IOC/Program.cs @@ -10,6 +10,9 @@ using NLog; using NLog.Web; using StackExchange.Redis; using System.Reflection; +using ZiggyCreatures.Caching.Fusion; +using ZiggyCreatures.Caching.Fusion.Serialization; +using ZiggyCreatures.Caching.Fusion.Serialization.NewtonsoftJson; var builder = WebApplication.CreateBuilder(args); @@ -85,6 +88,20 @@ builder.Services.AddSingleton(redisMux); //builder.Services.AddScoped(); builder.Services.AddSingleton(); +// 1. Registra il serializzatore NewtonsoftJson per FusionCache +builder.Services.AddSingleton(new FusionCacheNewtonsoftJsonSerializer()); + +// 2. Configura FusionCache solo per la memoria (L1) +builder.Services.AddFusionCache() + .WithDefaultEntryOptions(options => + { + // Durata di default dei dati in memoria + options.Duration = TimeSpan.FromMinutes(1); + + // Jitter: variazione casuale alla scadenza per evitare scadenze in blocco + options.JitterMaxDuration = TimeSpan.FromSeconds(5); + }); + logger.Info("Standard service configured"); // WeightProvider: Redis/Memory da config diff --git a/MP.IOC/Resources/ChangeLog.html b/MP.IOC/Resources/ChangeLog.html index ae820af1..480c59fb 100644 --- a/MP.IOC/Resources/ChangeLog.html +++ b/MP.IOC/Resources/ChangeLog.html @@ -1,6 +1,6 @@ Modulo MP-IOC -

Versione: 8.16.2605.1112

+

Versione: 8.16.2605.1119


Note di rilascio:
  • diff --git a/MP.IOC/Resources/VersNum.txt b/MP.IOC/Resources/VersNum.txt index 482cea3b..282e9dc7 100644 --- a/MP.IOC/Resources/VersNum.txt +++ b/MP.IOC/Resources/VersNum.txt @@ -1 +1 @@ -8.16.2605.1112 +8.16.2605.1119 diff --git a/MP.IOC/Resources/manifest.xml b/MP.IOC/Resources/manifest.xml index 914fdc0f..0bbcd7eb 100644 --- a/MP.IOC/Resources/manifest.xml +++ b/MP.IOC/Resources/manifest.xml @@ -1,6 +1,6 @@ - 8.16.2605.1112 + 8.16.2605.1119 https://nexus.steamware.net/repository/SWS/MP-IOC/stable/LAST/MP.IOC.zip https://nexus.steamware.net/repository/SWS/MP-IOC/stable/LAST/ChangeLog.html false diff --git a/MP.RIOC/MP.RIOC.csproj b/MP.RIOC/MP.RIOC.csproj index 5b179860..4b9d8648 100644 --- a/MP.RIOC/MP.RIOC.csproj +++ b/MP.RIOC/MP.RIOC.csproj @@ -5,7 +5,7 @@ enable enable MP.RIOC - 8.16.2605.1111 + 8.16.2605.1207 diff --git a/MP.RIOC/Program.cs b/MP.RIOC/Program.cs index 31e3342f..a507237f 100644 --- a/MP.RIOC/Program.cs +++ b/MP.RIOC/Program.cs @@ -62,7 +62,7 @@ var httpClientInvoker = new HttpMessageInvoker(new SocketsHttpHandler UseCookies = false, // Correzione per il tracing: usa il propagatore corrente di sistema ActivityHeadersPropagator = DistributedContextPropagator.Current, - ConnectTimeout = TimeSpan.FromSeconds(30), + ConnectTimeout = TimeSpan.FromSeconds(60), // Gestione certificato (ignora errori per localhost/test) SslOptions = new System.Net.Security.SslClientAuthenticationOptions diff --git a/MP.RIOC/Resources/ChangeLog.html b/MP.RIOC/Resources/ChangeLog.html index e2824b7f..ce196314 100644 --- a/MP.RIOC/Resources/ChangeLog.html +++ b/MP.RIOC/Resources/ChangeLog.html @@ -1,6 +1,6 @@ Modulo MP-RIOC -

    Versione: 8.16.2605.1111

    +

    Versione: 8.16.2605.1207


    Note di rilascio:
    • diff --git a/MP.RIOC/Resources/VersNum.txt b/MP.RIOC/Resources/VersNum.txt index dcaf613a..57e5daf4 100644 --- a/MP.RIOC/Resources/VersNum.txt +++ b/MP.RIOC/Resources/VersNum.txt @@ -1 +1 @@ -8.16.2605.1111 +8.16.2605.1207 diff --git a/MP.RIOC/Resources/manifest.xml b/MP.RIOC/Resources/manifest.xml index d59bada6..a43e833c 100644 --- a/MP.RIOC/Resources/manifest.xml +++ b/MP.RIOC/Resources/manifest.xml @@ -1,6 +1,6 @@ - 8.16.2605.1111 + 8.16.2605.1207 https://nexus.steamware.net/repository/SWS/MP-RIOC/stable/LAST/MP.RIOC.zip https://nexus.steamware.net/repository/SWS/MP-RIOC/stable/LAST/ChangeLog.html false