Files
lux/EgwCoreLib.Lux.Data/Services/BaseServ.cs
T
2025-10-22 10:13:33 +02:00

266 lines
10 KiB
C#

using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Options;
using Microsoft.VisualBasic;
using Newtonsoft.Json;
using NLog;
using StackExchange.Redis;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime;
using System.Text;
using System.Threading.Tasks;
namespace EgwCoreLib.Lux.Data.Services
{
/// <summary>
/// Classe base per i servizi che fornisce funzionalità comuni come
/// - connessione a Redis
/// - configurazione
/// - gestione dei messaggi
/// - strategie di caching.
///
/// Questa classe agisce come modello per altri servizi derivati.
/// </summary>
public class BaseServ
{
#region Public Constructors
/// <summary>
/// Inizializza una nuova istanza della classe BaseServ.
/// Configura la connessione Redis, carica le impostazioni di configurazione e inizializza il serializzatore JSON.
/// </summary>
/// <param name="Configuration">Oggetto di configurazione per recuperare le impostazioni dell'applicazione.</param>
/// <param name="RedisConn">Multiplexer di connessione Redis per operazioni sul database.</param>
public BaseServ(IConfiguration Configuration, IConnectionMultiplexer RedisConn)
{
_config = Configuration;
redisConn = RedisConn;
redisDb = redisConn.GetDatabase();
// channel name setup
svgChannel = _config.GetValue<string>("ServerConf:SvgChannel") ?? "Egw:svg:img";
bomChannel = _config.GetValue<string>("ServerConf:BomChannel") ?? "Egw:bom";
updateChannel = _config.GetValue<string>("ServerConf:UpdateChannel") ?? "Egw:update";
shapeChannel = _config.GetValue<string>("ServerConf:ShapeChannel") ?? "Egw:shape:curr";
hwListChannel = _config.GetValue<string>("ServerConf:HwListChannel") ?? "Egw:hw:list";
hwOptChannel = _config.GetValue<string>("ServerConf:HwOptChannel") ?? "Egw:hw:opt";
profListChannel = _config.GetValue<string>("ServerConf:ProfListChannel") ?? "Egw:prof:list";
// Appends ":*" to the channels to enable wildcard subscription for dynamic events
if (!svgChannel.EndsWith(":*"))
{
svgChannel += ":*";
}
if (!bomChannel.EndsWith(":*"))
{
bomChannel += ":*";
}
if (!updateChannel.EndsWith(":*"))
{
updateChannel += ":*";
}
if (!shapeChannel.EndsWith(":*"))
{
shapeChannel += ":*";
}
if (!hwListChannel.EndsWith(":*"))
{
hwListChannel += ":*";
}
if (!hwOptChannel.EndsWith(":*"))
{
hwOptChannel += ":*";
}
if (!profListChannel.EndsWith(":*"))
{
profListChannel += ":*";
}
// Configurazione serializzatore JSON per risolvere errore di loop circolare
JSSettings = new JsonSerializerSettings()
{
ReferenceLoopHandling = ReferenceLoopHandling.Ignore
};
// Configurazione pipe dei messaggi
PipeSvg = new MessagePipe(redisConn, svgChannel);
PipeBom = new MessagePipe(RedisConn, bomChannel);
PipeUpdate = new MessagePipe(RedisConn, updateChannel);
PipeShape = new MessagePipe(RedisConn, shapeChannel);
PipeHwList = new MessagePipe(RedisConn, hwListChannel);
PipeHwOpt = new MessagePipe(RedisConn, hwOptChannel);
PipeProfList = new MessagePipe(RedisConn, profListChannel);
}
#endregion Public Constructors
#region Public Properties
/// <summary>
/// Pipe dei messaggi per la comunicazione riguardo update calcolo BOM
/// </summary>
public MessagePipe PipeBom { get; set; } = null!;
/// <summary>
/// Pipe dei messaggi per ritorno HwList da Engine di calcolo verso interfaccia utente.
/// I messaggi vengono inviati sul canale Redis definito da HwListChannel.
/// </summary>
public MessagePipe PipeHwList { get; set; } = null!;
/// <summary>
/// Pipe dei messaggi per ritorno HwOptions calcolate da Engine di calcolo verso interfaccia utente.
/// I messaggi vengono inviati sul canale Redis definito da HwOptChannel.
/// </summary>
public MessagePipe PipeHwOpt { get; set; } = null!;
/// <summary>
/// Pipe dei messaggi per ritorno ProfileList calcolate da Engine di calcolo verso interfaccia utente.
/// I messaggi vengono inviati sul canale Redis definito da ProfListChannel.
/// </summary>
public MessagePipe PipeProfList { get; set; } = null!;
/// <summary>
/// Pipe dei messaggi per ritorno Shape calcolate da Engine di calcolo verso interfaccia utente.
/// I messaggi vengono inviati sul canale Redis definito da ShapeChannel.
/// </summary>
public MessagePipe PipeShape { get; set; } = null!;
/// <summary>
/// Pipe dei messaggi per ritorno SVG calcolati da Engine di calcolo verso interfaccia utente.
/// I messaggi vengono inviati sul canale Redis definito da SvgChannel.
/// </summary>
public MessagePipe PipeSvg { get; set; } = null!;
/// <summary>
/// Pipe dei messaggi per la comunicazione riguardo update generico UI
/// </summary>
public MessagePipe PipeUpdate { get; set; } = null!;
#endregion Public Properties
#region Protected Fields
/// <summary>
/// Oggetto di configurazione statico per accedere alle impostazioni dell'applicazione (es. stringhe di connessione).
/// Condiviso tra tutte le istanze di BaseServ.
/// </summary>
protected static IConfiguration _config = null!;
/// <summary>
/// Impostazioni del serializzatore JSON utilizzato per gestire oggetti con riferimenti circolari
/// (es. oggetti che si fanno riferimento reciprocamente).
/// </summary>
protected JsonSerializerSettings? JSSettings;
/// <summary>
/// Oggetto per la connessione a Redis utilizzato per operazioni di lettura/scrittura.
/// </summary>
protected IConnectionMultiplexer redisConn = null!;
/// <summary>
/// Database Redis utilizzato per le operazioni di lettura/scrittura
/// nb: ottenuto tramite redisConn.GetDatabase()
/// </summary>
protected IDatabase redisDb = null!;
#endregion Protected Fields
#region Protected Properties
/// <summary>
/// Durata della cache breve (circa 1 minuto + variazione del +/-10%)
/// </summary>
protected TimeSpan FastCache
{
get => TimeSpan.FromSeconds(cacheTtlShort * rnd.Next(900, 1100) / 1000);
}
/// <summary>
/// Durata della cache lunga (+ variazione del +/-10%)
/// </summary>
protected TimeSpan LongCache
{
get => TimeSpan.FromSeconds(cacheTtlLong * rnd.Next(900, 1100) / 1000);
}
/// <summary>
/// Durata della cache molto breve (circa 10 secondi + variazione del +/-10%)
/// </summary>
protected TimeSpan UltraFastCache
{
get => TimeSpan.FromSeconds(cacheTtlShort / 6 * rnd.Next(900, 1100) / 1000);
}
/// <summary>
/// Durata della cache molto lunga (+ variazione del +/-10%)
/// </summary>
protected TimeSpan UltraLongCache
{
get => TimeSpan.FromSeconds(cacheTtlLong * 10 * rnd.Next(900, 1100) / 1000);
}
#endregion Protected Properties
#region Private Fields
/// <summary>
/// Oggetto logger utilizzato per registrare eventi e errori a livello di classe.
/// Utile per il monitoraggio del comportamento dell'applicazione e la risoluzione di problemi.
/// </summary>
private static Logger Log = LogManager.GetCurrentClassLogger();
/// <summary>
/// Redis channel for BOM related info
/// </summary>
private string bomChannel = "";
/// <summary>
/// Durata della cache lunga in secondi (predefinito: 5 minuti)
/// Utilizzato nella proprietà LongCache per definire quanto a lungo i dati devono essere memorizzati in cache.
/// </summary>
private int cacheTtlLong = 60 * 5;
/// <summary>
/// Durata della cache breve in secondi (predefinito: 1 minuto)
/// Utilizzato nelle proprietà FastCache e UltraFastCache per definire la durata della cache breve.
/// </summary>
private int cacheTtlShort = 60 * 1;
/// <summary>
/// Canale ritorno Hw List
/// </summary>
private string hwListChannel = "";
/// <summary>
/// Canale ritorno Hw Options
/// </summary>
private string hwOptChannel = "";
/// <summary>
/// Canale ritorno Profile List
/// </summary>
private string profListChannel = "";
/// <summary>
/// Generatore di numeri casuali utilizzato per introdurre variabilità dinamica nelle durate della cache
/// (simula variazioni reali nella freschezza dei dati e nei tempi di scadenza).
/// </summary>
private Random rnd = new Random();
/// <summary>
/// Canale ritorno shape calcolate
/// </summary>
private string shapeChannel = "";
/// <summary>
/// Nome del canale Redis utilizzato per l'invio/ricezione di messaggi relativi a img svg.
/// Predefinito a "svg:img" con suffisso ":*".
/// </summary>
private string svgChannel = "";
/// <summary>
/// Nome del canale Redis utilizzato per l'invio/ricezione di messaggi di update
/// </summary>
private string updateChannel = "";
#endregion Private Fields
}
}