1198 lines
36 KiB
C#
1198 lines
36 KiB
C#
using Newtonsoft.Json;
|
|
using NLog;
|
|
using StackExchange.Redis;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Net.NetworkInformation;
|
|
using System.Text;
|
|
using System.Threading.Tasks;
|
|
|
|
namespace IobManComm
|
|
{
|
|
public class RedisWatchDog
|
|
{
|
|
#region Public Constructors
|
|
|
|
/// <summary>
|
|
/// Classe logger
|
|
/// </summary>
|
|
public static Logger lg = LogManager.GetCurrentClassLogger();
|
|
|
|
#if false
|
|
/// <summary>
|
|
/// init classe "implicita"
|
|
/// </summary>
|
|
/// <param name="codServer"></param>
|
|
/// <param name="codIob"></param>
|
|
public RedisWatchDog()
|
|
{
|
|
initHashKeys();
|
|
}
|
|
#endif
|
|
|
|
/// <summary>
|
|
/// Init classe gestione dati WatchDog su Redis
|
|
/// CABLATO su localhost!!!!
|
|
/// </summary>
|
|
/// <param name="CodIob">Cod istanza = nome file ini (es nome macchina: SERIAL_PUMA25)</param>
|
|
/// <param name="appName">Nome applicazione</param>
|
|
/// <param name="tipoIob">Tipo di IOB</param>
|
|
/// <param name="redisDb">DB redis da usare x scambio info</param>
|
|
/// <param name="minDeltaS">Minima differenza in secondi x considerare variazione dati DataOra</param>
|
|
public RedisWatchDog(string CodIob, string tipoIob, string appName, int redisDb, int minDeltaS)
|
|
{
|
|
// init dati di base...
|
|
AppName = appName;
|
|
currCodIob = CodIob;
|
|
currIobType = tipoIob;
|
|
RedisDb = redisDb;
|
|
initHashKeys();
|
|
// init oggetti gestiti: IOB
|
|
IobWinStatus newIobStatus = new IobWinStatus()
|
|
{
|
|
CodIob = currCodIob,
|
|
IobType = currIobType,
|
|
online = false,
|
|
minDeltaSec = minDeltaS
|
|
};
|
|
// salvo in area REDIS
|
|
iobStatus = newIobStatus;
|
|
}
|
|
|
|
#endregion Public Constructors
|
|
|
|
#region Public Enums
|
|
|
|
/// <summary>
|
|
/// Tipologia di ordinamento x liste KVP
|
|
/// </summary>
|
|
public enum kvpOrderBy
|
|
{
|
|
/// <summary>
|
|
/// Ordinamento ASCending per KEY
|
|
/// </summary>
|
|
KeyAsc,
|
|
|
|
/// <summary>
|
|
/// Ordinamento DESCending per KEY
|
|
/// </summary>
|
|
KeyDesc,
|
|
|
|
/// <summary>
|
|
/// Ordinamento ASCending per VAL
|
|
/// </summary>
|
|
ValAsc,
|
|
|
|
/// <summary>
|
|
/// Ordinamento DESCending per VAL
|
|
/// </summary>
|
|
ValDesc
|
|
}
|
|
|
|
#endregion Public Enums
|
|
|
|
#region Public Properties
|
|
|
|
/// <summary>
|
|
/// Oggetto DB REDIS corrente
|
|
/// </summary>
|
|
public IDatabase cache //currDB
|
|
{
|
|
get
|
|
{
|
|
IDatabase answ;
|
|
// se già valorizzato uso oggetto private...
|
|
if (_currDB != null)
|
|
{
|
|
answ = _currDB;
|
|
}
|
|
else
|
|
{
|
|
// init DB (sullo 0)
|
|
answ = connRedis.GetDatabase();
|
|
// gestione override...
|
|
if (RedisDb >= 0)
|
|
{
|
|
// in questo caso uso il DB configurato in app.config...
|
|
answ = connRedis.GetDatabase(RedisDb);
|
|
}
|
|
_currDB = answ;
|
|
}
|
|
// restituisco oggetto DB
|
|
return answ;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Oggetto statico connessione redis
|
|
/// </summary>
|
|
public ConnectionMultiplexer connRedis
|
|
{
|
|
get
|
|
{
|
|
return lazyConnection.Value;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Oggetto statico connessione redis
|
|
/// </summary>
|
|
public ConnectionMultiplexer connRedisAdmin
|
|
{
|
|
get
|
|
{
|
|
return lazyConnectionAdmin.Value;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Accesso all'oggetto stato IOB da esterno
|
|
/// </summary>
|
|
public IobWinStatus iobStatus
|
|
{
|
|
get
|
|
{
|
|
IobWinStatus answ = null;
|
|
// cerco in REDIS
|
|
string rawData = getRSV(redIobKey);
|
|
// se non ci fosse creo e salvo
|
|
if (string.IsNullOrEmpty(rawData))
|
|
{
|
|
answ = new IobWinStatus()
|
|
{
|
|
CodIob = currCodIob,
|
|
IobType = currIobType,
|
|
online = false,
|
|
freeNotes = "loading"
|
|
};
|
|
// salvo serializzando...
|
|
rawData = JsonConvert.SerializeObject(answ);
|
|
setRSV(redIobKey, rawData);
|
|
}
|
|
else
|
|
{
|
|
// deserializzo
|
|
answ = JsonConvert.DeserializeObject<IobWinStatus>(rawData);
|
|
}
|
|
return answ;
|
|
}
|
|
set
|
|
{
|
|
string rawData = JsonConvert.SerializeObject(value);
|
|
saveAndSendMessage(redIobKey, redIobChannel, rawData);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// MEssage Dispatcher: oggetto comunicazione pub/sub via REDIS channels corrente
|
|
/// </summary>
|
|
public ISubscriber messageDisp
|
|
{
|
|
get
|
|
{
|
|
ISubscriber answ;
|
|
// se già valorizzato uso oggetto private...
|
|
if (_currSub != null)
|
|
{
|
|
answ = _currSub;
|
|
}
|
|
else
|
|
{
|
|
// init DB (sullo 0)
|
|
answ = connRedis.GetSubscriber();
|
|
_currSub = answ;
|
|
}
|
|
// restituisco oggetto DB
|
|
return answ;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Restituisce numero record in Redis DB
|
|
/// </summary>
|
|
public long numRecRedis
|
|
{
|
|
get
|
|
{
|
|
long answ = 0;
|
|
try
|
|
{
|
|
foreach (var ep in connRedis.GetEndPoints())
|
|
{
|
|
var server = connRedis.GetServer(ep);
|
|
answ += server.DatabaseSize();
|
|
}
|
|
}
|
|
catch (Exception exc)
|
|
{
|
|
lg.Error($"numRecRedis {exc}");
|
|
}
|
|
return answ;
|
|
}
|
|
}
|
|
|
|
#endregion Public Properties
|
|
|
|
#region Public Methods
|
|
|
|
/// <summary>
|
|
/// Effettua comaprazione x VALORE in KVP ASC
|
|
/// </summary>
|
|
/// <param name="x"></param>
|
|
/// <param name="y"></param>
|
|
/// <returns></returns>
|
|
public int CompareVal(KeyValuePair<string, int> x, KeyValuePair<string, int> y)
|
|
{
|
|
return x.Value.CompareTo(y.Value);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Effettua comaprazione x VALORE in KVP DESC
|
|
/// </summary>
|
|
/// <param name="x"></param>
|
|
/// <param name="y"></param>
|
|
/// <returns></returns>
|
|
public int CompareValDesc(KeyValuePair<string, int> x, KeyValuePair<string, int> y)
|
|
{
|
|
return y.Value.CompareTo(x.Value);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Deserializzazione di un valore string in oggetto generico
|
|
/// </summary>
|
|
/// <param name="serVal"></param>
|
|
/// <returns></returns>
|
|
public object deserializeVal(string serVal)
|
|
{
|
|
object answ = "";
|
|
try
|
|
{
|
|
answ = JsonConvert.DeserializeObject(serVal);
|
|
}
|
|
catch (Exception exc)
|
|
{
|
|
lg.Error($"deserializeVal {exc}");
|
|
}
|
|
return answ;
|
|
}
|
|
|
|
public int getKReqCount(string keyReq)
|
|
{
|
|
string keyReqHash = redHash($"IOB:{currCodIob}:KRCOUNT:{keyReq}");
|
|
int answ = 0;
|
|
string rawData = getRSV(keyReqHash);
|
|
if (!string.IsNullOrEmpty(rawData))
|
|
{
|
|
int.TryParse(rawData, out answ);
|
|
}
|
|
return answ;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Restituisce una chiave COUNTER in RedisCache
|
|
/// </summary>
|
|
/// <param name="chiave"></param>
|
|
/// <returns></returns>
|
|
public int getRCnt(string chiave)
|
|
{
|
|
int answInt = 0;
|
|
string answ = "";
|
|
try
|
|
{
|
|
answ = cache.StringGet(chiave);
|
|
answInt = Convert.ToInt32(answ);
|
|
}
|
|
catch (Exception exc)
|
|
{
|
|
lg.Error($"getRCnt {exc}");
|
|
}
|
|
return answInt;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Restituisce un pò di info sul server redis connesso
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
public string getRedisInfoData()
|
|
{
|
|
string answ = "";
|
|
StringBuilder sb = new StringBuilder();
|
|
try
|
|
{
|
|
sb.AppendLine($"Configuration: {connRedis.Configuration}");
|
|
sb.AppendLine($"Connected: {connRedis.IsConnected}");
|
|
sb.AppendLine($"ClientName: {connRedis.ClientName}");
|
|
sb.AppendLine($"Total Ops: {connRedis.OperationCount}");
|
|
sb.AppendLine($"Status: {connRedis.GetStatus()}");
|
|
answ = sb.ToString();
|
|
}
|
|
catch (Exception exc)
|
|
{
|
|
lg.Error($"getRedisInfoData {exc}");
|
|
}
|
|
return answ;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Restituisce un set KVP (Key Value Pair) salvati in RedisCache
|
|
/// </summary>
|
|
/// <param name="chiavi"></param>
|
|
/// <returns></returns>
|
|
public RedisValue[] getRKeys(RedisKey[] chiavi)
|
|
{
|
|
RedisValue[] answ = null;
|
|
try
|
|
{
|
|
answ = cache.StringGet(chiavi);
|
|
}
|
|
catch (Exception exc)
|
|
{
|
|
lg.Error($"getRKeys {exc}");
|
|
}
|
|
return answ;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Restituisce una chiave salvata in RedisCache
|
|
/// </summary>
|
|
/// <param name="chiave"></param>
|
|
/// <returns></returns>
|
|
public string getRSV(string chiave)
|
|
{
|
|
string answ = "";
|
|
try
|
|
{
|
|
answ = cache.StringGet(chiave);
|
|
}
|
|
catch (Exception exc)
|
|
{
|
|
lg.Info($"getRSV {exc}");
|
|
}
|
|
return answ;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Conta num oggetti cache redis che rispondono a pattern
|
|
/// </summary>
|
|
/// <param name="keyPattern">** = tutti</param>
|
|
/// <returns></returns>
|
|
public int redCountKey(string keyPattern)
|
|
{
|
|
int answ = 0;
|
|
// cerco se ci sia valore in redis... se vuoto = ALL...
|
|
keyPattern = string.IsNullOrEmpty(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($"redCountKey {exc}");
|
|
}
|
|
return answ;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Elimina una key (hash, string)
|
|
/// </summary>
|
|
/// <param name="key"></param>
|
|
/// <returns></returns>
|
|
public bool redDelKey(string key)
|
|
{
|
|
bool answ = false;
|
|
// cerco se ci sia valore in redis...
|
|
try
|
|
{
|
|
RedisKey chiave = key;
|
|
cache.KeyDelete(chiave);
|
|
answ = true;
|
|
}
|
|
catch (Exception exc)
|
|
{
|
|
lg.Error($"redDelKey {exc}");
|
|
}
|
|
return answ;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Flush completo cache redis
|
|
/// </summary>
|
|
/// <param name="keyPattern">** = tutti</param>
|
|
/// <returns></returns>
|
|
public bool redFlushKey(string keyPattern)
|
|
{
|
|
bool answ = false;
|
|
// cerco se ci sia valore in redis... se vuoto = ALL...
|
|
keyPattern = string.IsNullOrEmpty(keyPattern) ? "**" : keyPattern;
|
|
try
|
|
{
|
|
foreach (var ep in connRedis.GetEndPoints())
|
|
{
|
|
var server = connRedis.GetServer(ep);
|
|
var keys = server.Keys(database: RedisDb, pattern: $"{keyPattern}*");
|
|
foreach (var key in keys)
|
|
{
|
|
cache.KeyDelete(key);
|
|
}
|
|
}
|
|
answ = true;
|
|
}
|
|
catch (Exception exc)
|
|
{
|
|
lg.Error($"redFlushKey {exc}");
|
|
}
|
|
return answ;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Restituisce oggetti cache redis che rispondono a pattern
|
|
/// </summary>
|
|
/// <param name="keyPattern">** = tutti</param>
|
|
/// <param name="orderBy">Tipo di ordinamento per kvp</param>
|
|
/// <returns></returns>
|
|
public List<KeyValuePair<string, int>> redGetCounterByKey(string keyPattern, kvpOrderBy orderBy)
|
|
{
|
|
int numAnsw = redCountKey(keyPattern);
|
|
RedisKey[] chiavi = new RedisKey[numAnsw];
|
|
List<KeyValuePair<string, int>> answ = new List<KeyValuePair<string, int>>();
|
|
// se vuoto = ALL...
|
|
keyPattern = string.IsNullOrEmpty(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($"redGetCounterByKey 01 {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<string, int>(chiavi[i], currVal));
|
|
}
|
|
}
|
|
catch (Exception exc)
|
|
{
|
|
lg.Error($"redGetCounterByKey 02 {exc}");
|
|
}
|
|
// 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;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Recupera tutti i valori dalla hash
|
|
/// </summary>
|
|
/// <param name="hashKey"></param>
|
|
/// <returns></returns>
|
|
public KeyValuePair<string, string>[] redGetHash(string hashKey)
|
|
{
|
|
KeyValuePair<string, string>[] answ = new KeyValuePair<string, string>[1];
|
|
// cerco se ci sia valore in redis...
|
|
try
|
|
{
|
|
RedisKey chiave = hashKey;
|
|
HashEntry[] valori = cache.HashGetAll(chiave);
|
|
answ = new KeyValuePair<string, string>[valori.Length];
|
|
int i = 0;
|
|
foreach (HashEntry item in valori)
|
|
{
|
|
answ[i] = new KeyValuePair<string, string>(item.Name, item.Value);
|
|
i++;
|
|
}
|
|
}
|
|
catch (Exception exc)
|
|
{
|
|
lg.Error($"redGetHash {exc}");
|
|
}
|
|
return answ;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Recupera tutti i valori dalla hash in formato Dictionary
|
|
/// </summary>
|
|
/// <param name="hashKey"></param>
|
|
/// <returns></returns>
|
|
public Dictionary<string, string> redGetHashDict(string hashKey)
|
|
{
|
|
Dictionary<string, string> answ = new Dictionary<string, string>();
|
|
// cerco se ci sia valore in redis...
|
|
try
|
|
{
|
|
RedisKey chiave = hashKey;
|
|
HashEntry[] valori = cache.HashGetAll(chiave);
|
|
foreach (HashEntry item in valori)
|
|
{
|
|
answ.Add(item.Name, item.Value);
|
|
}
|
|
}
|
|
catch (Exception exc)
|
|
{
|
|
lg.Error($"redGetHashDict {exc}");
|
|
}
|
|
return answ;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Recupera UN SINGOLO VALORE dalla hash per un dato field
|
|
/// </summary>
|
|
/// <param name="hashKey"></param>
|
|
/// <param name="hashField"></param>
|
|
/// <returns></returns>
|
|
public string redGetHashField(string hashKey, string hashField)
|
|
{
|
|
string answ = "";
|
|
// cerco se ci sia valore in redis...
|
|
try
|
|
{
|
|
RedisKey chiave = hashKey;
|
|
RedisValue campo = hashField;
|
|
RedisValue valOut = cache.HashGet(chiave, campo);
|
|
answ = valOut.ToString();
|
|
}
|
|
catch (Exception exc)
|
|
{
|
|
lg.Error($"redGetHashField {exc}");
|
|
}
|
|
return answ;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Nome della variabile HASH da utilizzare (dato CodModulo / Server / DB impiegato da
|
|
/// funzionalita' DbConfig) + keyName richiesto...
|
|
/// </summary>
|
|
public string redHash(string keyName)
|
|
{
|
|
keyName = keyName.Replace("\\", "_");
|
|
string answ = keyName;
|
|
try
|
|
{
|
|
answ = string.Format($"{AppName}:{keyName}");
|
|
}
|
|
catch (Exception exc)
|
|
{
|
|
lg.Error($"redHash {exc}");
|
|
}
|
|
return answ;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Verifica se ci siano valori nella hash indicata...
|
|
/// </summary>
|
|
/// <param name="key"></param>
|
|
/// <returns></returns>
|
|
public bool redHashPresent(RedisKey key)
|
|
{
|
|
bool answ = false;
|
|
// cerco se ci sia valore in redis...
|
|
try
|
|
{
|
|
answ = cache.HashGetAll(key).Length > 0;
|
|
}
|
|
catch (Exception exc)
|
|
{
|
|
lg.Error($"redHashPresent {exc}");
|
|
}
|
|
return answ;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Verifica se ci siano valori nella hash indicata (string)
|
|
/// </summary>
|
|
/// <param name="key"></param>
|
|
/// <returns></returns>
|
|
public bool redHashPresentSz(string key)
|
|
{
|
|
bool answ = false;
|
|
try
|
|
{
|
|
RedisKey chiave = key;
|
|
answ = redHashPresent(chiave);
|
|
}
|
|
catch (Exception exc)
|
|
{
|
|
lg.Error($"redHashPresentSz {exc}");
|
|
}
|
|
return answ;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Verifica se ci siano valori nella KEY indicata...
|
|
/// </summary>
|
|
/// <param name="key"></param>
|
|
/// <returns></returns>
|
|
public bool redKeyPresent(RedisKey key)
|
|
{
|
|
bool answ = false;
|
|
// cerco se ci sia valore in redis...
|
|
try
|
|
{
|
|
answ = cache.KeyExists(key);
|
|
}
|
|
catch (Exception exc)
|
|
{
|
|
lg.Error($"redKeyPresent {exc}");
|
|
}
|
|
return answ;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Verifica se ci siano valori nella KEY indicata (string)
|
|
/// </summary>
|
|
/// <param name="key"></param>
|
|
/// <returns></returns>
|
|
public bool redKeyPresentSz(string key)
|
|
{
|
|
bool answ = false;
|
|
try
|
|
{
|
|
RedisKey chiave = key;
|
|
answ = redKeyPresent(chiave);
|
|
}
|
|
catch (Exception exc)
|
|
{
|
|
lg.Error($"redKeyPresentSz {exc}");
|
|
}
|
|
return answ;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Salvataggio di una hash di valori
|
|
/// </summary>
|
|
/// <param name="hashKey">chiave</param>
|
|
/// <param name="hashFields">valori</param>
|
|
/// <returns></returns>
|
|
public bool redSaveHash(string hashKey, KeyValuePair<string, string>[] hashFields)
|
|
{
|
|
bool answ = false;
|
|
// cerco se ci sia valore in redis...
|
|
try
|
|
{
|
|
RedisKey chiave = hashKey;
|
|
HashEntry[] valori = new HashEntry[hashFields.Length];
|
|
int i = 0;
|
|
foreach (KeyValuePair<string, string> kvp in hashFields)
|
|
{
|
|
valori[i] = new HashEntry(kvp.Key, kvp.Value);
|
|
i++;
|
|
}
|
|
cache.HashSet(chiave, valori);
|
|
answ = true;
|
|
}
|
|
catch (Exception exc)
|
|
{
|
|
lg.Error($"redSaveHash {exc}");
|
|
}
|
|
return answ;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Salvataggio di una hash di valori
|
|
/// </summary>
|
|
/// <param name="hashKey">chiave</param>
|
|
/// <param name="hashFields">valori</param>
|
|
/// <param name="expireSeconds">
|
|
/// scadenza preimpostata hash (secondi) | defaoult = -1 (non scade)
|
|
/// </param>
|
|
/// <returns></returns>
|
|
public bool redSaveHash(string hashKey, KeyValuePair<string, string>[] hashFields, double expireSeconds = -1)
|
|
{
|
|
bool answ = false;
|
|
// cerco se ci sia valore in redis...
|
|
try
|
|
{
|
|
RedisKey chiave = hashKey;
|
|
answ = redSaveHash(hashKey, hashFields);
|
|
if (expireSeconds > 0)
|
|
{
|
|
cache.KeyExpire(chiave, DateTime.Now.AddSeconds(expireSeconds));
|
|
}
|
|
}
|
|
catch (Exception exc)
|
|
{
|
|
lg.Error($"redSaveHash {exc}");
|
|
}
|
|
return answ;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Salvataggio di una hash di valori in formato Dictionary
|
|
/// </summary>
|
|
/// <param name="hashKey">chiave</param>
|
|
/// <param name="hashFields">valori</param>
|
|
/// <returns></returns>
|
|
public bool redSaveHashDict(string hashKey, Dictionary<string, string> hashFields)
|
|
{
|
|
bool answ = false;
|
|
// cerco se ci sia valore in redis...
|
|
try
|
|
{
|
|
RedisKey chiave = hashKey;
|
|
HashEntry[] valori = new HashEntry[hashFields.Count];
|
|
int i = 0;
|
|
foreach (KeyValuePair<string, string> kvp in hashFields)
|
|
{
|
|
valori[i] = new HashEntry(kvp.Key, kvp.Value);
|
|
i++;
|
|
}
|
|
cache.HashSet(chiave, valori);
|
|
answ = true;
|
|
}
|
|
catch (Exception exc)
|
|
{
|
|
lg.Error($"redSaveHashDict {exc}");
|
|
}
|
|
return answ;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Salvataggio di una hash di valori in formato Dictionary
|
|
/// </summary>
|
|
/// <param name="hashKey">chiave</param>
|
|
/// <param name="hashFields">valori</param>
|
|
/// <param name="expireSeconds">
|
|
/// scadenza preimpostata hash (secondi) | defaoult = -1 (non scade)
|
|
/// </param>
|
|
/// <returns></returns>
|
|
public bool redSaveHashDict(string hashKey, Dictionary<string, string> hashFields, double expireSeconds = -1)
|
|
{
|
|
bool answ = false;
|
|
// cerco se ci sia valore in redis...
|
|
try
|
|
{
|
|
RedisKey chiave = hashKey;
|
|
answ = redSaveHashDict(hashKey, hashFields);
|
|
if (expireSeconds > 0)
|
|
{
|
|
cache.KeyExpire(chiave, DateTime.Now.AddSeconds(expireSeconds));
|
|
}
|
|
//answ = true;
|
|
}
|
|
catch (Exception exc)
|
|
{
|
|
lg.Error($"redSaveHashDict {exc}");
|
|
}
|
|
return answ;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Salvataggio di una hash di valori
|
|
/// </summary>
|
|
/// <param name="hashKey">chiave</param>
|
|
/// <param name="hashListKVP">valori come lista KVP</param>
|
|
/// <returns></returns>
|
|
public bool redSaveHashList(string hashKey, List<KeyValuePair<string, string>> 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<string, string> kvp in hashListKVP)
|
|
{
|
|
valori[i] = new HashEntry(kvp.Key, kvp.Value);
|
|
i++;
|
|
}
|
|
cache.HashSet(chiave, valori);
|
|
answ = true;
|
|
}
|
|
catch (Exception exc)
|
|
{
|
|
lg.Error($"redSaveHashList {exc}");
|
|
}
|
|
}
|
|
return answ;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Restituisce info dei server connessi...
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
public IServer[] redServInfo()
|
|
{
|
|
IServer[] answ = new IServer[1];
|
|
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($"redServInfo {exc}");
|
|
}
|
|
return answ;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Resetta (elimina) un contatore in Redis
|
|
/// </summary>
|
|
/// <param name="chiave"></param>
|
|
/// <returns></returns>
|
|
public bool resetRCnt(string chiave)
|
|
{
|
|
bool answ = false;
|
|
try
|
|
{
|
|
answ = cache.KeyDelete(chiave);
|
|
}
|
|
catch (Exception exc)
|
|
{
|
|
lg.Error($"resetRCnt {exc}");
|
|
}
|
|
return answ;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Invia un messaggio tramite notify channel + salva in cache (se scaduto periodo veto)
|
|
/// </summary>
|
|
/// <param name="memKey"></param>
|
|
/// <param name="notifyChannel"></param>
|
|
/// <param name="message"></param>
|
|
/// <returns></returns>
|
|
public bool saveAndSendMessage(string memKey, string notifyChannel, string message)
|
|
{
|
|
bool fatto = false;
|
|
// effettuo la scrittura nell'area di memoria indicata SE passato intervallo minimo
|
|
bool doSave = true;
|
|
if (LastKeySave.ContainsKey(memKey))
|
|
{
|
|
if (DateTime.Now.Subtract(LastKeySave[memKey]).TotalSeconds < 1)
|
|
{
|
|
doSave = false;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
LastKeySave.Add(memKey, DateTime.Now);
|
|
}
|
|
if (doSave)
|
|
{
|
|
cache.StringSet(memKey, message);
|
|
LastKeySave[memKey] = DateTime.Now;
|
|
lg.Trace($"Redis Cache Key: {memKey}");
|
|
}
|
|
|
|
// invio notifica tramite il canale richiesto
|
|
messageDisp.Publish(notifyChannel, message);
|
|
fatto = true;
|
|
// restituisco!
|
|
return fatto;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Serializzazione di un oggetto generico
|
|
/// </summary>
|
|
/// <param name="origVal"></param>
|
|
/// <returns></returns>
|
|
public string serializeVal(object origVal)
|
|
{
|
|
string answ = "";
|
|
try
|
|
{
|
|
answ = JsonConvert.SerializeObject(origVal);
|
|
}
|
|
catch (Exception exc)
|
|
{
|
|
lg.Error($"serializeVal {exc}");
|
|
}
|
|
return answ;
|
|
}
|
|
|
|
public bool setKReqCount(string keyReq, int val)
|
|
{
|
|
string keyReqHash = redHash($"IOB:{currCodIob}:KRCOUNT:{keyReq}");
|
|
// salvo ogni chiave x 25 h (in sec 60*60*25)
|
|
bool done = setRSV(keyReqHash, $"{val}", 60 * 60 * 25);
|
|
return done;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Decrementa un contatore in Redis
|
|
/// </summary>
|
|
/// <param name="chiave"></param>
|
|
/// <returns></returns>
|
|
public long setRCntD(string chiave)
|
|
{
|
|
long answ = 0;
|
|
try
|
|
{
|
|
answ = cache.StringDecrement(chiave, 1);
|
|
}
|
|
catch (Exception exc)
|
|
{
|
|
lg.Error($"setRCntD {exc}");
|
|
}
|
|
return answ;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Incrementa un contatore in Redis
|
|
/// </summary>
|
|
/// <param name="chiave"></param>
|
|
/// <returns></returns>
|
|
public long setRCntI(string chiave)
|
|
{
|
|
long answ = 0;
|
|
try
|
|
{
|
|
answ = cache.StringIncrement(chiave, 1);
|
|
}
|
|
catch (Exception exc)
|
|
{
|
|
lg.Error($"setRCntI {exc}");
|
|
}
|
|
return answ;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Salva un set KVP (Key Value Pair) in RedisCache
|
|
/// </summary>
|
|
/// <param name="valori">Set KVP chiave-valore da salvare</param>
|
|
/// <returns></returns>
|
|
public bool setRKeys(KeyValuePair<RedisKey, RedisValue>[] valori)
|
|
{
|
|
bool answ = false;
|
|
try
|
|
{
|
|
cache.StringSet(valori);
|
|
answ = true;
|
|
}
|
|
catch (Exception exc)
|
|
{
|
|
lg.Error($"setRKeys {exc}");
|
|
}
|
|
return answ;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Salva una chiave in RedisCache
|
|
/// </summary>
|
|
/// <param name="chiave"></param>
|
|
/// <param name="valore"></param>
|
|
/// <returns></returns>
|
|
public bool setRSV(string chiave, string valore)
|
|
{
|
|
bool answ = false;
|
|
try
|
|
{
|
|
cache.StringSet(chiave, valore);
|
|
answ = true;
|
|
}
|
|
catch (Exception exc)
|
|
{
|
|
lg.Error($"setRSV {exc}");
|
|
}
|
|
return answ;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Salva una chiave in RedisCache
|
|
/// </summary>
|
|
/// <param name="chiave"></param>
|
|
/// <param name="valore"></param>
|
|
/// <param name="TTL_sec">in secondi</param>
|
|
/// <returns></returns>
|
|
public bool setRSV(string chiave, string valore, int TTL_sec)
|
|
{
|
|
bool answ = false;
|
|
try
|
|
{
|
|
TimeSpan expT = new TimeSpan(0, 0, TTL_sec);
|
|
// salvo con expyry...
|
|
cache.StringSet(chiave, valore, expT);
|
|
answ = true;
|
|
}
|
|
catch (Exception exc)
|
|
{
|
|
lg.Error($"setRSV {exc}");
|
|
}
|
|
return answ;
|
|
}
|
|
|
|
#endregion Public Methods
|
|
|
|
#region Protected Fields
|
|
|
|
/// <summary>
|
|
/// DB Redis di default
|
|
/// </summary>
|
|
protected int RedisDb = 0;
|
|
|
|
/// <summary>
|
|
/// Stringa connessione redis (base)
|
|
/// </summary>
|
|
protected static string RedisConn { get; set; } = "";
|
|
/// <summary>
|
|
/// Stringa connessione redis (admin)
|
|
/// </summary>
|
|
protected static string RedisConnAdmin { get; set; } = "";
|
|
|
|
/// <summary>
|
|
/// Nome APP x scambio dati
|
|
/// </summary>
|
|
protected string AppName = "SERIAL";
|
|
/// <summary>
|
|
/// Cod IOB
|
|
/// </summary>
|
|
protected string currCodIob = "000";
|
|
|
|
/// <summary>
|
|
/// Tipo IOB
|
|
/// </summary>
|
|
protected string currIobType = "ND";
|
|
|
|
/// <summary>
|
|
/// Nome del channel REDIS x dati IOB
|
|
/// </summary>
|
|
protected string redIobChannel = "IobChannel";
|
|
|
|
/// <summary>
|
|
/// Hash REDIS x dati IOB
|
|
/// </summary>
|
|
protected string redIobKey = "";
|
|
|
|
/// <summary>
|
|
/// Hash REDIS x dati server
|
|
/// </summary>
|
|
protected string redServKey = "";
|
|
|
|
#endregion Protected Fields
|
|
|
|
#region Private Fields
|
|
|
|
/// <summary>
|
|
/// Dizionario delle ultime scritture in cache redis dei messaggi
|
|
/// </summary>
|
|
private Dictionary<string, DateTime> LastKeySave = new Dictionary<string, DateTime>();
|
|
|
|
/// <summary>
|
|
/// Connessione lazy a redis...
|
|
/// </summary>
|
|
private Lazy<ConnectionMultiplexer> lazyConnection = new Lazy<ConnectionMultiplexer>(() =>
|
|
{
|
|
if (string.IsNullOrEmpty(RedisConn))
|
|
{
|
|
RedisConn = "localhost,abortConnect=false,ssl=false";
|
|
}
|
|
return ConnectionMultiplexer.Connect(RedisConn);
|
|
});
|
|
|
|
/// <summary>
|
|
/// Connessione lazy a redis...
|
|
/// </summary>
|
|
private Lazy<ConnectionMultiplexer> lazyConnectionAdmin = new Lazy<ConnectionMultiplexer>(() =>
|
|
{
|
|
if (string.IsNullOrEmpty(RedisConnAdmin))
|
|
{
|
|
RedisConnAdmin = "localhost,abortConnect=false,ssl=false,allowAdmin=true";
|
|
}
|
|
return ConnectionMultiplexer.Connect(RedisConnAdmin);
|
|
});
|
|
|
|
#endregion Private Fields
|
|
|
|
#region Private Properties
|
|
|
|
/// <summary>
|
|
/// Oggetto currentDb REDIS locale
|
|
/// </summary>
|
|
private IDatabase _currDB { get; set; }
|
|
|
|
/// <summary>
|
|
/// Oggetto subscriber x pubblicazione/sottoscrizione canali REDIS
|
|
/// </summary>
|
|
private ISubscriber _currSub { get; set; }
|
|
|
|
#endregion Private Properties
|
|
|
|
#region Private Methods
|
|
|
|
/// <summary>
|
|
/// Effettua comaprazione x CHIAVE in KVP ASC
|
|
/// </summary>
|
|
/// <param name="x"></param>
|
|
/// <param name="y"></param>
|
|
/// <returns></returns>
|
|
private int CompareKey(KeyValuePair<string, int> x, KeyValuePair<string, int> y)
|
|
{
|
|
return x.Key.CompareTo(y.Key);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Effettua comaprazione x CHIAVE in KVP DESC
|
|
/// </summary>
|
|
/// <param name="x"></param>
|
|
/// <param name="y"></param>
|
|
/// <returns></returns>
|
|
private int CompareKeyDesc(KeyValuePair<string, int> x, KeyValuePair<string, int> y)
|
|
{
|
|
return y.Key.CompareTo(x.Key);
|
|
}
|
|
|
|
private void initHashKeys()
|
|
{
|
|
// init dati di base...
|
|
redServKey = redHash($"MP");
|
|
redIobKey = redHash($"IOB:{currCodIob}");
|
|
redIobChannel = $"IobChannel_{currCodIob}";
|
|
}
|
|
|
|
#endregion Private Methods
|
|
}
|
|
} |