using Microsoft.Extensions.Caching.Distributed; using Microsoft.Extensions.Caching.Memory; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Logging; using Newtonsoft.Json; using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Text; using System.Threading.Tasks; namespace MP.Stats.Data { public class MpStatsService : IDisposable { #region Private Fields private static IConfiguration _configuration; private static ILogger _logger; private static List ActionsList = new List(); private readonly IDistributedCache distributedCache; private readonly IMemoryCache memoryCache; /// /// Durata assoluta massima della cache /// private int chAbsExp = 15; /// /// Durata della cache in modalità inattiva (non acceduta) prima di venire rimossa /// NON estende oltre il tempo massimo di validità della cache (chAbsExp) /// private int chSliExp = 5; #endregion Private Fields #region Protected Fields protected static string connStringBBM = ""; protected static string connStringFatt = ""; #endregion Protected Fields #region Public Fields public static MP.Data.Controllers.MpStatsController dbController; #endregion Public Fields #region Public Constructors public MpStatsService(IConfiguration configuration, ILogger logger, IMemoryCache memoryCache, IDistributedCache distributedCache) { _logger = logger; _configuration = configuration; // conf cache this.memoryCache = memoryCache; this.distributedCache = distributedCache; // conf DB string connStr = _configuration.GetConnectionString("Mp.Stats"); if (string.IsNullOrEmpty(connStr)) { _logger.LogError("ConnString empty!"); } else { dbController = new MP.Data.Controllers.MpStatsController(configuration); StringBuilder sb = new StringBuilder(); sb.AppendLine($"DbController OK"); //sb.AppendLine($"CST: {dbController.CustomersCount()} | CNT: {dbController.CountersCount()} | BSK: {dbController.BasketsCount()} | NGT: {dbController.NegotiationsCount()} | DOC: {dbController.DocsCount()} | ITM: {dbController.ItemsCount()} | RES: {dbController.ResourcesCount()}"); _logger.LogInformation(sb.ToString()); } } #endregion Public Constructors #region Private Properties private DistributedCacheEntryOptions cacheOpt { get { return new DistributedCacheEntryOptions().SetAbsoluteExpiration(DateTime.Now.AddMinutes(chAbsExp)).SetSlidingExpiration(TimeSpan.FromMinutes(chSliExp)); } } private DistributedCacheEntryOptions cacheOptLong { get { return new DistributedCacheEntryOptions().SetAbsoluteExpiration(DateTime.Now.AddMinutes(chAbsExp * 10)).SetSlidingExpiration(TimeSpan.FromMinutes(chSliExp)); } } #endregion Private Properties #region Protected Methods protected string getCacheKey(string TableName, SelectData CurrFilter) { string answ = $"{TableName}:M_{CurrFilter.IdxMacchina}:AZ_{CurrFilter.Azione}:ART_{CurrFilter.CodArticolo}:KR_{CurrFilter.KeyRichiesta}:O_{CurrFilter.IdxOdl}:D_{CurrFilter.DateStart:yyyyMMddHHmm}_{CurrFilter.DateEnd:yyyyMMddHHmm}"; return answ; } protected string getCacheKeyPaged(string TableName, SelectData CurrFilter) { string answ = $"{TableName}:M_{CurrFilter.IdxMacchina}:A_{CurrFilter.CodArticolo}:K_{CurrFilter.KeyRichiesta}:O_{CurrFilter.IdxOdl}:D_{CurrFilter.DateStart:yyMMddHHmm}_{CurrFilter.DateEnd:yyMMddHHmm}:R_{CurrFilter.FirstRecord}_{CurrFilter.FirstRecord + CurrFilter.NumRecord}"; return answ; } #endregion Protected Methods #region Public Methods public async Task> ActionsGetAll() { //return Task.FromResult(dbController.ActionsGetAll()); List dbResult = new List(); string cacheKey = "MP:STATS:AZIONI_ALL"; string rawData; var redisDataList = await distributedCache.GetAsync(cacheKey); if (redisDataList != null) { rawData = Encoding.UTF8.GetString(redisDataList); dbResult = JsonConvert.DeserializeObject>(rawData); } else { Stopwatch stopWatch = new Stopwatch(); stopWatch.Start(); dbResult = dbController.ActionsGetAll(); rawData = JsonConvert.SerializeObject(dbResult); redisDataList = Encoding.UTF8.GetBytes(rawData); await distributedCache.SetAsync(cacheKey, redisDataList, cacheOpt); stopWatch.Stop(); TimeSpan ts = stopWatch.Elapsed; _logger.LogTrace($"Effettuata lettura da DB + caching per AzioniUL: {ts.TotalMilliseconds} ms"); } return await Task.FromResult(dbResult); } public Task> ArticoliGetSearch(int numRecord, string searchVal = "") { List answ = new List(); answ.Add(new AutocompleteModel { LabelField = "--- TUTTE ---", ValueField = "*" }); if (numRecord > -1) { answ.AddRange(dbController.ArticoliGetSearch(numRecord, searchVal).Select(x => new AutocompleteModel { LabelField = $"{x.CodArticolo} {x.DescArticolo} {x.Disegno}", ValueField = x.CodArticolo }).ToList()); } return Task.FromResult(answ); } public async Task> ArticoliList(string searchVal) { List answ = new List(); answ.Add(new AutocompleteModel { LabelField = "--- TUTTE ---", ValueField = "*" }); var listMacchine = dbController.MacchineGetAll(); answ.AddRange(listMacchine.Select(x => new AutocompleteModel { LabelField = x.IdxMacchina, ValueField = x.IdxMacchina }).ToList()); return await Task.FromResult(answ); } public Task> AzioniList() { List answ = new List(); answ.Add(new AutocompleteModel { LabelField = "--- TUTTE ---", ValueField = "*" }); answ.AddRange(dbController.ActionsGetAll().Select(x => new AutocompleteModel { LabelField = $"{x.Descrizione}", ValueField = x.Azione}).ToList()); return Task.FromResult(answ); } public Task> CommesseGetSearch(int numRecord, string searchVal = "") { List answ = new List(); answ.Add(new AutocompleteModel { LabelField = "--- TUTTE ---", ValueField = "*" }); if (numRecord > -1) { answ.AddRange(dbController.CommesseGetSearch(numRecord, searchVal).GroupBy(x => x.KeyRichiesta).Select(x => new AutocompleteModel { LabelField = $"{x.First().CodArticolo} | {x.First().KeyRichiesta}", ValueField = x.First().KeyRichiesta }).ToList()); } return Task.FromResult(answ); } public void Dispose() { // Clear database controller dbController.Dispose(); } public Task> MacchineGetAll() { return Task.FromResult(dbController.MacchineGetAll().ToList()); } public Task> MachineList() { List answ = new List(); answ.Add(new AutocompleteModel { LabelField = "--- TUTTE ---", ValueField = "*" }); answ.AddRange(dbController.MacchineGetAll().Select(x => new AutocompleteModel { LabelField = $"{x.IdxMacchina} | {x.Nome} {x.Descrizione} ", ValueField = x.IdxMacchina }).ToList()); return Task.FromResult(answ); } public void rollBackEdit(object item) { dbController.RollBackEntity(item); } public async Task> StatControlliGetAll(SelectData CurrFilter, string searchVal = "") { //return Task.FromResult(dbController.StatControlliGetAll(DataStart, DataEnd, IdxMacchina, IdxODL, KeyRichiesta, CodArticolo).ToArray()); List dbResult = new List(); string cacheKey = getCacheKey("MP:STATS:CONTROLLI", CurrFilter); string rawData; var redisDataList = await distributedCache.GetAsync(cacheKey); if (redisDataList != null) { rawData = Encoding.UTF8.GetString(redisDataList); dbResult = JsonConvert.DeserializeObject>(rawData); } else { Stopwatch stopWatch = new Stopwatch(); stopWatch.Start(); dbResult = dbController.StatControlliGetAll(CurrFilter.DateStart, CurrFilter.DateEnd, CurrFilter.IdxMacchina, CurrFilter.IdxOdl, CurrFilter.KeyRichiesta, CurrFilter.CodArticolo); rawData = JsonConvert.SerializeObject(dbResult); redisDataList = Encoding.UTF8.GetBytes(rawData); await distributedCache.SetAsync(cacheKey, redisDataList, cacheOpt); stopWatch.Stop(); TimeSpan ts = stopWatch.Elapsed; _logger.LogTrace($"Effettuata lettura da DB + caching per ResControlli: {ts.TotalMilliseconds} ms"); } return await Task.FromResult(dbResult); } public async Task> StatDdbGetAll(SelectData CurrFilter, string searchVal = "") { //return Task.FromResult(dbController.StatDdbGetAll(numRecord, searchVal).ToArray()); List dbResult = new List(); string cacheKey = getCacheKeyPaged("MP:STATS:DDBT", CurrFilter); string rawData; var redisDataList = await distributedCache.GetAsync(cacheKey); if (redisDataList != null) { rawData = Encoding.UTF8.GetString(redisDataList); dbResult = JsonConvert.DeserializeObject>(rawData); } else { Stopwatch stopWatch = new Stopwatch(); stopWatch.Start(); dbResult = dbController.StatDdbGetAll(CurrFilter.DateStart, CurrFilter.DateEnd, CurrFilter.IdxMacchina, CurrFilter.IdxOdl, CurrFilter.KeyRichiesta, CurrFilter.CodArticolo, CurrFilter.FirstRecord, CurrFilter.NumRecord); rawData = JsonConvert.SerializeObject(dbResult); redisDataList = Encoding.UTF8.GetBytes(rawData); await distributedCache.SetAsync(cacheKey, redisDataList, cacheOpt); stopWatch.Stop(); TimeSpan ts = stopWatch.Elapsed; _logger.LogTrace($"Effettuata lettura da DB + caching per DdbTurni: {ts.TotalMilliseconds} ms"); } return await Task.FromResult(dbResult); } /// /// Recupera TUTTI x export /// /// /// /// public async Task> StatDdbGetAllExport(SelectData CurrFilter, string searchVal = "") { //return Task.FromResult(dbController.StatDdbGetAll(numRecord, searchVal).ToArray()); List dbResult = new List(); Stopwatch stopWatch = new Stopwatch(); stopWatch.Start(); dbResult = dbController.StatDdbGetAll(CurrFilter.DateStart, CurrFilter.DateEnd, CurrFilter.IdxMacchina, CurrFilter.IdxOdl, CurrFilter.KeyRichiesta, CurrFilter.CodArticolo, 1, 0); stopWatch.Stop(); TimeSpan ts = stopWatch.Elapsed; _logger.LogTrace($"Effettuata lettura COMPLETA da DB + caching per StatDdbGetAllExport: {ts.TotalMilliseconds} ms"); return await Task.FromResult(dbResult); } public async Task StatDdbGetCount(SelectData CurrFilter, string searchVal = "") { int numRec = 0; string cacheKey = getCacheKey("MP:STATS:DDBT-COUNT", CurrFilter); string rawData; var redisDataList = await distributedCache.GetAsync(cacheKey); if (redisDataList != null) { rawData = Encoding.UTF8.GetString(redisDataList); int.TryParse(rawData, out numRec); } else { Stopwatch stopWatch = new Stopwatch(); stopWatch.Start(); numRec = dbController.StatDdbGetCount(CurrFilter.DateStart, CurrFilter.DateEnd, CurrFilter.IdxMacchina, CurrFilter.IdxOdl, CurrFilter.KeyRichiesta, CurrFilter.CodArticolo); rawData = $"{numRec}"; redisDataList = Encoding.UTF8.GetBytes(rawData); await distributedCache.SetAsync(cacheKey, redisDataList, cacheOptLong); stopWatch.Stop(); TimeSpan ts = stopWatch.Elapsed; _logger.LogTrace($"Effettuata lettura da DB + caching per DdbTurni: {ts.TotalMilliseconds} ms"); } return await Task.FromResult(numRec); } public async Task> StatOdlGetAll(SelectData CurrFilter, string searchVal = "") { //return Task.FromResult(dbController.StatOdlGetAll(numRecord, searchVal)); List dbResult = new List(); string cacheKey = getCacheKey("MP:STATS:ODL", CurrFilter); string rawData; var redisDataList = await distributedCache.GetAsync(cacheKey); if (redisDataList != null) { rawData = Encoding.UTF8.GetString(redisDataList); dbResult = JsonConvert.DeserializeObject>(rawData); } else { Stopwatch stopWatch = new Stopwatch(); stopWatch.Start(); dbResult = dbController.StatOdlGetAll(CurrFilter.DateStart, CurrFilter.DateEnd, CurrFilter.IdxMacchina, CurrFilter.IdxOdl, CurrFilter.KeyRichiesta, CurrFilter.CodArticolo); rawData = JsonConvert.SerializeObject(dbResult); redisDataList = Encoding.UTF8.GetBytes(rawData); await distributedCache.SetAsync(cacheKey, redisDataList, cacheOpt); stopWatch.Stop(); TimeSpan ts = stopWatch.Elapsed; _logger.LogTrace($"Effettuata lettura da DB + caching per ODL: {ts.TotalMilliseconds} ms"); } return await Task.FromResult(dbResult); } public async Task> StatScartiGetAll(SelectData CurrFilter, string searchVal = "") { //return Task.FromResult(dbController.StatScartiGetAll(DataStart, DataEnd, IdxMacchina, IdxODL, KeyRichiesta, CodArticolo).ToArray()); List dbResult = new List(); string cacheKey = getCacheKey("MP:STATS:SCARTI:RAW", CurrFilter); string rawData; var redisDataList = await distributedCache.GetAsync(cacheKey); if (redisDataList != null) { rawData = Encoding.UTF8.GetString(redisDataList); dbResult = JsonConvert.DeserializeObject>(rawData); } else { Stopwatch stopWatch = new Stopwatch(); stopWatch.Start(); dbResult = dbController.StatScartiGetAll(CurrFilter.DateStart, CurrFilter.DateEnd, CurrFilter.IdxMacchina, CurrFilter.IdxOdl, CurrFilter.KeyRichiesta, CurrFilter.CodArticolo); rawData = JsonConvert.SerializeObject(dbResult); redisDataList = Encoding.UTF8.GetBytes(rawData); await distributedCache.SetAsync(cacheKey, redisDataList, cacheOpt); stopWatch.Stop(); TimeSpan ts = stopWatch.Elapsed; _logger.LogTrace($"Effettuata lettura da DB + caching per ResScarti: {ts.TotalMilliseconds} ms"); } return await Task.FromResult(dbResult); } public async Task> StatTurniOeeGetAllAsync(DateTime DataStart, DateTime DataEnd, string IdxMacchina, int IdxODL, string KeyRichiesta, string CodArticolo, string searchVal = "") { return await Task.FromResult(dbController.StatTurniOeeGetAll(DataStart, DataEnd, IdxMacchina, IdxODL, KeyRichiesta, CodArticolo)); } public async Task> StatTurniOeeGetAllCached(SelectData CurrFilter, string searchVal = "") { List dbResult = new List(); string cacheKey = getCacheKey("MP:STATS:OEE", CurrFilter); string rawData; var redisDataList = await distributedCache.GetAsync(cacheKey); if (redisDataList != null) { rawData = Encoding.UTF8.GetString(redisDataList); dbResult = JsonConvert.DeserializeObject>(rawData); } else { Stopwatch stopWatch = new Stopwatch(); stopWatch.Start(); dbResult = dbController.StatTurniOeeGetAll(CurrFilter.DateStart, CurrFilter.DateEnd, CurrFilter.IdxMacchina, CurrFilter.IdxOdl, CurrFilter.KeyRichiesta, CurrFilter.CodArticolo); rawData = JsonConvert.SerializeObject(dbResult); redisDataList = Encoding.UTF8.GetBytes(rawData); await distributedCache.SetAsync(cacheKey, redisDataList, cacheOpt); stopWatch.Stop(); TimeSpan ts = stopWatch.Elapsed; _logger.LogTrace($"Effettuata lettura da DB + caching per TurniOee: {ts.TotalMilliseconds} ms"); } return await Task.FromResult(dbResult); } public async Task> StatUserLogGetAll(SelectData CurrFilter, string searchVal = "") { //return Task.FromResult(dbController.StatUserLogGetAll(DataStart, DataEnd, IdxMacchina, IdxODL, KeyRichiesta, CodArticolo).ToArray()); List dbResult = new List(); string cacheKey = getCacheKey("MP:STATS:USRACTLOG", CurrFilter); string rawData; var redisDataList = await distributedCache.GetAsync(cacheKey); if (redisDataList != null) { rawData = Encoding.UTF8.GetString(redisDataList); dbResult = JsonConvert.DeserializeObject>(rawData); } else { Stopwatch stopWatch = new Stopwatch(); stopWatch.Start(); dbResult = dbController.StatUserLogGetAll(CurrFilter.DateStart, CurrFilter.DateEnd, CurrFilter.IdxMacchina, CurrFilter.IdxOdl, CurrFilter.KeyRichiesta, CurrFilter.CodArticolo); // se richiesto filtro azioni effettuo ora selezione... if (CurrFilter.Azione != "*") { dbResult= dbResult.Where(x => x.Azione == CurrFilter.Azione).ToList(); } rawData = JsonConvert.SerializeObject(dbResult); redisDataList = Encoding.UTF8.GetBytes(rawData); await distributedCache.SetAsync(cacheKey, redisDataList, cacheOpt); stopWatch.Stop(); TimeSpan ts = stopWatch.Elapsed; _logger.LogTrace($"Effettuata lettura da DB + caching per UserActionLog: {ts.TotalMilliseconds} ms"); } return await Task.FromResult(dbResult); } #endregion Public Methods } }