From 38b8f37d30bd88f3089ff2efccb0a33941737a01 Mon Sep 17 00:00:00 2001 From: Samuele Locatelli Date: Wed, 27 May 2026 14:11:31 +0200 Subject: [PATCH] Riorganizzazione codice MpDataService --- MP.SPEC/Data/MpDataService.cs | 283 +++++++++++++++++----------------- 1 file changed, 140 insertions(+), 143 deletions(-) diff --git a/MP.SPEC/Data/MpDataService.cs b/MP.SPEC/Data/MpDataService.cs index 777ad5e8..7a2894cb 100644 --- a/MP.SPEC/Data/MpDataService.cs +++ b/MP.SPEC/Data/MpDataService.cs @@ -82,18 +82,14 @@ namespace MP.SPEC.Data #endregion Public Events #region Public Properties + public static MpSpecController dbController { get; set; } = null!; public static MpMongoController mongoController { get; set; } = null!; public MessagePipe BroadastMsgPipe { get; set; } = null!; public Dictionary> currTagConf { get; set; } = new Dictionary>(); - // Cache per controllo eliminazione articoli (Smart HashSet approach) - private HashSet _usedArtIdsCache = new(); - private HashSet _unusedArtIdsCache = new(); - private DateTime _artCacheExpiry = DateTime.MinValue; #endregion Public Properties - #region Public Methods /// @@ -412,7 +408,6 @@ namespace MP.SPEC.Data await dbController.ArticoliGetByTipoAsync(tipo, azienda) ?? new List() ); - } /// @@ -438,97 +433,6 @@ namespace MP.SPEC.Data ); } - /// - /// Implementa gestione recupero cache da memoria o da obj esterno + cache memoria + tracking attività - /// - /// - /// - /// - /// - /// - private async Task GetOrFetchAsync(string operationName, string cacheKey, Func> fetchFunc, TimeSpan expiration, params string[] tags) - { - using var activity = ActivitySource.StartActivity(operationName); - string source; - var tryGet = await _cache.TryGetAsync(cacheKey); - if (tryGet.HasValue) - { - source = "MEMORY"; - var result = tryGet.Value!; - - activity?.SetTag("data.source", source); - activity?.Stop(); - LogTrace($"{operationName} | {source} | {activity?.Duration.TotalMilliseconds:F4} ms"); - return result; - } - bool fromDb = false; - var final = await _cache.GetOrSetAsync( - cacheKey, - async _ => - { - fromDb = true; - return await fetchFunc(); - }, - opt => - { - opt.SetDuration(expiration) - .SetFailSafe(true); - - //if (tags != null && tags.Length > 0) - // opt.SetTags(tags); - - }); - - source = fromDb ? "DB" : "REDIS"; - activity?.SetTag("data.source", source); - activity?.Stop(); - LogTrace($"{operationName} | {source} | {activity?.Duration.TotalMilliseconds:F4} ms"); - return final!; - } - - - /// - /// Cancellazione FusionCache (totale) - /// - /// - public async Task FlushCacheAsync() - { - bool fatto = false; - await _cache.ClearAsync(); - _configData.Clear(); - fatto = true; - return fatto; - } - - /// - /// Cancellazione FusionCache dato elenco tags - /// - /// - public async Task FlushCacheByTagsAsync(List listTags) - { - bool fatto = false; - foreach (var item in listTags) - { - await _cache.RemoveByTagAsync(item); - } - _configData.Clear(); - fatto = true; - return fatto; - } - /// - /// Cancellazione FusionCache dato singolo tag - /// - /// - public async Task FlushCacheByTagAsync(string tag) - { - bool fatto = false; - await _cache.RemoveByTagAsync(tag); - _configData.Clear(); - fatto = true; - return fatto; - } - - /// /// Aggiornamento record selezionato /// @@ -546,7 +450,6 @@ namespace MP.SPEC.Data return fatto; } - /// /// Verifica se sia possiubile cancellare articolo dato suo CodArt cercando su redis o su /// tab veto da DB @@ -592,42 +495,6 @@ namespace MP.SPEC.Data return !usato; } - /// - /// Caricamento asincrono della cache degli articoli (Used/Unused) - /// - public async Task EnsureArtCacheLoadedAsync(bool forceReload) - { - if (!forceReload && (DateTime.Now < _artCacheExpiry && (_usedArtIdsCache.Count > 0 || _unusedArtIdsCache.Count > 0))) - return; - - try - { - // verifico quale sia il set + piccolo - int totalCount = await dbController.ArticoliCountAsync(); - int usedCount = await dbController.ArticoliCountUsedAsync(); - - if (usedCount <= (totalCount - usedCount)) - { - var usedList = await dbController.ArticoliGetUsedAsync(); - _usedArtIdsCache = new HashSet(usedList.Select(x => x.CodArticolo)); - _unusedArtIdsCache.Clear(); - } - else - { - var unusedList = await dbController.ArticoliGetUnusedAsync(); - _unusedArtIdsCache = new HashSet(unusedList.Select(x => x.CodArticolo)); - _usedArtIdsCache.Clear(); - } - _artCacheExpiry = DateTime.Now.AddMinutes(15); // TTL ragionevole per la cache locale - } - catch (Exception ex) - { - Log.Error($"Errore nel caricamento cache articoli: {ex.Message}"); - _artCacheExpiry = DateTime.Now.AddSeconds(1); // Retry breve in caso di errore - } - } - - public string CalcRecipe(RecipeModel currRecipe) { using var activity = ActivitySource.StartActivity("CalcRecipe"); @@ -1037,6 +904,41 @@ namespace MP.SPEC.Data return result; } + /// + /// Caricamento asincrono della cache degli articoli (Used/Unused) + /// + public async Task EnsureArtCacheLoadedAsync(bool forceReload) + { + if (!forceReload && (DateTime.Now < _artCacheExpiry && (_usedArtIdsCache.Count > 0 || _unusedArtIdsCache.Count > 0))) + return; + + try + { + // verifico quale sia il set + piccolo + int totalCount = await dbController.ArticoliCountAsync(); + int usedCount = await dbController.ArticoliCountUsedAsync(); + + if (usedCount <= (totalCount - usedCount)) + { + var usedList = await dbController.ArticoliGetUsedAsync(); + _usedArtIdsCache = new HashSet(usedList.Select(x => x.CodArticolo)); + _unusedArtIdsCache.Clear(); + } + else + { + var unusedList = await dbController.ArticoliGetUnusedAsync(); + _unusedArtIdsCache = new HashSet(unusedList.Select(x => x.CodArticolo)); + _usedArtIdsCache.Clear(); + } + _artCacheExpiry = DateTime.Now.AddMinutes(15); // TTL ragionevole per la cache locale + } + catch (Exception ex) + { + Log.Error($"Errore nel caricamento cache articoli: {ex.Message}"); + _artCacheExpiry = DateTime.Now.AddSeconds(1); // Retry breve in caso di errore + } + } + /// /// Aggiunta record EventList /// @@ -1189,6 +1091,48 @@ namespace MP.SPEC.Data return fatto; } + /// + /// Cancellazione FusionCache (totale) + /// + /// + public async Task FlushCacheAsync() + { + bool fatto = false; + await _cache.ClearAsync(); + _configData.Clear(); + fatto = true; + return fatto; + } + + /// + /// Cancellazione FusionCache dato singolo tag + /// + /// + public async Task FlushCacheByTagAsync(string tag) + { + bool fatto = false; + await _cache.RemoveByTagAsync(tag); + _configData.Clear(); + fatto = true; + return fatto; + } + + /// + /// Cancellazione FusionCache dato elenco tags + /// + /// + public async Task FlushCacheByTagsAsync(List listTags) + { + bool fatto = false; + foreach (var item in listTags) + { + await _cache.RemoveByTagAsync(item); + } + _configData.Clear(); + fatto = true; + return fatto; + } + public async Task FlushCacheFluxLog() { using var activity = ActivitySource.StartActivity("FlushCacheFluxLog"); @@ -1739,7 +1683,7 @@ namespace MP.SPEC.Data LogTrace($"MacchineGetFilt | Read from {source}: {activity?.Duration.TotalMilliseconds}ms"); return result; } - private readonly IFusionCache _cache; + /// /// Elenco di tutte le macchine filtrate x gruppo /// @@ -2072,12 +2016,6 @@ namespace MP.SPEC.Data return dbResult; } - /// - /// ODL correnti (tutti) - /// - /// - /// - public async Task> OdlGetCurrentAsync() { string redisKey = Utils.redisOdlCurrByMac; @@ -2100,7 +2038,11 @@ namespace MP.SPEC.Data ); } - + /// + /// ODL correnti (tutti) + /// + /// + /// /// /// elenco TUTTI gli ODL /// @@ -2528,7 +2470,6 @@ namespace MP.SPEC.Data endDate ) ?? new List() ); - } /// @@ -3256,8 +3197,17 @@ namespace MP.SPEC.Data private static Logger Log = LogManager.GetCurrentClassLogger(); + private readonly IFusionCache _cache; + + private DateTime _artCacheExpiry = DateTime.MinValue; + private Dictionary _configData = new(); + private HashSet _unusedArtIdsCache = new(); + + // Cache per controllo eliminazione articoli (Smart HashSet approach) + private HashSet _usedArtIdsCache = new(); + private string MpIoNS = ""; /// @@ -3326,6 +3276,53 @@ namespace MP.SPEC.Data } } + /// + /// Implementa gestione recupero cache da memoria o da obj esterno + cache memoria + tracking attività + /// + /// + /// + /// + /// + /// + private async Task GetOrFetchAsync(string operationName, string cacheKey, Func> fetchFunc, TimeSpan expiration, params string[] tags) + { + using var activity = ActivitySource.StartActivity(operationName); + string source; + var tryGet = await _cache.TryGetAsync(cacheKey); + if (tryGet.HasValue) + { + source = "MEMORY"; + var result = tryGet.Value!; + + activity?.SetTag("data.source", source); + activity?.Stop(); + LogTrace($"{operationName} | {source} | {activity?.Duration.TotalMilliseconds:F4} ms"); + return result; + } + bool fromDb = false; + var final = await _cache.GetOrSetAsync( + cacheKey, + async _ => + { + fromDb = true; + return await fetchFunc(); + }, + opt => + { + opt.SetDuration(expiration) + .SetFailSafe(true); + + //if (tags != null && tags.Length > 0) + // opt.SetTags(tags); + }); + + source = fromDb ? "DB" : "REDIS"; + activity?.SetTag("data.source", source); + activity?.Stop(); + LogTrace($"{operationName} | {source} | {activity?.Duration.TotalMilliseconds:F4} ms"); + return final!; + } + /// /// Helper trace messaggio log (SE abilitato) ///