using Microsoft.AspNetCore.Identity.UI.Services; using Newtonsoft.Json; using NLog; using StackExchange.Redis; using System.Diagnostics; using WebDoorCreator.Core; using WebDoorCreator.Data.DbModels; namespace WebDoorCreator.API.Data { public class ApiDataService : IDisposable { #region Public Fields /// /// Classe Accesso metodi DB /// public static WebDoorCreator.Data.Controllers.WebDoorCreatorController dbController = null!; #endregion Public Fields #region Public Constructors /// /// Init classe /// /// /// /// /// public ApiDataService(IConfiguration configuration, IEmailSender emailSender, IConnectionMultiplexer redisConn) { _configuration = configuration; _emailSender = emailSender; // setup compoenti REDIS var redConnString = _configuration.GetConnectionString("Redis"); if (redConnString == null) { Log.Error("REDIS ConnString empty!"); } else { this.redisConn = ConnectionMultiplexer.Connect(redConnString); this.redisDb = this.redisConn.GetDatabase(); } // Conf DB var connStrDB = _configuration.GetConnectionString("WDC.DB"); if (string.IsNullOrEmpty(connStrDB)) { Log.Error("ConnString empty!"); } else { dbController = new WebDoorCreator.Data.Controllers.WebDoorCreatorController(configuration); Log.Info("DbController OK"); } } #endregion Public Constructors #region Public Methods public void Dispose() { // Clear database controller dbController.Dispose(); } /// /// Doors list by orderId /// public async Task?> DoorGetByOrderId(int orderId) { string source = "DB"; List? dbResult = new List(); // cerco da cache string currKey = $"{Constants.rKeyOrderDetail}:{orderId}"; Stopwatch stopWatch = new Stopwatch(); stopWatch.Start(); string? rawData = await redisDb.StringGetAsync(currKey); if (!string.IsNullOrEmpty(rawData)) { source = "REDIS"; var tempResult = JsonConvert.DeserializeObject>(rawData); if (tempResult == null) { dbResult = new List(); } else { dbResult = tempResult; } } else { dbResult = dbController.DoorsGetByOrderId(orderId); rawData = JsonConvert.SerializeObject(dbResult, JSSettings); await redisDb.StringSetAsync(currKey, rawData, UltraLongCache); } if (dbResult == null) { dbResult = new List(); } stopWatch.Stop(); TimeSpan ts = stopWatch.Elapsed; Log.Debug($"DoorGetByOrderId | {source} in: {ts.TotalMilliseconds} ms"); return dbResult; } #endregion Public Methods #region Protected Fields protected const string rKeyCalcOreFase = "Check:OreFasi"; protected const string rKeyFasiAct = "Check:FasiAct"; protected const string rKeyProjAct = "Check:ProjAct"; /// /// TTL da 1 min x cache Redis /// protected const int shortTTL = 60 * 5; protected Random rnd = new Random(); #endregion Protected Fields #region Protected Methods /// /// Recupero chiave da redis /// /// /// protected async Task getRSV(string rKey) { string answ = ""; var rawData = await redisDb.StringGetAsync(rKey); if (rawData.HasValue) { answ = $"{rawData}"; } return answ; } /// /// Salvataggio chiave in redis /// /// /// /// /// protected async Task setRSV(string rKey, string rVal, int ttlSec) { bool fatto = false; await redisDb.StringSetAsync(rKey, rVal, TimeSpan.FromSeconds(ttlSec)); fatto = true; return fatto; } /// /// Salvataggio chiave in redis /// /// /// /// /// protected async Task setRSV(string rKey, int rValInt, int ttlSec) { bool fatto = false; await redisDb.StringSetAsync(rKey, rValInt, TimeSpan.FromSeconds(ttlSec)); fatto = true; return fatto; } /// /// Registra in cache chiave se non fosse già in elenco /// /// protected void trackCache(string newKey) { if (!cachedDataList.Contains(newKey)) { cachedDataList.Add(newKey); } } #endregion Protected Methods #region Private Fields private static IConfiguration _configuration = null!; private static JsonSerializerSettings? JSSettings; private static Logger Log = LogManager.GetCurrentClassLogger(); private readonly IEmailSender _emailSender; /// /// Elenco obj in cache /// private List cachedDataList = new List(); /// /// Durata cache lunga IN SECONDI /// private int cacheTtlLong = 60 * 5; /// /// Durata cache breve IN SECONDI /// private int cacheTtlShort = 60 * 1; /// /// Oggetto per connessione a REDIS /// private ConnectionMultiplexer redisConn = null!; /// /// Oggetto DB redis da impiegare x chiamate R/W /// private IDatabase redisDb = null!; #endregion Private Fields #region Private Properties /// /// Durata cache lunga (+ perturbazione percentuale +/-10%) /// private TimeSpan FastCache { get => TimeSpan.FromSeconds(cacheTtlShort * rnd.Next(900, 1100) / 1000); } /// /// Durata cache lunga (+ perturbazione percentuale +/-10%) /// private TimeSpan LongCache { get => TimeSpan.FromSeconds(cacheTtlLong * rnd.Next(900, 1100) / 1000); } /// /// Durata cache lunga (+ perturbazione percentuale +/-10%) /// private TimeSpan UltraLongCache { get => TimeSpan.FromSeconds(cacheTtlLong * 10 * rnd.Next(900, 1100) / 1000); } #endregion Private Properties } }