using Newtonsoft.Json; using Newtonsoft.Json.Serialization; using NLog; using StackExchange.Redis; using System; using System.Collections.Generic; namespace Step.Database.Redis { public class redUtil { /// /// wrapper di log /// public static Logger lg; private const string baseHash = "SOUR"; public redUtil() { lg = LogManager.GetCurrentClassLogger(); } /// /// Metodo accesso statico /// public static redUtil man = new redUtil(); #region gestione valori in RedisCache /// /// Nome della variabile HASH da utilizzare (dato CodModulo / Server / DB impiegato da funzionalita' DbConfig) + keyName richiesto... /// public string redHash(string keyName) { string answ = keyName; try { answ = string.Format("{0}:{1}", baseHash, keyName); } catch { } return answ; } /// /// Connessione lazy a redis... /// private static Lazy lazyConnection = new Lazy(() => { return ConnectionMultiplexer.Connect("127.0.0.1,abortConnect=false,ssl=false"); }); /// /// Connessione lazy a redis... /// private static Lazy lazyConnectionAdmin = new Lazy(() => { return ConnectionMultiplexer.Connect("127.0.0.1,abortConnect=false,ssl=false,allowAdmin=true"); }); /// /// Oggetto statico connessione redis /// public static ConnectionMultiplexer connRedis { get { return lazyConnection.Value; } } /// /// Oggetto statico connessione redis /// public static ConnectionMultiplexer connRedisAdmin { get { return lazyConnectionAdmin.Value; } } /// /// Restituisce info dei server connessi... /// /// public IServer[] redServInfo() { IServer[] answ = new IServer[1]; if (connRedisAdmin.IsConnected) { try { answ = new IServer[connRedisAdmin.GetEndPoints().Length]; int i = 0; foreach (var ep in connRedisAdmin.GetEndPoints()) { var server = connRedisAdmin.GetServer(ep); answ[i] = server; i++; } } catch (Exception exc) { lg.Error("Eccezione in redServInfo: " + exc.ToString()); } } else { lg.Error("Server REDIS Admin non disponibile"); } return answ; } /// /// Restituisce una chiave salvata in RedisCache /// /// /// public string getRSV(string chiave) { string answ = ""; if (connRedis.IsConnected) { try { IDatabase cache = connRedis.GetDatabase(); answ = cache.StringGet(chiave); } catch (Exception exc) { lg.Info(string.Format("Errore in getRSV:{0}{1}", Environment.NewLine, exc)); } } else { lg.Error("Server REDIS non disponibile per getRSV"); } return answ; } /// /// Salva una chiave in RedisCache /// /// /// /// public bool setRSV(string chiave, string valore) { bool answ = false; if (connRedis.IsConnected) { try { IDatabase cache = connRedis.GetDatabase(); cache.StringSet(chiave, valore); answ = true; } catch (Exception exc) { lg.Info(string.Format("Errore in setRSV:{0}{1}", Environment.NewLine, exc)); } } else { lg.Error("Server REDIS non disponibile (setRSV)"); } return answ; } /// /// Salva una chiave in RedisCache /// /// /// /// in secondi /// public bool setRSV(string chiave, string valore, int TTL_sec) { bool answ = false; if (connRedis.IsConnected) { try { IDatabase cache = connRedis.GetDatabase(); TimeSpan expT = new TimeSpan(0, 0, TTL_sec); // salvo con expyry... cache.StringSet(chiave, valore, expT); answ = true; } catch (Exception exc) { lg.Info(string.Format("Errore in setRSV:{0}{1}", Environment.NewLine, exc)); } } else { lg.Error("Server REDIS non disponibile (setRSV:TTL)"); } return answ; } /// /// Scrive un oggtto json in Redis /// /// /// public bool setJson(string chiave, object valore) { try { string json = JsonConvert.SerializeObject(valore, new JsonSerializerSettings { ContractResolver = new CamelCasePropertyNamesContractResolver() }); return setRSV(chiave, json); } catch { return false; } } /// /// Incrementa un contatore in Redis /// /// /// public long setRCntI(string chiave) { long answ = 0; try { IDatabase cache = connRedis.GetDatabase(); answ = cache.StringIncrement(chiave, 1); } catch (Exception exc) { lg.Info(string.Format("Errore in setRCI:{0}{1}", Environment.NewLine, exc)); } return answ; } /// /// Decrementa un contatore in Redis /// /// /// public long setRCntD(string chiave) { long answ = 0; try { IDatabase cache = connRedis.GetDatabase(); answ = cache.StringDecrement(chiave, 1); } catch (Exception exc) { lg.Info(string.Format("Errore in setRCD:{0}{1}", Environment.NewLine, exc)); } return answ; } /// /// Restituisce una chiave COUNTER in RedisCache /// /// /// public int getRCnt(string chiave) { int answInt = 0; string answ = ""; try { IDatabase cache = connRedis.GetDatabase(); answ = cache.StringGet(chiave); answInt = Convert.ToInt32(answ); } catch (Exception exc) { lg.Info(string.Format("Errore in getRSV:{0}{1}", Environment.NewLine, exc)); } return answInt; } /// /// Resetta (elimina) un contatore in Redis /// /// /// public bool resetRCnt(string chiave) { bool answ = false; try { IDatabase cache = connRedis.GetDatabase(); answ = cache.KeyDelete(chiave); } catch (Exception exc) { lg.Info(string.Format("Errore in resetRCnt:{0}{1}", Environment.NewLine, exc)); } return answ; } /// /// Restituisce un set KVP (Key Value Pair) salvati in RedisCache /// /// /// public RedisValue[] getRKeys(RedisKey[] chiavi) { RedisValue[] answ = null; try { IDatabase cache = connRedis.GetDatabase(); answ = cache.StringGet(chiavi); } catch (Exception exc) { lg.Info(string.Format("Errore in getRKeys:{0}{1}", Environment.NewLine, exc)); } return answ; } /// /// Salva un set KVP (Key Value Pair) in RedisCache /// /// Set KVP chiave-valore da salvare /// public bool setRKeys(KeyValuePair[] valori) { bool answ = false; try { IDatabase cache = connRedis.GetDatabase(); cache.StringSet(valori); answ = true; } catch (Exception exc) { lg.Info(string.Format("Errore in setRKeys:{0}{1}", Environment.NewLine, exc)); } return answ; } /// /// Verifica se ci siano valori nella hash indicata... /// /// /// public bool redHashPresent(RedisKey key) { bool answ = false; // cerco se ci sia valore in redis... IDatabase cache = connRedis.GetDatabase(); try { answ = cache.HashGetAll(key).Length > 0; } catch { } return answ; } /// /// Verifica se ci siano valori nella hash indicata (string) /// /// /// public bool redHashPresentSz(string key) { bool answ = false; try { RedisKey chiave = key; answ = redHashPresent(chiave); } catch { } return answ; } /// /// Recupera tutti i valori dalla hash /// /// /// public KeyValuePair[] redGetHash(string hashKey) { KeyValuePair[] answ = new KeyValuePair[1]; // cerco se ci sia valore in redis... IDatabase cache = connRedis.GetDatabase(); try { RedisKey chiave = hashKey; HashEntry[] valori = cache.HashGetAll(chiave); answ = new KeyValuePair[valori.Length]; int i = 0; foreach (HashEntry item in valori) { answ[i] = new KeyValuePair(item.Name, item.Value); i++; } } catch { } return answ; } /// /// Recupera tutti i valori dalla hash in formato Dictionary /// /// /// public Dictionary redGetHashDict(string hashKey) { Dictionary answ = new Dictionary(); // cerco se ci sia valore in redis... IDatabase cache = connRedis.GetDatabase(); try { RedisKey chiave = hashKey; HashEntry[] valori = cache.HashGetAll(chiave); foreach (HashEntry item in valori) { answ.Add(item.Name, item.Value); } } catch { } return answ; } /// /// Recupera UN SINGOLO VALORE dalla hash per un dato field /// /// /// /// public string redGetHashField(string hashKey, string hashField) { string answ = ""; // cerco se ci sia valore in redis... IDatabase cache = connRedis.GetDatabase(); try { RedisKey chiave = hashKey; RedisValue campo = hashField; RedisValue valOut = cache.HashGet(chiave, campo); answ = valOut.ToString(); } catch { } return answ; } /// /// Salvataggio di una hash di valori /// /// chiave /// valori /// public bool redSaveHash(string hashKey, KeyValuePair[] hashFields) { bool answ = false; if (connRedis.IsConnected) { // cerco se ci sia valore in redis... IDatabase cache = connRedis.GetDatabase(); try { RedisKey chiave = hashKey; HashEntry[] valori = new HashEntry[hashFields.Length]; int i = 0; foreach (KeyValuePair kvp in hashFields) { valori[i] = new HashEntry(kvp.Key, kvp.Value); i++; } cache.HashSet(chiave, valori); answ = true; } catch { } } else { lg.Error("Server REDIS non disponibile (redSaveHash)"); } return answ; } /// /// Salvataggio di una hash di valori /// /// chiave /// valori come lista KVP /// public bool redSaveHashList(string hashKey, List> hashListKVP) { bool answ = false; if (connRedis.IsConnected) { // cerco se ci sia valore in redis... IDatabase cache = connRedis.GetDatabase(); try { RedisKey chiave = hashKey; HashEntry[] valori = new HashEntry[hashListKVP.Count]; int i = 0; foreach (KeyValuePair kvp in hashListKVP) { valori[i] = new HashEntry(kvp.Key, kvp.Value); i++; } cache.HashSet(chiave, valori); answ = true; } catch { } } else { lg.Error("Server REDIS non disponibile (redSaveHashList)"); } return answ; } /// /// Salvataggio di una hash di valori in formato Dictionary /// /// chiave /// valori /// public bool redSaveHashDict(string hashKey, Dictionary hashFields) { bool answ = false; // cerco se ci sia valore in redis... IDatabase cache = connRedis.GetDatabase(); try { RedisKey chiave = hashKey; HashEntry[] valori = new HashEntry[hashFields.Count]; int i = 0; foreach (KeyValuePair kvp in hashFields) { valori[i] = new HashEntry(kvp.Key, kvp.Value); i++; } cache.HashSet(chiave, valori); answ = true; } catch { } return answ; } /// /// Salvataggio di una hash di valori /// /// chiave /// valori /// scadenza preimpostata hash (secondi) | defaoult = -1 (non scade) /// public bool redSaveHash(string hashKey, KeyValuePair[] hashFields, double expireSeconds = -1) { bool answ = false; // cerco se ci sia valore in redis... IDatabase cache = connRedis.GetDatabase(); try { RedisKey chiave = hashKey; answ = redSaveHash(hashKey, hashFields); if (expireSeconds > 0) { cache.KeyExpire(chiave, DateTime.Now.AddSeconds(expireSeconds)); } //answ = true; } catch { } return answ; } /// /// Salvataggio di una hash di valori in formato Dictionary /// /// chiave /// valori /// scadenza preimpostata hash (secondi) | defaoult = -1 (non scade) /// public bool redSaveHashDict(string hashKey, Dictionary hashFields, double expireSeconds = -1) { bool answ = false; // cerco se ci sia valore in redis... IDatabase cache = connRedis.GetDatabase(); try { RedisKey chiave = hashKey; answ = redSaveHashDict(hashKey, hashFields); if (expireSeconds > 0) { cache.KeyExpire(chiave, DateTime.Now.AddSeconds(expireSeconds)); } //answ = true; } catch { } return answ; } /// /// Elimina una key (hash, string) /// /// /// public bool redDelKey(string key) { bool answ = false; // cerco se ci sia valore in redis... IDatabase cache = connRedis.GetDatabase(); try { RedisKey chiave = key; cache.KeyDelete(chiave); answ = true; } catch { } return answ; } /// /// Flush completo cache redis /// /// ** = tutti /// public bool redFlushKey(string keyPattern) { bool answ = false; // cerco se ci sia valore in redis... IDatabase cache = connRedis.GetDatabase(); // se vuoto = ALL... keyPattern = keyPattern == "" ? "**" : keyPattern; try { foreach (var ep in connRedis.GetEndPoints()) { var server = connRedis.GetServer(ep); foreach (var key in server.Keys(pattern: keyPattern)) { cache.KeyDelete(key); } } answ = true; } catch (Exception exc) { lg.Error(string.Format("Eccezione: {0}", exc)); } return answ; } /// /// Conta num oggetti cache redis che rispondono a pattern /// /// ** = tutti /// public int redCountKey(string keyPattern) { int answ = 0; // cerco se ci sia valore in redis... IDatabase cache = connRedis.GetDatabase(); // se vuoto = ALL... keyPattern = keyPattern == "" ? "**" : keyPattern; try { foreach (var ep in connRedis.GetEndPoints()) { var server = connRedis.GetServer(ep); foreach (var key in server.Keys(pattern: keyPattern)) { answ++; } } } catch (Exception exc) { lg.Error(string.Format("Eccezione: {0}", exc)); } return answ; } /// /// Restituisce numero record in Redis DB /// public long numRecRedis { get { long answ = 0; try { foreach (var ep in connRedis.GetEndPoints()) { var server = connRedis.GetServer(ep); answ += server.DatabaseSize(); } } catch { } return answ; } } /// /// Restituisce oggetti cache redis che rispondono a pattern /// /// ** = tutti /// Tipo di ordinamento per kvp /// public List> redGetCounterByKey(string keyPattern, kvpOrderBy orderBy) { int numAnsw = redCountKey(keyPattern); RedisKey[] chiavi = new RedisKey[numAnsw]; List> answ = new List>(); // se vuoto = ALL... keyPattern = keyPattern == "" ? "**" : keyPattern; // recupero in primis elenco chiavi try { int i = 0; foreach (var ep in connRedis.GetEndPoints()) { var server = connRedis.GetServer(ep); foreach (var key in server.Keys(pattern: keyPattern)) { chiavi[i] = key; i++; } } } catch (Exception exc) { lg.Error(string.Format("Eccezione: {0}", exc)); } // ora recupero valori! var valori = getRKeys(chiavi); int currVal = 0; // popolo rispsota try { for (int i = 0; i < numAnsw; i++) { Int32.TryParse(valori[i], out currVal); answ.Add(new KeyValuePair(chiavi[i], currVal)); } } catch { } // se richiesto riordino... switch (orderBy) { case kvpOrderBy.KeyAsc: answ.Sort(CompareKey); break; case kvpOrderBy.KeyDesc: answ.Sort(CompareKeyDesc); break; case kvpOrderBy.ValAsc: answ.Sort(CompareVal); break; case kvpOrderBy.ValDesc: answ.Sort(CompareValDesc); break; default: break; } return answ; } /// /// Effettua comaprazione x CHIAVE in KVP ASC /// /// /// /// private int CompareKey(KeyValuePair x, KeyValuePair y) { return x.Key.CompareTo(y.Key); } /// /// Effettua comaprazione x VALORE in KVP ASC /// /// /// /// public int CompareVal(KeyValuePair x, KeyValuePair y) { return x.Value.CompareTo(y.Value); } /// /// Effettua comaprazione x CHIAVE in KVP DESC /// /// /// /// private int CompareKeyDesc(KeyValuePair x, KeyValuePair y) { return y.Key.CompareTo(x.Key); } /// /// Effettua comaprazione x VALORE in KVP DESC /// /// /// /// public int CompareValDesc(KeyValuePair x, KeyValuePair y) { return y.Value.CompareTo(x.Value); } /// /// Tipologia di ordinamento x liste KVP /// public enum kvpOrderBy { /// /// Ordinamento ASCending per KEY /// KeyAsc, /// /// Ordinamento DESCending per KEY /// KeyDesc, /// /// Ordinamento ASCending per VAL /// ValAsc, /// /// Ordinamento DESCending per VAL /// ValDesc } #endregion } }