Files
webdoorcreator/WebDoorCreator.Data/Services/QueueDataService.cs
T
2023-05-12 15:07:02 +02:00

831 lines
30 KiB
C#

using Microsoft.AspNetCore.Identity.UI.Services;
using Microsoft.Extensions.Configuration;
using Newtonsoft.Json;
using NLog;
using StackExchange.Redis;
using System.Diagnostics;
using WebDoorCreator.Core;
using WebDoorCreator.Data.DTO;
namespace WebDoorCreator.Data.Services
{
public class QueueDataService : IDisposable
{
#region Public Constructors
/// <summary>
/// Init classe
/// </summary>
/// <param name="configuration"></param>
/// <param name="logger"></param>
/// <param name="emailSender"></param>
/// <param name="redisCacheClient"></param>
public QueueDataService(IConfiguration configuration, IEmailSender emailSender, IConnectionMultiplexer redisConn)
{
_configuration = configuration;
_emailSender = emailSender;
// setup componenti REDIS
var redConnString = _configuration.GetConnectionString("Redis");
if (redConnString == null)
{
Log.Error("REDIS ConnString empty!");
}
else
{
this.redisConn = ConnectionMultiplexer.Connect(redConnString);
redisDb = this.redisConn.GetDatabase();
}
// setup canali pub/sub
CalcReqPipe = new MessagePipe(redisConn, Constants.CALC_REQ_QUEUE);
CalcDonePipe = new MessagePipe(redisConn, Constants.CALC_DONE_QUEUE);
}
#endregion Public Constructors
#region Public Properties
/// <summary>
/// Message pipe esecuzione elaborazione CAM --&gt; UI
/// </summary>
public MessagePipe CalcDonePipe { get; set; } = null!;
/// <summary>
/// Message pipe richieste elaborazione UI --&gt; CAM
/// </summary>
public MessagePipe CalcReqPipe { get; set; } = null!;
#endregion Public Properties
#region Public Methods
public void Dispose()
{
redisConn.Dispose();
}
/// <summary>
/// Restitusice gli errori della porta in oggetto
/// </summary>
/// <param name="doorIdVers">formato DoorId:Versione</param>
/// <returns></returns>
public async Task<bool> DoorErrExists(string doorIdVers)
{
bool hasErr = false;
// cerco versione errore x la porta...
var doorData = doorIdVers.Split(":");
if (doorData.Length == 2)
{
RedisKey currErrKey = new RedisKey($"{Constants.CALC_REQ_ERRS}");
int currId = await RedHashGet(currErrKey, doorData[0]);
hasErr = doorData[1] == $"{currId}";
}
return hasErr;
}
/// <summary>
/// Restitusice gli errori della porta in oggetto
/// </summary>
/// <param name="doorIdVers">formato DoorId:Versione</param>
/// <returns></returns>
public async Task<string> DoorErrGet(string doorIdVers)
{
RedisKey currErrKey = new RedisKey($"{Constants.CALC_REQ_ERRS}:{doorIdVers}");
RedisValue errVal = await redisDb.StringGetAsync(currErrKey);
return errVal.ToString();
}
/// <summary>
/// Restitusice l'SVG della porta in oggetto
/// </summary>
/// <param name="doorIdVers">formato DoorId:Versione</param>
/// <returns></returns>
public async Task<string> DoorSvgGet(string doorIdVers)
{
RedisKey currSvgKey = new RedisKey($"{Constants.CALC_REQ_SVG_CACHE}:{doorIdVers}");
RedisValue svgVal = await redisDb.StringGetAsync(currSvgKey);
return svgVal.ToString();
}
public async Task<bool> FlushRedisCache()
{
await Task.Delay(1);
RedisValue pattern = new RedisValue($"{Constants.BASE_HASH}:Cache*");
bool answ = await ExecFlushRedisPattern(pattern);
return answ;
}
/// <summary>
/// Get # of calculation request done
/// </summary>
public async Task<long> NumRequestDone()
{
long numReq = 0;
string source = "REDIS";
Dictionary<string, string> dictResult = new Dictionary<string, string>();
// cerco da cache
RedisKey currKey = new RedisKey(Constants.CALC_REQ_DONE);
Stopwatch stopWatch = new Stopwatch();
stopWatch.Start();
numReq = await redisDb.HashLengthAsync(currKey);
stopWatch.Stop();
TimeSpan ts = stopWatch.Elapsed;
Log.Debug($"NumRequestDone | {source} in: {ts.TotalMilliseconds} ms");
return numReq;
}
/// <summary>
/// Get # of calculation request with errors
/// </summary>
public async Task<long> NumRequestErrors()
{
long numReq = 0;
string source = "REDIS";
Dictionary<string, string> dictResult = new Dictionary<string, string>();
// cerco da cache
RedisKey currKey = new RedisKey(Constants.CALC_REQ_ERRS);
Stopwatch stopWatch = new Stopwatch();
stopWatch.Start();
numReq = await redisDb.HashLengthAsync(currKey);
stopWatch.Stop();
TimeSpan ts = stopWatch.Elapsed;
Log.Debug($"NumRequestErrors | {source} in: {ts.TotalMilliseconds} ms");
return numReq;
}
/// <summary>
/// Get # of calculation request pending
/// </summary>
public async Task<long> NumRequestPending()
{
long numReq = 0;
string source = "REDIS";
Dictionary<string, string> dictResult = new Dictionary<string, string>();
// cerco da cache
RedisKey currKey = new RedisKey(Constants.CALC_REQ_PEND);
Stopwatch stopWatch = new Stopwatch();
stopWatch.Start();
numReq = await redisDb.HashLengthAsync(currKey);
stopWatch.Stop();
TimeSpan ts = stopWatch.Elapsed;
Log.Debug($"NumRequestPending | {source} in: {ts.TotalMilliseconds} ms");
return numReq;
}
/// <summary>
/// Get # of calculation request processing
/// </summary>
public async Task<long> NumRequestProcessing()
{
long numReq = 0;
string source = "REDIS";
Dictionary<string, string> dictResult = new Dictionary<string, string>();
// cerco da cache
RedisKey currKey = new RedisKey(Constants.CALC_REQ_PROC);
Stopwatch stopWatch = new Stopwatch();
stopWatch.Start();
numReq = await redisDb.HashLengthAsync(currKey);
stopWatch.Stop();
TimeSpan ts = stopWatch.Elapsed;
Log.Debug($"NumRequestProcessing | {source} in: {ts.TotalMilliseconds} ms");
return numReq;
}
/// <summary>
/// Remove for single hash record
/// </summary>
/// <param name="currKey">Chiave redis della Hashlist</param>
/// <param name="chiave">Chiave nella HashList</param>
/// <returns>Esito rimozione</returns>
public async Task<bool> RedHashRemove(RedisKey currKey, string chiave)
{
bool fatto = false;
Stopwatch stopWatch = new Stopwatch();
stopWatch.Start();
fatto = await redisDb.HashDeleteAsync(currKey, chiave);
stopWatch.Stop();
TimeSpan ts = stopWatch.Elapsed;
Log.Trace($"RedHashRemove | {currKey} | in: {ts.TotalMilliseconds} ms");
return fatto;
}
/// <summary>
/// Verify existence for single hash record
/// </summary>
/// <param name="currKey">Chiave redis della Hashlist</param>
/// <param name="chiave">Chiave nella HashList</param>
/// <returns>Esito rimozione</returns>
public async Task<int> RedHashGet(RedisKey currKey, string chiave)
{
int result = 0;
Stopwatch stopWatch = new Stopwatch();
stopWatch.Start();
var hasVal = await redisDb.HashExistsAsync(currKey, chiave);
if (hasVal)
{
var rawRes = await redisDb.HashGetAsync(currKey, chiave);
if (rawRes.HasValue)
{
int.TryParse($"{rawRes}", out result);
}
}
stopWatch.Stop();
TimeSpan ts = stopWatch.Elapsed;
Log.Trace($"RedHashGet | {currKey} | in: {ts.TotalMilliseconds} ms");
return result;
}
/// <summary>
/// Get Queue request done
/// </summary>
/// <returns>Dictionary of DoorId, saveVersNumb</returns>
public async Task<Dictionary<string, string>> RequestDone()
{
string source = "REDIS";
long numReq = 0;
Dictionary<string, string> dictResult = new Dictionary<string, string>();
// cerco da cache
RedisKey currKey = new RedisKey(Constants.CALC_REQ_DONE);
Stopwatch stopWatch = new Stopwatch();
stopWatch.Start();
numReq = redisDb.HashLength(currKey);
if (numReq > 0)
{
var rawData = await redisDb.HashGetAllAsync(currKey);
foreach (var item in rawData)
{
dictResult.Add($"{item.Name}", $"{item.Value}");
}
}
stopWatch.Stop();
TimeSpan ts = stopWatch.Elapsed;
Log.Debug($"RequestDone | {source} in: {ts.TotalMilliseconds} ms");
return dictResult;
}
/// <summary>
/// Remove for single hash record
/// </summary>
/// <returns>Dictionary of DoorId, saveVersNumb</returns>
public async Task<bool> RequestDoneRemove(string doorId)
{
RedisKey currKey = new RedisKey(Constants.CALC_REQ_DONE);
bool fatto = await RedHashRemove(currKey, doorId);
return fatto;
}
/// <summary>
/// Upsert for single hash record
/// </summary>
/// <returns>Dictionary of DoorId, saveVersNumb</returns>
public async Task<long> RequestDoneUpsert(string doorId, string vers)
{
RedisKey currKey = new RedisKey(Constants.CALC_REQ_DONE);
long numReq = await RedHashUpsert(currKey, doorId, vers);
return numReq;
}
/// <summary>
/// Get Queue request with errors
/// </summary>
/// <returns>Dictionary of DoorId, saveVersNumb</returns>
public async Task<Dictionary<string, string>> RequestErr()
{
string source = "REDIS";
long numReq = 0;
Dictionary<string, string> dictResult = new Dictionary<string, string>();
// cerco da cache
RedisKey currKey = new RedisKey(Constants.CALC_REQ_ERRS);
Stopwatch stopWatch = new Stopwatch();
stopWatch.Start();
numReq = redisDb.HashLength(currKey);
if (numReq > 0)
{
var rawData = await redisDb.HashGetAllAsync(currKey);
foreach (var item in rawData)
{
dictResult.Add($"{item.Name}", $"{item.Value}");
}
}
stopWatch.Stop();
TimeSpan ts = stopWatch.Elapsed;
Log.Debug($"RequestErr | {source} in: {ts.TotalMilliseconds} ms");
return dictResult;
}
/// <summary>
/// Rimuove hash record errori
/// </summary>
/// <returns>Dictionary of DoorId, saveVersNumb</returns>
public async Task<bool> RequestErrRemove(string doorId)
{
RedisKey currKey = new RedisKey(Constants.CALC_REQ_ERRS);
bool fatto = await RedHashRemove(currKey, doorId);
return fatto;
}
/// <summary>
/// Upsert record errori
/// </summary>
/// <returns>Dictionary of DoorId, saveVersNumb</returns>
public async Task<long> RequestErrUpsert(string doorId, string vers)
{
RedisKey currKey = new RedisKey(Constants.CALC_REQ_ERRS);
long numReq = await RedHashUpsert(currKey, doorId, vers);
return numReq;
}
/// <summary>
/// Get Queue request pending
/// </summary>
/// <returns>Dictionary of DoorId, saveVersNumb</returns>
public async Task<Dictionary<string, string>> RequestPending()
{
string source = "REDIS";
long numReq = 0;
Dictionary<string, string> dictResult = new Dictionary<string, string>();
// cerco da cache
RedisKey currKey = new RedisKey(Constants.CALC_REQ_PEND);
Stopwatch stopWatch = new Stopwatch();
stopWatch.Start();
numReq = redisDb.HashLength(currKey);
if (numReq > 0)
{
var rawData = await redisDb.HashGetAllAsync(currKey);
foreach (var item in rawData)
{
dictResult.Add($"{item.Name}", $"{item.Value}");
}
}
stopWatch.Stop();
TimeSpan ts = stopWatch.Elapsed;
Log.Debug($"RequestPending | {source} in: {ts.TotalMilliseconds} ms");
return dictResult;
}
/// <summary>
/// Remove for single hash record
/// </summary>
/// <returns>Dictionary of DoorId, saveVersNumb</returns>
public async Task<bool> RequestPendingRemove(string doorId)
{
RedisKey currKey = new RedisKey(Constants.CALC_REQ_PEND);
bool fatto = await RedHashRemove(currKey, doorId);
return fatto;
}
/// <summary>
/// Upsert for single hash record
/// </summary>
/// <returns>Dictionary of DoorId, saveVersNumb</returns>
public async Task<long> RequestPendingUpsert(string doorId, string vers)
{
RedisKey currKey = new RedisKey(Constants.CALC_REQ_PEND);
long numReq = await RedHashUpsert(currKey, doorId, vers);
return numReq;
}
/// <summary>
/// Get Queue request processing
/// </summary>
/// <returns>Dictionary of DoorId, saveVersNumb</returns>
public async Task<Dictionary<string, string>> RequestProcessing()
{
string source = "REDIS";
long numReq = 0;
Dictionary<string, string> dictResult = new Dictionary<string, string>();
// cerco da cache
RedisKey currKey = new RedisKey(Constants.CALC_REQ_PROC);
Stopwatch stopWatch = new Stopwatch();
stopWatch.Start();
numReq = redisDb.HashLength(currKey);
if (numReq > 0)
{
var rawData = await redisDb.HashGetAllAsync(currKey);
foreach (var item in rawData)
{
dictResult.Add($"{item.Name}", $"{item.Value}");
}
}
stopWatch.Stop();
TimeSpan ts = stopWatch.Elapsed;
Log.Debug($"RequestProcessing | {source} in: {ts.TotalMilliseconds} ms");
return dictResult;
}
/// <summary>
/// Remove for single hash record
/// </summary>
/// <returns>Dictionary of DoorId, saveVersNumb</returns>
public async Task<bool> RequestProcessingRemove(string doorId)
{
RedisKey currKey = new RedisKey(Constants.CALC_REQ_PROC);
bool fatto = await RedHashRemove(currKey, doorId);
return fatto;
}
/// <summary>
/// Upsert for single hash record
/// </summary>
/// <returns>Dictionary of DoorId, saveVersNumb</returns>
public async Task<long> RequestProcessingUpsert(string doorId, string vers)
{
RedisKey currKey = new RedisKey(Constants.CALC_REQ_PROC);
long numReq = await RedHashUpsert(currKey, doorId, vers);
return numReq;
}
/// <summary>
/// Reset to queue request all processing/processed data
/// </summary>
/// <returns>Dictionary of DoorId, saveVersNumb</returns>
public async Task<bool> ResetQueue()
{
bool fatto = false;
await Task.Delay(1);
Stopwatch stopWatch = new Stopwatch();
stopWatch.Start();
// cerco le richieste processing
RedisKey currKey = new RedisKey(Constants.CALC_REQ_PROC);
var rawData = await redisDb.HashGetAllAsync(currKey);
foreach (var item in rawData)
{
await RequestPendingUpsert(item.Name!, item.Value!);
await RequestProcessingRemove(item.Name!);
fatto = true;
}
// cerco le richieste con errori
currKey = new RedisKey(Constants.CALC_REQ_ERRS);
rawData = await redisDb.HashGetAllAsync(currKey);
foreach (var item in rawData)
{
await RequestPendingUpsert(item.Name!, item.Value!);
await RequestErrRemove(item.Name!);
fatto = true;
}
// cerco le richieste processed
currKey = new RedisKey(Constants.CALC_REQ_DONE);
rawData = await redisDb.HashGetAllAsync(currKey);
foreach (var item in rawData)
{
await RequestPendingUpsert(item.Name!, item.Value!);
await RequestDoneRemove(item.Name!);
fatto = true;
}
stopWatch.Stop();
TimeSpan ts = stopWatch.Elapsed;
Log.Debug($"ResetQueue | REDIS in: {ts.TotalMilliseconds} ms");
return fatto;
}
/// <summary>
/// Salvo elenco risultati elaborazioni (modalità boolean di esecuzione corretta)
/// </summary>
/// <param name="calcResults">Risultati elaborazioni in formato CalcResultDTO</param>
/// <returns></returns>
public async Task<bool> SaveProcessingResult(List<CalcResultDTO> calcResults)
{
bool answ = true;
await Task.Delay(1);
if (calcResults != null && calcResults.Count > 0)
{
string sDoorId = "";
string sCurrVers = "";
foreach (var calcTask in calcResults)
{
RedisKey currSvgKey = new RedisKey("");
var doorData = calcTask.DoorIdVers.Split(".");
sDoorId = doorData.Length > 0 ? doorData[0] : "";
sCurrVers = doorData.Length > 0 ? doorData[1] : "";
// se valido salvo SVG...
if (calcTask.Validated)
{
// salvo in area REDIS
currSvgKey = new RedisKey($"{Constants.CALC_REQ_SVG_CACHE}:{sDoorId}:{sCurrVers}");
await redisDb.StringSetAsync(currSvgKey, calcTask.SvgGen, DayLongCache);
// elimino dalle code proc/err
await RequestProcessingRemove(sDoorId);
await RequestErrRemove(sDoorId);
// metto in coda done
await RequestDoneUpsert(sDoorId, sCurrVers);
}
// altrimenti salvo errore e metto in coda errori
else
{
// salvo in area REDIS
currSvgKey = new RedisKey($"{Constants.CALC_REQ_ERRS}:{sDoorId}:{sCurrVers}");
await redisDb.StringSetAsync(currSvgKey, calcTask.ErrorMsg, DayLongCache);
// elimino dalle code proc/done
await RequestProcessingRemove(sDoorId);
await RequestDoneRemove(sDoorId);
// metto in coda err
await RequestErrUpsert(sDoorId, sCurrVers);
}
// invio il messaggio di ritorno...
CalcDonePipe.saveAndSendMessage(Constants.LAST_CALC_DONE_KEY, calcTask.DoorIdVers);
}
}
return answ;
}
/// <summary>
/// Invio richiesta di calcolo per la porta indicata, dato il suo DDF
/// </summary>
/// <param name="DoorId"></param>
/// <param name="FullDDF">Contenuto completo del DDF</param>
/// <returns>indice/versione del calcolo DDF</returns>
public async Task<int> SendCalcReq(int DoorId, string FullDDF)
{
int currVers = 1;
string sDoorId = $"{DoorId}";
string sCurrVers = "";
Stopwatch stopWatch = new Stopwatch();
stopWatch.Start();
// per prima cosa controllo se ho GIA' in coda qualcosa come richieste
long numPending = await NumRequestPending();
// se coda non vuota: cerco la DoorId corrente, se c'è sovrascrivo versione altrimenti
if (numPending != 0)
{
var currPending = await RequestPending();
if (currPending != null)
{
if (currPending.ContainsKey(sDoorId))
{
sCurrVers = currPending[sDoorId];
int.TryParse(sCurrVers, out currVers);
currVers++;
}
}
}
sCurrVers = $"{currVers}";
// inserisco in coda
numPending = await RequestPendingUpsert(sDoorId, sCurrVers);
// elimino da code errori
await RequestErrRemove(sDoorId);
// salvo nell'archivio REDIS delle porte il DDF corrente (key=doorId.versNumb), potrebbe
// venire buono anche x eventuale UNDO...
RedisKey currDdfKey = new RedisKey($"{Constants.CALC_REQ_DDF_CACHE}:{sDoorId}:{sCurrVers}");
await redisDb.StringSetAsync(currDdfKey, FullDDF, DayLongCache);
// invio sul canale dei messaggi il numero di items in coda attuali x chiedere esecuzione...
numPending = await NumRequestPending();
bool answ = CalcReqPipe.saveAndSendMessage(Constants.LAST_CALC_REQ_KEY, $"{numPending}");
stopWatch.Stop();
TimeSpan ts = stopWatch.Elapsed;
Log.Debug($"SendCalcReq | DoorId: {DoorId} enqueued in: {ts.TotalMilliseconds} ms");
return currVers;
}
/// <summary>
/// Get Queue request pending, removing from queue and putting on processing queue
/// </summary>
/// <returns>Dictionary of DoorId, saveVersNumb</returns>
public async Task<Dictionary<string, string>> TakeProcessingItems(int numItems)
{
int maxTake = Math.Min(10, numItems);
long numReq = 0;
Dictionary<string, string> dictResult = new Dictionary<string, string>();
// cerco da cache
RedisKey currKey = new RedisKey(Constants.CALC_REQ_PEND);
Stopwatch stopWatch = new Stopwatch();
stopWatch.Start();
// calcolo il totale delle richieste pending
numReq = redisDb.HashLength(currKey);
if (numReq > 0)
{
var rawData = await redisDb.HashGetAllAsync(currKey);
// sposto fino a concorrenza...
foreach (var item in rawData)
{
maxTake--;
// recupero il DDF...
RedisKey currDdfKey = new RedisKey($"{Constants.CALC_REQ_DDF_CACHE}:{item.Name}:{item.Value}");
var rawDDF = await redisDb.StringGetAsync(currDdfKey);
dictResult.Add($"{item.Name}.{item.Value}", $"{rawDDF}");
// sposto tra le 2 code
await RequestProcessingUpsert(item.Name!, item.Value!);
await RequestPendingRemove(item.Name!);
if (maxTake <= 0)
{
break;
}
}
}
stopWatch.Stop();
TimeSpan ts = stopWatch.Elapsed;
Log.Debug($"TakeProcessingItems | REDIS in: {ts.TotalMilliseconds} ms");
return dictResult;
}
#endregion Public Methods
#region Protected Fields
protected const string rKeyCalcOreFase = "Check:OreFasi";
protected const string rKeyFasiAct = "Check:FasiAct";
protected const string rKeyProjAct = "Check:ProjAct";
/// <summary>
/// TTL da 1 min x cache Redis
/// </summary>
protected const int shortTTL = 60 * 5;
protected int idxSim = 0;
protected Random rnd = new Random();
#endregion Protected Fields
#region Protected Methods
/// <summary>
/// Recupero chiave da redis
/// </summary>
/// <param name="rKey"></param>
/// <returns></returns>
protected async Task<string> getRSV(string rKey)
{
string answ = "";
var rawData = await redisDb.StringGetAsync(rKey);
if (rawData.HasValue)
{
answ = $"{rawData}";
}
return answ;
}
/// <summary>
/// Effettua upsert in HasList redis
/// </summary>
/// <param name="currKey">Chiave redis della Hashlist</param>
/// <param name="chiave">Chiave nella HashList</param>
/// <param name="valore">Valore da salvare</param>
/// <returns>Num record nella HashList</returns>
protected async Task<long> RedHashUpsert(RedisKey currKey, string chiave, string valore)
{
long numReq = 0;
Stopwatch stopWatch = new Stopwatch();
stopWatch.Start();
await redisDb.HashSetAsync(currKey, chiave, valore);
numReq = await redisDb.HashLengthAsync(currKey);
stopWatch.Stop();
TimeSpan ts = stopWatch.Elapsed;
Log.Trace($"RedHashUpsert | {currKey} | in: {ts.TotalMilliseconds} ms");
return numReq;
}
/// <summary>
/// Salvataggio chiave in redis
/// </summary>
/// <param name="rKey"></param>
/// <param name="rVal"></param>
/// <param name="ttlSec"></param>
/// <returns></returns>
protected async Task<bool> setRSV(string rKey, string rVal, int ttlSec)
{
bool fatto = false;
await redisDb.StringSetAsync(rKey, rVal, TimeSpan.FromSeconds(ttlSec));
fatto = true;
return fatto;
}
/// <summary>
/// Salvataggio chiave in redis
/// </summary>
/// <param name="rKey"></param>
/// <param name="rValInt"></param>
/// <param name="ttlSec"></param>
/// <returns></returns>
protected async Task<bool> setRSV(string rKey, int rValInt, int ttlSec)
{
bool fatto = false;
await redisDb.StringSetAsync(rKey, rValInt, TimeSpan.FromSeconds(ttlSec));
fatto = true;
return fatto;
}
/// <summary>
/// Registra in cache chiave se non fosse già in elenco
/// </summary>
/// <param name="newKey"></param>
protected void trackCache(string newKey)
{
if (!cachedDataList.Contains(newKey))
{
cachedDataList.Add(newKey);
}
}
#endregion Protected Methods
#region Private Fields
private static IConfiguration _configuration = null!;
private static JsonSerializerSettings? JSSettings;
private static Logger Log = LogManager.GetCurrentClassLogger();
private readonly IEmailSender _emailSender;
/// <summary>
/// Elenco obj in cache
/// </summary>
private List<string> cachedDataList = new List<string>();
/// <summary>
/// Durata cache lunga IN SECONDI
/// </summary>
private int cacheTtlLong = 60 * 5;
/// <summary>
/// Durata cache breve IN SECONDI
/// </summary>
private int cacheTtlShort = 60 * 1;
/// <summary>
/// Oggetto per connessione a REDIS
/// </summary>
private ConnectionMultiplexer redisConn = null!;
/// <summary>
/// Oggetto DB redis da impiegare x chiamate R/W
/// </summary>
private IDatabase redisDb = null!;
#endregion Private Fields
#region Private Properties
/// <summary>
/// Durata cache di 24h
/// </summary>
private TimeSpan DayLongCache
{
get => TimeSpan.FromHours(24);
}
/// <summary>
/// Durata cache lunga (+ perturbazione percentuale +/-10%)
/// </summary>
private TimeSpan FastCache
{
get => TimeSpan.FromSeconds(cacheTtlShort * rnd.Next(900, 1100) / 1000);
}
/// <summary>
/// Durata cache lunga (+ perturbazione percentuale +/-10%)
/// </summary>
private TimeSpan LongCache
{
get => TimeSpan.FromSeconds(cacheTtlLong * rnd.Next(900, 1100) / 1000);
}
/// <summary>
/// Durata cache lunga (+ perturbazione percentuale +/-10%)
/// </summary>
private TimeSpan UltraLongCache
{
get => TimeSpan.FromSeconds(cacheTtlLong * 10 * rnd.Next(900, 1100) / 1000);
}
#endregion Private Properties
#region Private Methods
/// <summary>
/// Esegue flush memoria redis dato pattern
/// </summary>
/// <param name="pattern"></param>
/// <returns></returns>
private async Task<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)
{
await redisDb.KeyDeleteAsync(item);
}
// brutalmente rimuovo intero contenuto DB... DANGER
//await server.FlushDatabaseAsync();
answ = true;
}
}
return answ;
}
#endregion Private Methods
}
}