using Microsoft.Extensions.Caching.Distributed; using Microsoft.Extensions.Caching.Memory; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Logging; using MP.FileData; using Newtonsoft.Json; using NLog; using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Diagnostics; using MP.FileData.Controllers; using MP.FileData.DTO; namespace MP.Prog.Data { public class FileArchDataService : IDisposable { #region Private Fields private static IConfiguration _configuration; private static ILogger _logger; private static List ElencoMacchine = new List(); private static NLog.Logger Log = LogManager.GetCurrentClassLogger(); 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 FileData.Controllers.FileController dbController; #endregion Public Fields #region Public Constructors public FileArchDataService(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.Prog"); if (string.IsNullOrEmpty(connStr)) { _logger.LogError("ConnString empty!"); } else { dbController = new FileData.Controllers.FileController(configuration); StringBuilder sb = new StringBuilder(); sb.AppendLine($"DbController OK"); _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 Internal Methods internal Task FileApprove(FileData.DatabaseModels.FileModel currItem) { return Task.FromResult(dbController.FileModApprove(currItem)); } internal Task FileDelete(FileData.DatabaseModels.FileModel currItem) { return Task.FromResult(dbController.FileDelete(currItem)); } internal Task FileReject(FileData.DatabaseModels.FileModel currItem) { return Task.FromResult(dbController.FileModReject(currItem)); } internal Task FileUpdate(FileData.DatabaseModels.FileModel updItem) { return Task.FromResult(dbController.FileUpdate(updItem)); } internal void ResetController() { dbController.ResetController(); } #endregion Internal Methods #if false protected string getCacheKey(string TableName, SelectData CurrFilter) { string answ = $"{TableName}:M_{CurrFilter.IdxMacchina}:A_{CurrFilter.CodArticolo}:K_{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; } #endif #if false 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; Log.Info($"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> 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); } #endif #region Public Methods public void Dispose() { // Clear database controller dbController.Dispose(); } public async Task FileCountFilt(SelectData CurrFilter) { int numCount = 0; Stopwatch stopWatch = new Stopwatch(); stopWatch.Start(); numCount = dbController.FileCountFilt(CurrFilter.IdxMacchina, CurrFilter.OnlyActive, CurrFilter.OnlyMod, CurrFilter.SearchVal); stopWatch.Stop(); TimeSpan ts = stopWatch.Elapsed; Log.Info($"Effettuata lettura da DB + caching per FileCountFilt: {ts.TotalMilliseconds} ms"); return await Task.FromResult(numCount); } public Task FileGetByKey(int FileId) { return Task.FromResult(dbController.FileGetByKey(FileId)); } public async Task> FileGetFilt(SelectData CurrFilter) { List dbResult = new List(); Stopwatch stopWatch = new Stopwatch(); stopWatch.Start(); dbResult = dbController.FileGetFilt(CurrFilter.IdxMacchina, CurrFilter.OnlyActive, CurrFilter.OnlyMod, CurrFilter.NumSkip, CurrFilter.PageSize, CurrFilter.SearchVal).ToList(); //dbResult = dbController.FileGetFilt(CurrFilter.IdxMacchina, CurrFilter.OnlyActive, CurrFilter.OnlyMod, CurrFilter.FirstRecord, CurrFilter.PageSize * 10, CurrFilter.SearchVal).ToList(); stopWatch.Stop(); TimeSpan ts = stopWatch.Elapsed; Log.Info($"Effettuata lettura da DB + caching per FileGetFilt: {ts.TotalMilliseconds} ms"); return await Task.FromResult(dbResult); } public async Task> GetArchiveStatus() { List dbResult = new List(); Stopwatch stopWatch = new Stopwatch(); stopWatch.Start(); dbResult = dbController.GetArchiveStatus(); stopWatch.Stop(); TimeSpan ts = stopWatch.Elapsed; Log.Info($"Effettuata lettura da DB + caching per GetArchiveStatus: {ts.TotalMilliseconds} ms"); return await Task.FromResult(dbResult); } public Task> MacchineGetAll() { return Task.FromResult(dbController.MacchineGetAll().ToList()); } public async 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 await Task.FromResult(answ); } public void rollBackEdit(object item) { dbController.RollBackEntity(item); } public async Task> TagGetFilt(string SearchVal) { return await Task.FromResult(dbController.TagGetFilt(SearchVal, 200).ToList()); } /// /// Aggiorna intero archivio scansionando dati x tutte le macchine che hanno un path valido /// /// Numero giorni x ricerca all'indietro da data corrente / 0 = nessun limite /// public async Task updateAllArchive(int numDayPre) { int checkDone = 0; Stopwatch stopWatch = new Stopwatch(); stopWatch.Start(); string ruleName = "Rule01.json"; try { var listaMacchine = await MacchineGetAll(); foreach (var item in listaMacchine.Where(x => !string.IsNullOrEmpty(x.BasePath)).ToList()) { if (!string.IsNullOrEmpty(item.RuleName)) { ruleName = item.RuleName; // gestione confRule... SearchRules currRule = new SearchRules(); try { string rawData = File.ReadAllText(FileController.rulePath(ruleName)); currRule = JsonConvert.DeserializeObject(rawData); //Log.Info($"Conf rule acquisito da file {ruleName}:{Environment.NewLine}{rawData}"); } catch (Exception exc) { Log.Error($"Eccezione in deserializzazione conf rule{Environment.NewLine}{exc}"); } // se NON deserializzato inizializzo hard-coded if (currRule.Name == "ND") { // fare: lettura conf rule x recupero tag x singola macchina //$"\\b{fileName}" + @".{0,2}\([\w\d\s.]+\)"; Dictionary confReplace = new Dictionary(); confReplace.Add("(", " "); confReplace.Add(")", " "); Dictionary fileExtReplace = new Dictionary(); fileExtReplace.Add(".P-2", ""); // hard coded + salvataggio conf x creare json currRule = new SearchRules() { Name = "Commento Filename", Mode = SearchMode.StringOnFile, MaxChar2Search = 100, ReplaceCR = true, RegExPattern = "\\b{{fileName}}" + @".{0,2}\([\w\d\s./]+\)", RegExRepFileName = true, FileNameExtReplace = fileExtReplace, ExcludedTags = new List() { "M4", "M5", "M4+A", "M4+B", "M5+A", "M5+B" }, OutReplace = confReplace, OutExcludeFileName = true }; // serializzo string rawRule = JsonConvert.SerializeObject(currRule, Formatting.Indented); Log.Info($"Conf rule generato:{Environment.NewLine}{rawRule}"); } checkDone += dbController.CheckFileArchived(item.IdxMacchina, item.BasePath, numDayPre, "*.*", currRule); } } } catch (Exception exc) { Log.Error($"Eccezione in updateAllArchive{Environment.NewLine}{exc}{Environment.NewLine}{exc.InnerException}"); } stopWatch.Stop(); TimeSpan ts = stopWatch.Elapsed; Log.Info($"Effettuato update archivio file | last {numDayPre} days | {checkDone} checked | {ts.TotalMilliseconds} ms"); return await Task.FromResult(checkDone); } #endregion Public Methods #if false 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; Log.Info($"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; Log.Info($"Effettuata lettura da DB + caching per DdbTurni: {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; Log.Info($"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; Log.Info($"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; Log.Info($"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; Log.Info($"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); rawData = JsonConvert.SerializeObject(dbResult); redisDataList = Encoding.UTF8.GetBytes(rawData); await distributedCache.SetAsync(cacheKey, redisDataList, cacheOpt); stopWatch.Stop(); TimeSpan ts = stopWatch.Elapsed; Log.Info($"Effettuata lettura da DB + caching per UserActionLog: {ts.TotalMilliseconds} ms"); } return await Task.FromResult(dbResult); } #endif } }