using Microsoft.Extensions.Configuration; using MP.Core.Conf; using MP.Data.DbModels; using Newtonsoft.Json; using NLog; using StackExchange.Redis; using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.Data; using System.Diagnostics; using System.IO; using System.Linq; using System.Text; using System.Threading.Tasks; namespace MP.Data.Services { /// /// Classe accesso processi traduzione /// public class TranslateSrv : BaseServ { #region Public Constructors public TranslateSrv(IConfiguration configuration, IConnectionMultiplexer redConn) : base(configuration, redConn) { Stopwatch sw = new Stopwatch(); sw.Start(); // conf DB string connStr = _configuration.GetConnectionString("MP.Voc"); if (string.IsNullOrEmpty(connStr)) { Log.Error("MP.Voc: ConnString empty!"); } else { dbController = new Controllers.MpVocController(configuration); InitDict(); sw.Stop(); Log.Info($"TranslateSrv | MpVocController OK | {sw.Elapsed.TotalMilliseconds} ms"); } } #endregion Public Constructors #region Public Properties public static Controllers.MpVocController dbController { get; set; } = null!; #endregion Public Properties #region Public Methods /// /// Recupero elenco config /// /// public async Task> ConfigGetAll() { string source = "DB"; Stopwatch sw = new Stopwatch(); sw.Start(); List? result = new List(); // cerco in _redisConn... string currKey = $"{redisBaseKey}:Conf"; RedisValue rawData = await _redisDb.StringGetAsync(currKey); //if (!string.IsNullOrEmpty($"{rawData}")) if (rawData.HasValue) { result = JsonConvert.DeserializeObject>($"{rawData}"); source = "REDIS"; } else { result = dbController.ConfigGetAll(); // serializzo e salvo... rawData = JsonConvert.SerializeObject(result); _redisDb.StringSet(currKey, rawData, LongCache); } if (result == null) { result = new List(); } sw.Stop(); Log.Debug($"ConfigGetAll | {source} | {sw.Elapsed.TotalMilliseconds}ms"); return result; } /// /// Pulizia cache Redis (tutta) /// /// public async Task FlushCache() { RedisValue pattern = new RedisValue($"{redisBaseKey}:*"); bool answ = await ExecFlushRedisPattern(pattern); // rileggo vocabolario! var rawData = await VocabolarioGetAll(); DictVocab = rawData.ToDictionary(kvp => $"{kvp.Lingua}_{kvp.Lemma}".ToUpper(), kvp => kvp.Traduzione); return answ; } /// /// Pulizia cache Redis per chiave specifica (da redisBaseKey...) /// /// public async Task FlushCache(string KeyReq) { RedisValue pattern = new RedisValue($"{redisBaseKey}:{KeyReq}:*"); bool answ = await ExecFlushRedisPattern(pattern); return answ; } /// /// Recupero elenco config /// /// public async Task> LingueGetAll() { string source = "DB"; Stopwatch sw = new Stopwatch(); sw.Start(); List? result = new List(); // cerco in _redisConn... string currKey = $"{redisBaseKey}:Lang"; RedisValue rawData = await _redisDb.StringGetAsync(currKey); //if (!string.IsNullOrEmpty($"{rawData}")) if (rawData.HasValue) { result = JsonConvert.DeserializeObject>($"{rawData}"); source = "REDIS"; } else { result = dbController.LingueGetAll(); // serializzo e salvo... rawData = JsonConvert.SerializeObject(result); _redisDb.StringSet(currKey, rawData, UltraLongCache); } if (result == null) { result = new List(); } sw.Stop(); Log.Debug($"LingueGetAll | {source} | {sw.Elapsed.TotalMilliseconds}ms"); return result; } /// /// Traduzione termine /// /// /// /// public string Traduci(string lemma, string lingua = "IT") { string answ = $"[{lemma}.{lingua}]"; string key = $"{lingua}_{lemma}".ToUpper(); if (DictVocab.ContainsKey(key)) { answ = DictVocab[key]; } return answ; } /// /// Recupero elenco config /// /// public async Task> VocabolarioGetAll() { string source = "DB"; Stopwatch sw = new Stopwatch(); sw.Start(); List? result = new List(); // cerco in _redisConn... string currKey = $"{redisBaseKey}:Voc"; RedisValue rawData = await _redisDb.StringGetAsync(currKey); //if (!string.IsNullOrEmpty($"{rawData}")) if (rawData.HasValue) { result = JsonConvert.DeserializeObject>($"{rawData}"); source = "REDIS"; } else { result = dbController.VocabolarioGetAll(); // serializzo e salvo... rawData = JsonConvert.SerializeObject(result); _redisDb.StringSet(currKey, rawData, UltraLongCache); } if (result == null) { result = new List(); } sw.Stop(); Log.Debug($"VocabolarioGetAll | {source} | {sw.Elapsed.TotalMilliseconds}ms"); return result; } #endregion Public Methods #region Protected Fields /// /// Vocabolario x recupero rapido traduzioni /// protected static Dictionary DictVocab = new Dictionary(); #endregion Protected Fields #region Protected Methods protected override void Dispose(bool disposing) { if (!_disposed) { if (disposing) { // Free managed resources here DictVocab.Clear(); dbController.Dispose(); } // Free unmanaged resources here _disposed = true; } // Call base class implementation. base.Dispose(disposing); } #endregion Protected Methods #region Private Fields private static Logger Log = LogManager.GetCurrentClassLogger(); private bool _disposed = false; private string redisBaseKey = "MP:Voc:Cache"; #endregion Private Fields #region Private Methods /// /// Inizializzazione dict vari /// private static void InitDict() { // inizializzo dizionario vocabolario var rawData = dbController.VocabolarioGetAll(); DictVocab = rawData.ToDictionary(kvp => $"{kvp.Lingua}_{kvp.Lemma}".ToUpper(), kvp => kvp.Traduzione); } /// /// Esegue flush memoria _redisConn dato pat2Flush /// /// /// private async Task ExecFlushRedisPattern(RedisValue pat2Flush) { bool answ = false; var masterEndpoint = _redisConn.GetEndPoints() .Where(ep => _redisConn.GetServer(ep).IsConnected && !_redisConn.GetServer(ep).IsReplica) .FirstOrDefault(); // sepattern è "*" elimino intero DB... if (masterEndpoint != null && (pat2Flush.Equals(new RedisValue("*")) || pat2Flush == RedisValue.Null)) { _redisConn.GetServer(masterEndpoint).FlushDatabase(database: _redisDb.Database); } else { var server = _redisConn.GetServer(masterEndpoint); var keys = server.Keys(database: _redisDb.Database, pattern: pat2Flush, pageSize: 1000); var deleteTasks = new List(); foreach (var key in keys) { deleteTasks.Add(_redisDb.KeyDeleteAsync(key)); if (deleteTasks.Count >= 1000) { await Task.WhenAll(deleteTasks); deleteTasks.Clear(); } } if (deleteTasks.Count > 0) { await Task.WhenAll(deleteTasks); } } answ = true; #if false var listEndpoints = redisConn.GetEndPoints(); foreach (var endPoint in listEndpoints) { //var server = redisConnAdmin.GetServer(listEndpoints[0]); var server = redisConn.GetServer(endPoint); if (server != null) { var keyList = server.Keys(redisDb.Database, pattern); foreach (var item in keyList) { await redisDb.KeyDeleteAsync(item); } answ = true; } } #endif return answ; } #endregion Private Methods } }