1437 lines
51 KiB
C#
1437 lines
51 KiB
C#
using EgwCoreLib.Razor;
|
|
using IOB_MAN8.Core;
|
|
using IOB_MAN8.Core.DTO;
|
|
using Microsoft.Extensions.Configuration;
|
|
using Newtonsoft.Json;
|
|
using NLog;
|
|
using StackExchange.Redis;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Diagnostics;
|
|
using System.Globalization;
|
|
using System.Linq;
|
|
using System.Runtime;
|
|
using System.Text;
|
|
using System.Threading.Tasks;
|
|
|
|
namespace IOB_MAN8.Core.Data
|
|
{
|
|
/// <summary>
|
|
/// Classe gestione REDIS x recupero dati IOB
|
|
/// </summary>
|
|
public class RedisIobCache
|
|
{
|
|
#region Public Fields
|
|
|
|
/// <summary>
|
|
/// Hash REDIS x dati IOB
|
|
/// </summary>
|
|
public string redIobTrackKey = "";
|
|
|
|
#endregion Public Fields
|
|
|
|
#region Public Constructors
|
|
|
|
/// <summary>
|
|
/// Init classe gestione dati IOB su Redis
|
|
/// </summary>
|
|
/// <param name="redisMultiplex">Multiplexer connessione Redis</param>
|
|
/// <param name="codServer">Cod server con cui comunica</param>
|
|
/// <param name="codIob">Cod IOB gestito</param>
|
|
/// <param name="appNameExt">Nome app gestita (es IOB-WIN-NEXT)</param>
|
|
public RedisIobCache(IConnectionMultiplexer redisMultiplex, string codServer, string codIob, string appNameExt)
|
|
{
|
|
// init REDIS obj
|
|
redisConn = redisMultiplex;
|
|
redisDb = this.redisConn.GetDatabase();
|
|
// json serializer... FIX errore loop circolare https://www.ryadel.com/en/jsonserializationexception-self-referencing-loop-detected-error-fix-entity-framework-asp-net-core/
|
|
JSSettings = new JsonSerializerSettings()
|
|
{
|
|
ReferenceLoopHandling = ReferenceLoopHandling.Ignore
|
|
};
|
|
// init dati di base...
|
|
CodIob = codIob;
|
|
AppName = appNameExt;
|
|
redServKey = redHash(AppName, "MP");
|
|
redIobKey = redHash(AppName, $"IOB:{CodIob}");
|
|
redIobTrackKey = redHash(AppName, $"IOB:FluxLog:{CodIob}");
|
|
// init oggetti gestiti
|
|
ServerMpStatusDTO newSrvStatus = new ServerMpStatusDTO()
|
|
{
|
|
IP = codServer,
|
|
online = false
|
|
};
|
|
// init oggetto IOB
|
|
IobWinStatusDTO newIobStatus = new IobWinStatusDTO()
|
|
{
|
|
CodIob = codIob,
|
|
online = false
|
|
};
|
|
// salvo in area REDIS
|
|
servStatus = newSrvStatus;
|
|
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>
|
|
/// Accesso all'oggetto stato IOB da esterno
|
|
/// </summary>
|
|
public IobWinStatusDTO iobStatus
|
|
{
|
|
get
|
|
{
|
|
IobWinStatusDTO answ = new IobWinStatusDTO();
|
|
// cerco in REDIS
|
|
string rawData = getRSV(redIobKey);
|
|
// se non ci fosse creo e salvo
|
|
if (string.IsNullOrEmpty(rawData))
|
|
{
|
|
answ = new IobWinStatusDTO()
|
|
{
|
|
CodIob = CodIob,
|
|
online = false
|
|
};
|
|
// salvo serializzando...
|
|
rawData = JsonConvert.SerializeObject(answ);
|
|
setRSV(redIobKey, rawData);
|
|
}
|
|
else
|
|
{
|
|
// deserializzo
|
|
answ = JsonConvert.DeserializeObject<IobWinStatusDTO>(rawData) ?? new IobWinStatusDTO();
|
|
}
|
|
|
|
// aggiunta statistiche
|
|
DateTime adesso = DateTime.Now;
|
|
int ttlCache = 10;
|
|
string rKeyFLSent = $"{redIobTrackKey}:LastSent";
|
|
double ratio = 0;
|
|
if (redKeyPresent(rKeyFLSent))
|
|
{
|
|
var culture = CultureInfo.InvariantCulture;
|
|
string sRatio = getRSV(rKeyFLSent);
|
|
double.TryParse(sRatio, NumberStyles.Float, culture, out ratio);
|
|
}
|
|
// altrimenti calcolo
|
|
else
|
|
{
|
|
// recupero info accessorie x lettura dati e num FL inviati
|
|
var rKey = $"{redIobTrackKey}:DayStats:{adesso:yyMMdd}";
|
|
var rawStats = redGetHashDict(rKey);
|
|
// se ho dati li calcolo...
|
|
if (rawStats != null)
|
|
{
|
|
var numOre = adesso.Subtract(adesso.Date).TotalHours;
|
|
try
|
|
{
|
|
var numSent = rawStats.Sum(x => Convert.ToInt32(x.Value));
|
|
if (numOre > 0)
|
|
{
|
|
ratio = (double)numSent / (double)numOre;
|
|
}
|
|
}
|
|
catch
|
|
{ }
|
|
// salvo score x redisDb
|
|
setRSV(rKeyFLSent, ratio.ToString("F3", CultureInfo.InvariantCulture), ttlCache);
|
|
}
|
|
}
|
|
answ.sentFlHour = ratio;
|
|
|
|
// recupero info accessorie x info DataIn performances
|
|
string readBWidth = "NA";
|
|
int periodoCalcolo = 30;
|
|
string rKeyCalc = $"{redIobTrackKey}:LastScore";
|
|
// in primis: cerco in redisDb che uso x diminuire le letture complete...
|
|
if (redKeyPresent(rKeyCalc))
|
|
{
|
|
readBWidth = getRSV(rKeyCalc);
|
|
}
|
|
// altrimenti calcolo
|
|
else
|
|
{
|
|
if (redKeyPresent($"{redIobTrackKey}:DataInTS"))
|
|
{
|
|
// leggo dalle 2 chiavi TS/HS per ultimi 10 minuti
|
|
readBWidth = getEventsScore(redIobTrackKey, periodoCalcolo);
|
|
}
|
|
else if (redKeyPresent($"{redIobTrackKey}:DataIn:{adesso:yyMMdd}"))
|
|
{
|
|
readBWidth = getPollingScore($"{redIobTrackKey}:DataIn:{adesso:yyMMdd}");
|
|
}
|
|
else
|
|
{
|
|
readBWidth = "-";
|
|
}
|
|
// salvo score x redisDb
|
|
setRSV(rKeyCalc, readBWidth, ttlCache);
|
|
}
|
|
// salvo punteggio calcolato
|
|
answ.readBandwidth = readBWidth;
|
|
return answ;
|
|
}
|
|
set
|
|
{
|
|
string rawData = JsonConvert.SerializeObject(value);
|
|
setRSV(redIobKey, rawData);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Restituisce numero record in Redis DB
|
|
/// </summary>
|
|
public long numRecRedis
|
|
{
|
|
get
|
|
{
|
|
long answ = 0;
|
|
try
|
|
{
|
|
foreach (var ep in redisConn.GetEndPoints())
|
|
{
|
|
var server = redisConn.GetServer(ep);
|
|
answ += server.DatabaseSize();
|
|
}
|
|
}
|
|
catch (Exception exc)
|
|
{
|
|
Log.Error($"numRecRedis:{Environment.NewLine}{exc}");
|
|
}
|
|
return answ;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Accesso all'oggetto stato server da esterno
|
|
/// </summary>
|
|
public ServerMpStatusDTO servStatus
|
|
{
|
|
get
|
|
{
|
|
ServerMpStatusDTO answ = new ServerMpStatusDTO();
|
|
// cerco in REDIS
|
|
string rawData = getRSV(redServKey);
|
|
// se non ci fosse creo e salvo
|
|
if (string.IsNullOrEmpty(rawData))
|
|
{
|
|
answ = new ServerMpStatusDTO()
|
|
{
|
|
online = false
|
|
};
|
|
// salvo serializzando...
|
|
rawData = JsonConvert.SerializeObject(answ);
|
|
setRSV(redServKey, rawData);
|
|
}
|
|
else
|
|
{
|
|
// deserializzo
|
|
answ = JsonConvert.DeserializeObject<ServerMpStatusDTO>(rawData) ?? new ServerMpStatusDTO();
|
|
}
|
|
return answ;
|
|
}
|
|
set
|
|
{
|
|
string rawData = JsonConvert.SerializeObject(value);
|
|
setRSV(redServKey, rawData);
|
|
}
|
|
}
|
|
|
|
#endregion Public Properties
|
|
|
|
#region Public Methods
|
|
|
|
/// <summary>
|
|
/// Nome della variabile HASH da utilizzare (dato CodModulo / Server / DB impiegato da
|
|
/// funzionalita' DbConfig) + keyName richiesto...
|
|
/// </summary>
|
|
public static string redHash(string appName, string keyName)
|
|
{
|
|
keyName = keyName.Replace("\\", "_");
|
|
string answ = keyName;
|
|
try
|
|
{
|
|
answ = string.Format($"{appName}:{keyName}");
|
|
}
|
|
catch
|
|
{ }
|
|
return answ;
|
|
}
|
|
|
|
/// <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 { }
|
|
return answ;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Restituisce una chiave COUNTER in RedisCache
|
|
/// </summary>
|
|
/// <param name="chiave"></param>
|
|
/// <returns></returns>
|
|
public int getRCnt(string chiave)
|
|
{
|
|
int answInt = 0;
|
|
try
|
|
{
|
|
var rawData = redisDb.StringGet(chiave);
|
|
if (rawData.HasValue)
|
|
answInt = Convert.ToInt32(rawData);
|
|
}
|
|
catch (Exception exc)
|
|
{
|
|
Log.Error($"getRCnt:{Environment.NewLine}{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: {redisConn.Configuration}");
|
|
sb.AppendLine($"Connected: {redisConn.IsConnected}");
|
|
sb.AppendLine($"ClientName: {redisConn.ClientName}");
|
|
sb.AppendLine($"Total Ops: {redisConn.OperationCount}");
|
|
sb.AppendLine($"Status: {redisConn.GetStatus()}");
|
|
answ = sb.ToString();
|
|
}
|
|
catch
|
|
{ }
|
|
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 = new RedisValue[1];
|
|
try
|
|
{
|
|
answ = redisDb.StringGet(chiavi);
|
|
}
|
|
catch (Exception exc)
|
|
{
|
|
Log.Error($"getRKeys:{Environment.NewLine}{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
|
|
{
|
|
var rawData = redisDb.StringGet(chiave);
|
|
if (rawData.HasValue)
|
|
answ = $"{rawData}";
|
|
}
|
|
catch (Exception exc)
|
|
{
|
|
Log.Error($"getRSV:{Environment.NewLine}{exc}");
|
|
}
|
|
return answ;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Conta num oggetti redisDb 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 redisConn.GetEndPoints())
|
|
{
|
|
var server = redisConn.GetServer(ep);
|
|
foreach (var key in server.Keys(pattern: keyPattern))
|
|
{
|
|
answ++;
|
|
}
|
|
}
|
|
}
|
|
catch (Exception exc)
|
|
{
|
|
Log.Error($"redCountKey:{Environment.NewLine}{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;
|
|
redisDb.KeyDelete(chiave);
|
|
answ = true;
|
|
}
|
|
catch (Exception exc)
|
|
{
|
|
Log.Error($"redDelKey:{Environment.NewLine}{exc}");
|
|
}
|
|
return answ;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Flush completo redisDb redis
|
|
/// </summary>
|
|
/// <param name="strPattern">** = tutti</param>
|
|
/// <returns></returns>
|
|
public bool redFlushKey(string strPattern)
|
|
{
|
|
bool answ = false;
|
|
// cerco se ci sia valore in redis... se vuoto = ALL...
|
|
strPattern = string.IsNullOrEmpty(strPattern) ? "**" : strPattern;
|
|
RedisValue rkPattern = (RedisValue)strPattern;
|
|
ExecFlushRedisPattern(rkPattern);
|
|
return answ;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Restituisce oggetti redisDb 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 redisConn.GetEndPoints())
|
|
{
|
|
var server = redisConn.GetServer(ep);
|
|
foreach (var key in server.Keys(pattern: keyPattern))
|
|
{
|
|
chiavi[i] = key;
|
|
i++;
|
|
}
|
|
}
|
|
}
|
|
catch (Exception exc)
|
|
{
|
|
Log.Error($"redGetCounterByKey 01:{Environment.NewLine}{exc}");
|
|
}
|
|
// ora recupero valori!
|
|
var valori = getRKeys(chiavi);
|
|
int currVal = 0;
|
|
// popolo risposta
|
|
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)
|
|
{
|
|
Log.Error($"redGetCounterByKey 02:{Environment.NewLine}{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 = redisDb.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)
|
|
{
|
|
Log.Error($"redGetHash:{Environment.NewLine}{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 = redisDb.HashGetAll(chiave);
|
|
foreach (HashEntry item in valori)
|
|
{
|
|
answ.Add(item.Name, item.Value);
|
|
}
|
|
}
|
|
catch (Exception exc)
|
|
{
|
|
Log.Error($"redGetHashDict:{Environment.NewLine}{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 = redisDb.HashGet(chiave, campo);
|
|
answ = valOut.ToString();
|
|
}
|
|
catch (Exception exc)
|
|
{
|
|
Log.Error($"redGetHashField:{Environment.NewLine}{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 = redisDb.HashGetAll(key).Length > 0;
|
|
}
|
|
catch (Exception exc)
|
|
{
|
|
Log.Error($"redHashPresent:{Environment.NewLine}{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)
|
|
{
|
|
Log.Error($"redHashPresentSz:{Environment.NewLine}{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 = redisDb.KeyExists(key);
|
|
}
|
|
catch (Exception exc)
|
|
{
|
|
Log.Error($"redKeyPresent:{Environment.NewLine}{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)
|
|
{
|
|
Log.Error($"redKeyPresentSz:{Environment.NewLine}{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++;
|
|
}
|
|
redisDb.HashSet(chiave, valori);
|
|
answ = true;
|
|
}
|
|
catch (Exception exc)
|
|
{
|
|
Log.Error($"redSaveHash:{Environment.NewLine}{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)
|
|
{
|
|
redisDb.KeyExpire(chiave, DateTime.Now.AddSeconds(expireSeconds));
|
|
}
|
|
//answ = true;
|
|
}
|
|
catch (Exception exc)
|
|
{
|
|
Log.Error($"redSaveHash:{Environment.NewLine}{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++;
|
|
}
|
|
redisDb.HashSet(chiave, valori);
|
|
answ = true;
|
|
}
|
|
catch (Exception exc)
|
|
{
|
|
Log.Error($"redSaveHashDict:{Environment.NewLine}{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)
|
|
{
|
|
redisDb.KeyExpire(chiave, DateTime.Now.AddSeconds(expireSeconds));
|
|
}
|
|
//answ = true;
|
|
}
|
|
catch (Exception exc)
|
|
{
|
|
Log.Error($"redSaveHashDict:{Environment.NewLine}{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 (redisConn.IsConnected)
|
|
{
|
|
// cerco se ci sia valore in redis...
|
|
IDatabase cache = redisConn.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)
|
|
{
|
|
Log.Error($"redSaveHashList:{Environment.NewLine}{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 = redisDb.KeyDelete(chiave);
|
|
}
|
|
catch (Exception exc)
|
|
{
|
|
Log.Error($"resetRCnt:{Environment.NewLine}{exc}");
|
|
}
|
|
return answ;
|
|
}
|
|
|
|
/// <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 { }
|
|
return answ;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Decrementa un contatore in Redis
|
|
/// </summary>
|
|
/// <param name="chiave"></param>
|
|
/// <returns></returns>
|
|
public long setRCntD(string chiave)
|
|
{
|
|
long answ = 0;
|
|
try
|
|
{
|
|
answ = redisDb.StringDecrement(chiave, 1);
|
|
}
|
|
catch (Exception exc)
|
|
{
|
|
Log.Error($"setRCntD:{Environment.NewLine}{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 = redisDb.StringIncrement(chiave, 1);
|
|
}
|
|
catch (Exception exc)
|
|
{
|
|
Log.Error($"setRCntI:{Environment.NewLine}{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
|
|
{
|
|
redisDb.StringSet(valori);
|
|
answ = true;
|
|
}
|
|
catch (Exception exc)
|
|
{
|
|
Log.Error($"setRKeys:{Environment.NewLine}{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
|
|
{
|
|
redisDb.StringSet(chiave, valore);
|
|
answ = true;
|
|
}
|
|
catch (Exception exc)
|
|
{
|
|
Log.Error($"setRSV:{Environment.NewLine}{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...
|
|
redisDb.StringSet(chiave, valore, expT);
|
|
answ = true;
|
|
}
|
|
catch (Exception exc)
|
|
{
|
|
Log.Error($"setRSV + ttl:{Environment.NewLine}{exc}");
|
|
}
|
|
return answ;
|
|
}
|
|
|
|
#endregion Public Methods
|
|
|
|
#region Protected Fields
|
|
|
|
/// <summary>
|
|
/// Cod IOB
|
|
/// </summary>
|
|
protected string AppName = "IOB";
|
|
|
|
/// <summary>
|
|
/// Cod IOB
|
|
/// </summary>
|
|
protected string CodIob = "000";
|
|
|
|
/// <summary>
|
|
/// Hash redis x dati IOB
|
|
/// </summary>
|
|
protected string redIobKey = "";
|
|
|
|
/// <summary>
|
|
/// Hash redis x dati server
|
|
/// </summary>
|
|
protected string redServKey = "";
|
|
|
|
#endregion Protected Fields
|
|
|
|
#region Protected Methods
|
|
|
|
protected void CleanExpiredEvents(string rkeyTS, string rkeyHash, int minutesBack, int batchSize = 1000)
|
|
{
|
|
long adesso = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
|
|
long cutoffTimeMillis = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds() - (long)TimeSpan.FromMinutes(minutesBack).TotalMilliseconds;
|
|
|
|
// PRIMA: Recupera gli ID degli eventi che saranno rimossi dal Sorted Set.
|
|
// Facciamo questo per poter poi rimuovere i loro dettagli dalla Hash Table.
|
|
// Utilizziamo ZRangeByScoreAsync con un intervallo da -infinito fino al cutoffTimeMillis.
|
|
RedisValue[] eventIdsToClean = redisDb.SortedSetRangeByScore(
|
|
rkeyTS,
|
|
//start: double.NegativeInfinity, // Per ottenere tutti gli elementi dal più vecchio, uso default
|
|
stop: cutoffTimeMillis,
|
|
exclude: Exclude.None,
|
|
order: Order.Ascending, // Non strettamente necessario, ma può aiutare per debug
|
|
take: batchSize // Limita il numero di elementi recuperati
|
|
);
|
|
|
|
if (eventIdsToClean == null || eventIdsToClean.Length == 0)
|
|
{
|
|
Log.Debug("Nessun evento scaduto da pulire.");
|
|
return;
|
|
}
|
|
// rimuovo SOLO i valori definiti da rimuovere...
|
|
long removedFromZSet = redisDb.SortedSetRemove(rkeyTS, eventIdsToClean);
|
|
|
|
// Operazione 2 nel batch: Rimuovi i dettagli corrispondenti dalla Hash Table.
|
|
// Dobbiamo convertire i RedisValue[] in string[] per HDelAsync che accetta params RedisValue[]
|
|
RedisValue[] eventIdsAsRedisValues = eventIdsToClean.Select(id => (RedisValue)id.ToString()).ToArray();
|
|
redisDb.HashDelete(rkeyHash, eventIdsAsRedisValues);
|
|
Log.Trace($"Pulizia completata. Rimossi {eventIdsToClean.Length} eventi più vecchi di {minutesBack} minuti.");
|
|
}
|
|
|
|
/// <summary>
|
|
/// Pulisce gli eventi più vecchi di un certo numero di minuti sia dal Sorted Set che dalla Hash Table.
|
|
/// </summary>
|
|
/// <param name="rkeyTS">Chiave ZSet eventi tracciati per recupero recenti</param>
|
|
/// <param name="rkeyHash">Chiave hashset valore eventi</param>
|
|
/// <param name="minutesBack">Il numero di minuti oltre il quale gli eventi sono considerati "scaduti".</param>
|
|
protected async Task CleanExpiredEventsAsync(string rkeyTS, string rkeyHash, int minutesBack)
|
|
{
|
|
long cutoffTimeMillis = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds() - (long)TimeSpan.FromMinutes(minutesBack).TotalMilliseconds;
|
|
|
|
// PRIMA: Recupera gli ID degli eventi che saranno rimossi dal Sorted Set.
|
|
// Facciamo questo per poter poi rimuovere i loro dettagli dalla Hash Table.
|
|
// Utilizziamo ZRangeByScoreAsync con un intervallo da -infinito fino al cutoffTimeMillis.
|
|
RedisValue[] eventIdsToClean = await redisDb.SortedSetRangeByScoreAsync(
|
|
rkeyTS,
|
|
//start: double.NegativeInfinity, // Per ottenere tutti gli elementi dal più vecchio, uso default
|
|
stop: cutoffTimeMillis,
|
|
exclude: Exclude.None,
|
|
order: Order.Ascending // Non strettamente necessario, ma può aiutare per debug
|
|
);
|
|
|
|
if (eventIdsToClean == null || eventIdsToClean.Length == 0)
|
|
{
|
|
Log.Debug("Nessun evento scaduto da pulire.");
|
|
return;
|
|
}
|
|
|
|
// Operazione 1 nel batch: Rimuovi gli eventi scaduti dal Sorted Set.
|
|
// ZRemRangeByScoreAsync rimuove tutti i membri con score <= al max specificato.
|
|
await redisDb.SortedSetRemoveRangeByScoreAsync(rkeyTS, double.NegativeInfinity, cutoffTimeMillis);
|
|
|
|
// Operazione 2 nel batch: Rimuovi i dettagli corrispondenti dalla Hash Table.
|
|
// Dobbiamo convertire i RedisValue[] in string[] per HDelAsync che accetta params RedisValue[]
|
|
RedisValue[] eventIdsAsRedisValues = eventIdsToClean.Select(id => (RedisValue)id.ToString()).ToArray();
|
|
await redisDb.HashDeleteAsync(rkeyHash, eventIdsAsRedisValues);
|
|
Log.Debug($"Pulizia completata. Rimossi {eventIdsToClean.Length} eventi più vecchi di {minutesBack} minuti.");
|
|
}
|
|
|
|
/// <summary>
|
|
/// Recupera gli eventi degli ultimi minuti specificati e ne somma la quantità di dati.
|
|
/// </summary>
|
|
/// <param name="rkeyTS">Chiave ZSet eventi tracciati per recupero recenti</param>
|
|
/// <param name="rkeyHash">Chiave hashset valore eventi</param>
|
|
/// <param name="minutesBack">Il numero di minuti da cui recuperare gli eventi.</param>
|
|
/// <returns>Dimensione eventi indicata in KB (1024)</returns>
|
|
protected double GetRecentEventsAndSum(string rkeyTS, string rkeyHash, int minutesBack)
|
|
{
|
|
long currTimeMillis = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
|
|
long limitTimeMillis = currTimeMillis - (long)TimeSpan.FromMinutes(minutesBack).TotalMilliseconds;
|
|
|
|
// Recupera gli ID degli eventi dal Sorted Set nell'intervallo di tempo
|
|
// `SortedSetRangeByScoreAsync` restituisce i membri il cui score rientra nell'intervallo.
|
|
// I membri sono RedisValue, quindi potrebbero essere necessari .ToString() o .ToByteArray()
|
|
RedisValue[] eventIds = redisDb.SortedSetRangeByScore(
|
|
rkeyTS,
|
|
start: limitTimeMillis,
|
|
stop: currTimeMillis,
|
|
exclude: Exclude.None, // Includi entrambi gli estremi
|
|
order: Order.Ascending // Ordina per timestamp crescente
|
|
);
|
|
|
|
if (eventIds == null || eventIds.Length == 0)
|
|
{
|
|
return 0;
|
|
}
|
|
// Prepara l'array di RedisValue per la query HMGET
|
|
RedisValue[] eventIdsAsRedisValues = eventIds.ToList().Select(id => (RedisValue)id.ToString()).ToArray();
|
|
// Recupera le quantità di dati dalla Hash Table per gli ID trovati
|
|
// HMGET restituisce un array di RedisValue corrispondente ai field richiesti.
|
|
RedisValue[] dataQuantities = redisDb.HashGet(rkeyHash, eventIdsAsRedisValues);
|
|
long totalDataExchanged = 0;
|
|
for (int i = 0; i < eventIds.Length; i++)
|
|
{
|
|
string eventId = eventIds[i].ToString();
|
|
RedisValue quantityRedisValue = dataQuantities[i];
|
|
if (quantityRedisValue.HasValue && long.TryParse(quantityRedisValue.ToString(), out long quantity))
|
|
{
|
|
totalDataExchanged += quantity;
|
|
}
|
|
else
|
|
{
|
|
Log.Trace("Avviso: Dati mancanti o non validi per l'evento ID: {eventId}");
|
|
}
|
|
}
|
|
|
|
Log.Trace("Totale dati scambiati negli ultimi {minutesBack} minuti: {totalDataExchanged}");
|
|
Log.Trace("Elenco eventi trovati: {eventList.Count}");
|
|
return (double)totalDataExchanged / 1024;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Pulisce gli eventi più vecchi di un certo numero di minuti sia dal Sorted Set che dalla Hash Table.
|
|
/// </summary>
|
|
/// <param name="rkeyTS">Chiave ZSet eventi tracciati per recupero recenti</param>
|
|
/// <param name="rkeyHash">Chiave hashset valore eventi</param>
|
|
/// <param name="minutesBack">Il numero di minuti oltre il quale gli eventi sono considerati "scaduti".</param>
|
|
/// <param name="batchSize">Il numero massimo di eventi da rimuovere in una singola operazione.</param>
|
|
/// <summary>
|
|
/// Recupera gli eventi degli ultimi minuti specificati e ne somma la quantità di dati.
|
|
/// </summary>
|
|
/// <param name="rkeyTS">Chiave ZSet eventi tracciati per recupero recenti</param>
|
|
/// <param name="rkeyHash">Chiave hashset valore eventi</param>
|
|
/// <param name="minutesBack">Il numero di minuti da cui recuperare gli eventi.</param>
|
|
/// <returns>Una tupla contenente la quantità totale di dati scambiati e un elenco degli eventi trovati.</returns>
|
|
protected async Task<(long TotalDataExchanged, List<(string EventId, long Data)> EventList)> GetRecentEventsAndSumAsync(string rkeyTS, string rkeyHash, int minutesBack)
|
|
{
|
|
long currentTimeMillis = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
|
|
long fiveMinutesAgoMillis = currentTimeMillis - (long)TimeSpan.FromMinutes(minutesBack).TotalMilliseconds;
|
|
|
|
// Recupera gli ID degli eventi dal Sorted Set nell'intervallo di tempo
|
|
// `SortedSetRangeByScoreAsync` restituisce i membri il cui score rientra nell'intervallo.
|
|
// I membri sono RedisValue, quindi potrebbero essere necessari .ToString() o .ToByteArray()
|
|
RedisValue[] eventIds = await redisDb.SortedSetRangeByScoreAsync(
|
|
rkeyTS,
|
|
start: fiveMinutesAgoMillis,
|
|
stop: currentTimeMillis,
|
|
exclude: Exclude.None, // Includi entrambi gli estremi
|
|
order: Order.Ascending // Ordina per timestamp crescente
|
|
);
|
|
|
|
if (eventIds == null || eventIds.Length == 0)
|
|
{
|
|
return (0, new List<(string, long)>());
|
|
}
|
|
// Prepara l'array di RedisValue per la query HMGET
|
|
RedisValue[] eventIdsAsRedisValues = eventIds.ToList().Select(id => (RedisValue)id.ToString()).ToArray();
|
|
// Recupera le quantità di dati dalla Hash Table per gli ID trovati
|
|
// HMGET restituisce un array di RedisValue corrispondente ai field richiesti.
|
|
RedisValue[] dataQuantities = await redisDb.HashGetAsync(rkeyHash, eventIdsAsRedisValues);
|
|
long totalDataExchanged = 0;
|
|
var eventList = new List<(string EventId, long Data)>();
|
|
for (int i = 0; i < eventIds.Length; i++)
|
|
{
|
|
string eventId = eventIds[i].ToString();
|
|
RedisValue quantityRedisValue = dataQuantities[i];
|
|
if (quantityRedisValue.HasValue && long.TryParse(quantityRedisValue.ToString(), out long quantity))
|
|
{
|
|
totalDataExchanged += quantity;
|
|
eventList.Add((eventId, quantity));
|
|
}
|
|
else
|
|
{
|
|
Log.Debug("Avviso: Dati mancanti o non validi per l'evento ID: {eventId}");
|
|
}
|
|
}
|
|
|
|
Log.Debug("Totale dati scambiati negli ultimi {minutesBack} minuti: {totalDataExchanged}");
|
|
Log.Debug("Elenco eventi trovati: {eventList.Count}");
|
|
return (totalDataExchanged, eventList);
|
|
}
|
|
|
|
#endregion Protected Methods
|
|
|
|
#region Private Fields
|
|
|
|
private static JsonSerializerSettings? JSSettings;
|
|
private static Logger Log = LogManager.GetCurrentClassLogger();
|
|
|
|
/// <summary>
|
|
/// Oggetto per connessione a REDIS
|
|
/// </summary>
|
|
private IConnectionMultiplexer redisConn;
|
|
|
|
/// <summary>
|
|
/// Oggetto currentDb locale
|
|
/// </summary>
|
|
private IDatabase redisDb = null!;
|
|
|
|
#endregion Private Fields
|
|
|
|
#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);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Esegue flush memoria redis dato pattern
|
|
/// </summary>
|
|
/// <param name="pattern"></param>
|
|
/// <returns></returns>
|
|
private bool ExecFlushRedisPattern(RedisValue pattern)
|
|
{
|
|
bool answ = 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)
|
|
{
|
|
redisDb.KeyDelete(item);
|
|
}
|
|
answ = true;
|
|
}
|
|
}
|
|
|
|
return answ;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Esegue flush memoria redis dato pattern
|
|
/// </summary>
|
|
/// <param name="pattern"></param>
|
|
/// <returns></returns>
|
|
private async Task<bool> ExecFlushRedisPatternAsync(RedisValue pattern)
|
|
{
|
|
bool answ = 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;
|
|
}
|
|
}
|
|
|
|
return answ;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Recupero conteggio bandwith dall'analisi dei dati registrati come evento per la finestra richeista
|
|
/// </summary>
|
|
/// <param name="rKeyBase">Key di base dei valori salvari</param>
|
|
/// <param name="rKeyTS">Key dei valori HASHSET salvati</param>
|
|
/// <param name="minutesBack">Durata in minuti della finestra di analisi richiesta</param>
|
|
/// <returns></returns>
|
|
private string getEventsScore(string rKeyBase, int minutesBack)
|
|
{
|
|
// redisDb score parametri estesi x 20 sec...
|
|
string rKeyTS = $"{rKeyBase}:DataInTS";
|
|
string rKeyHS = $"{rKeyBase}:DataInHS";
|
|
string readScore = "";
|
|
if (minutesBack > 0)
|
|
{
|
|
double readTime = minutesBack;
|
|
// svuoto valori scaduti...
|
|
CleanExpiredEvents(rKeyTS, rKeyHS, minutesBack);
|
|
// recupero il valore double in KB degli eventi tracciati...
|
|
double kbRead = GetRecentEventsAndSum(rKeyTS, rKeyHS, minutesBack);
|
|
//valore come kb/sec
|
|
double kbSec = (double)kbRead / (double)readTime;
|
|
if (kbSec < 1)
|
|
{
|
|
readScore = $"{kbSec * 1024:N0} b/m";
|
|
}
|
|
else if (kbSec < 1024)
|
|
{
|
|
readScore = $"{kbSec:N2} Kb/m";
|
|
}
|
|
else
|
|
{
|
|
readScore = $"{kbSec / 1024:N1} Mb/m";
|
|
}
|
|
}
|
|
else
|
|
{
|
|
readScore = "na";
|
|
}
|
|
// restituisco valore calcolato
|
|
return readScore;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Recupero conteggio bandwith dall'analisi dei dati dalla hash indicata
|
|
/// </summary>
|
|
/// <param name="rKey"></param>
|
|
/// <returns></returns>
|
|
private string getPollingScore(string rKey)
|
|
{
|
|
string readScore = "";
|
|
var rawStats = redGetHashDict(rKey);
|
|
// se ho dati li calcolo...
|
|
if (rawStats != null && rawStats.Count > 1)
|
|
{
|
|
double kbRead = 0;
|
|
double readTime = 1;
|
|
// Specify Culture
|
|
var culture = CultureInfo.InvariantCulture;
|
|
|
|
if (rawStats.ContainsKey("KbRead"))
|
|
{
|
|
string rawVal = rawStats["KbRead"];
|
|
double.TryParse(rawVal, NumberStyles.Float, culture, out kbRead);
|
|
}
|
|
if (rawStats.ContainsKey("ProcTime"))
|
|
{
|
|
string rawVal = rawStats["ProcTime"];
|
|
double.TryParse(rawVal, NumberStyles.Float, culture, out readTime);
|
|
}
|
|
if (readTime > 0)
|
|
{
|
|
//valore come kb/sec
|
|
double kbSec = (double)kbRead / (double)readTime;
|
|
if (kbSec < 1)
|
|
{
|
|
readScore = $"{kbSec * 1024:N1} b/s";
|
|
}
|
|
else if (kbSec < 1024)
|
|
{
|
|
readScore = $"{kbSec:N1} Kb/s";
|
|
}
|
|
else
|
|
{
|
|
readScore = $"{kbSec / 1024:N1} Mb/s";
|
|
}
|
|
}
|
|
else
|
|
{
|
|
readScore = "na";
|
|
}
|
|
}
|
|
// restituisco valore calcolato
|
|
return readScore;
|
|
}
|
|
|
|
#endregion Private Methods
|
|
|
|
#if false
|
|
/// <summary>
|
|
/// Connessione lazy a redis...
|
|
/// </summary>
|
|
private static Lazy<ConnectionMultiplexer> lazyConnection = new Lazy<ConnectionMultiplexer>(() =>
|
|
{
|
|
string RedisConn = utils.CRS("RedisConn");
|
|
if (string.IsNullOrEmpty(RedisConn))
|
|
{
|
|
RedisConn = "localhost,abortConnect=false,ssl=false";
|
|
}
|
|
|
|
return ConnectionMultiplexer.Connect(RedisConn);
|
|
});
|
|
|
|
/// <summary>
|
|
/// Connessione lazy a redis...
|
|
/// </summary>
|
|
private static Lazy<ConnectionMultiplexer> lazyConnectionAdmin = new Lazy<ConnectionMultiplexer>(() =>
|
|
{
|
|
string RedisConnAdmin = utils.CRS("RedisConnAdmin");
|
|
if (string.IsNullOrEmpty(RedisConnAdmin))
|
|
{
|
|
RedisConnAdmin = "localhost,abortConnect=false,ssl=false,allowAdmin=true";
|
|
}
|
|
|
|
return ConnectionMultiplexer.Connect(RedisConnAdmin);
|
|
});
|
|
#endif
|
|
}
|
|
} |