Riorganizzazione codice MpDataService
This commit is contained in:
+140
-143
@@ -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<string, List<TagData>> currTagConf { get; set; } = new Dictionary<string, List<TagData>>();
|
||||
|
||||
// Cache per controllo eliminazione articoli (Smart HashSet approach)
|
||||
private HashSet<string> _usedArtIdsCache = new();
|
||||
private HashSet<string> _unusedArtIdsCache = new();
|
||||
private DateTime _artCacheExpiry = DateTime.MinValue;
|
||||
#endregion Public Properties
|
||||
|
||||
|
||||
#region Public Methods
|
||||
|
||||
/// <summary>
|
||||
@@ -412,7 +408,6 @@ namespace MP.SPEC.Data
|
||||
await dbController.ArticoliGetByTipoAsync(tipo, azienda)
|
||||
?? new List<AnagArticoliModel>()
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -438,97 +433,6 @@ namespace MP.SPEC.Data
|
||||
);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Implementa gestione recupero cache da memoria o da obj esterno + cache memoria + tracking attività
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="cacheKey"></param>
|
||||
/// <param name="fetchFunc"></param>
|
||||
/// <param name="expiration"></param>
|
||||
/// <returns></returns>
|
||||
private async Task<T> GetOrFetchAsync<T>(string operationName, string cacheKey, Func<Task<T>> fetchFunc, TimeSpan expiration, params string[] tags)
|
||||
{
|
||||
using var activity = ActivitySource.StartActivity(operationName);
|
||||
string source;
|
||||
var tryGet = await _cache.TryGetAsync<T>(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<T>(
|
||||
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!;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Cancellazione FusionCache (totale)
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public async Task<bool> FlushCacheAsync()
|
||||
{
|
||||
bool fatto = false;
|
||||
await _cache.ClearAsync();
|
||||
_configData.Clear();
|
||||
fatto = true;
|
||||
return fatto;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Cancellazione FusionCache dato elenco tags
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public async Task<bool> FlushCacheByTagsAsync(List<string> listTags)
|
||||
{
|
||||
bool fatto = false;
|
||||
foreach (var item in listTags)
|
||||
{
|
||||
await _cache.RemoveByTagAsync(item);
|
||||
}
|
||||
_configData.Clear();
|
||||
fatto = true;
|
||||
return fatto;
|
||||
}
|
||||
/// <summary>
|
||||
/// Cancellazione FusionCache dato singolo tag
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public async Task<bool> FlushCacheByTagAsync(string tag)
|
||||
{
|
||||
bool fatto = false;
|
||||
await _cache.RemoveByTagAsync(tag);
|
||||
_configData.Clear();
|
||||
fatto = true;
|
||||
return fatto;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Aggiornamento record selezionato
|
||||
/// </summary>
|
||||
@@ -546,7 +450,6 @@ namespace MP.SPEC.Data
|
||||
return fatto;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Caricamento asincrono della cache degli articoli (Used/Unused)
|
||||
/// </summary>
|
||||
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<string>(usedList.Select(x => x.CodArticolo));
|
||||
_unusedArtIdsCache.Clear();
|
||||
}
|
||||
else
|
||||
{
|
||||
var unusedList = await dbController.ArticoliGetUnusedAsync();
|
||||
_unusedArtIdsCache = new HashSet<string>(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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Caricamento asincrono della cache degli articoli (Used/Unused)
|
||||
/// </summary>
|
||||
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<string>(usedList.Select(x => x.CodArticolo));
|
||||
_unusedArtIdsCache.Clear();
|
||||
}
|
||||
else
|
||||
{
|
||||
var unusedList = await dbController.ArticoliGetUnusedAsync();
|
||||
_unusedArtIdsCache = new HashSet<string>(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
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Aggiunta record EventList
|
||||
/// </summary>
|
||||
@@ -1189,6 +1091,48 @@ namespace MP.SPEC.Data
|
||||
return fatto;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Cancellazione FusionCache (totale)
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public async Task<bool> FlushCacheAsync()
|
||||
{
|
||||
bool fatto = false;
|
||||
await _cache.ClearAsync();
|
||||
_configData.Clear();
|
||||
fatto = true;
|
||||
return fatto;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Cancellazione FusionCache dato singolo tag
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public async Task<bool> FlushCacheByTagAsync(string tag)
|
||||
{
|
||||
bool fatto = false;
|
||||
await _cache.RemoveByTagAsync(tag);
|
||||
_configData.Clear();
|
||||
fatto = true;
|
||||
return fatto;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Cancellazione FusionCache dato elenco tags
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public async Task<bool> FlushCacheByTagsAsync(List<string> listTags)
|
||||
{
|
||||
bool fatto = false;
|
||||
foreach (var item in listTags)
|
||||
{
|
||||
await _cache.RemoveByTagAsync(item);
|
||||
}
|
||||
_configData.Clear();
|
||||
fatto = true;
|
||||
return fatto;
|
||||
}
|
||||
|
||||
public async Task<bool> 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;
|
||||
|
||||
/// <summary>
|
||||
/// Elenco di tutte le macchine filtrate x gruppo
|
||||
/// </summary>
|
||||
@@ -2072,12 +2016,6 @@ namespace MP.SPEC.Data
|
||||
return dbResult;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// ODL correnti (tutti)
|
||||
/// </summary>
|
||||
/// <param name="idxMacchina"></param>
|
||||
/// <returns></returns>
|
||||
|
||||
public async Task<List<string>> OdlGetCurrentAsync()
|
||||
{
|
||||
string redisKey = Utils.redisOdlCurrByMac;
|
||||
@@ -2100,7 +2038,11 @@ namespace MP.SPEC.Data
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// ODL correnti (tutti)
|
||||
/// </summary>
|
||||
/// <param name="idxMacchina"></param>
|
||||
/// <returns></returns>
|
||||
/// <summary>
|
||||
/// elenco TUTTI gli ODL
|
||||
/// </summary>
|
||||
@@ -2528,7 +2470,6 @@ namespace MP.SPEC.Data
|
||||
endDate
|
||||
) ?? new List<PODLExpModel>()
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -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<string, string> _configData = new();
|
||||
|
||||
private HashSet<string> _unusedArtIdsCache = new();
|
||||
|
||||
// Cache per controllo eliminazione articoli (Smart HashSet approach)
|
||||
private HashSet<string> _usedArtIdsCache = new();
|
||||
|
||||
private string MpIoNS = "";
|
||||
|
||||
/// <summary>
|
||||
@@ -3326,6 +3276,53 @@ namespace MP.SPEC.Data
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Implementa gestione recupero cache da memoria o da obj esterno + cache memoria + tracking attività
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="cacheKey"></param>
|
||||
/// <param name="fetchFunc"></param>
|
||||
/// <param name="expiration"></param>
|
||||
/// <returns></returns>
|
||||
private async Task<T> GetOrFetchAsync<T>(string operationName, string cacheKey, Func<Task<T>> fetchFunc, TimeSpan expiration, params string[] tags)
|
||||
{
|
||||
using var activity = ActivitySource.StartActivity(operationName);
|
||||
string source;
|
||||
var tryGet = await _cache.TryGetAsync<T>(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<T>(
|
||||
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!;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Helper trace messaggio log (SE abilitato)
|
||||
/// </summary>
|
||||
|
||||
Reference in New Issue
Block a user