1350 lines
50 KiB
C#
1350 lines
50 KiB
C#
using Core;
|
|
using Core.DTO;
|
|
using LiMan.DB.DBModels;
|
|
using LiMan.DB.DTO;
|
|
using Microsoft.AspNetCore.Identity.UI.Services;
|
|
using Microsoft.Extensions.Caching.Distributed;
|
|
using Microsoft.Extensions.Configuration;
|
|
using Microsoft.Extensions.Logging;
|
|
using Newtonsoft.Json;
|
|
using NLog;
|
|
using Org.BouncyCastle.Asn1.X500;
|
|
using StackExchange.Redis;
|
|
using StackExchange.Redis.Extensions.Core.Abstractions;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Diagnostics;
|
|
using System.Linq;
|
|
using System.Runtime;
|
|
using System.Threading.Tasks;
|
|
using static Core.Enum;
|
|
|
|
namespace LiMan.APi.Data
|
|
{
|
|
/// <summary>
|
|
/// Classe astrazione accesso dati
|
|
/// </summary>
|
|
public class ApiDataService : IDisposable
|
|
{
|
|
#region Public Fields
|
|
|
|
/// <summary>
|
|
/// Classe Accesso metodi DB
|
|
/// </summary>
|
|
public static DB.Controllers.DbController dbController;
|
|
|
|
#endregion Public Fields
|
|
|
|
#region Public Constructors
|
|
|
|
/// <summary>
|
|
/// Init classe
|
|
/// </summary>
|
|
/// <param name="configuration"></param>
|
|
/// <param name="logger"></param>
|
|
/// <param name="emailSender"></param>
|
|
/// <param name="redisCacheClient"></param>
|
|
public ApiDataService(IConfiguration configuration, ILogger<ApiDataService> logger, IEmailSender emailSender, IRedisCacheClient redisCacheClient, IConnectionMultiplexer redisConnMult)
|
|
//public ApiDataService(IConfiguration configuration, ILogger<ApiDataService> logger, IDistributedCache distributedCache, IEmailSender emailSender, IRedisCacheClient redisCacheClient)
|
|
{
|
|
_logger = logger;
|
|
_configuration = configuration;
|
|
_emailSender = emailSender;
|
|
_redisCacheClient = redisCacheClient;
|
|
//this.distributedCache = distributedCache;
|
|
|
|
// Conf cache
|
|
redisConn = redisConnMult;
|
|
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
|
|
};
|
|
|
|
// conf DB
|
|
string connStrDB = _configuration.GetConnectionString("LiMan.DB");
|
|
if (string.IsNullOrEmpty(connStrDB))
|
|
{
|
|
_logger.LogError("ConnString empty!");
|
|
}
|
|
else
|
|
{
|
|
dbController = new LiMan.DB.Controllers.DbController(configuration);
|
|
_logger.LogInformation("DbController OK");
|
|
}
|
|
}
|
|
|
|
#endregion Public Constructors
|
|
|
|
#region Public Methods
|
|
|
|
/// <summary> Elenco Applicativi (all) <returns></returns>
|
|
public async Task<List<ApplicativoModel>> ApplicativiGetAll()
|
|
{
|
|
List<ApplicativoModel> dbResult = new List<ApplicativoModel>();
|
|
Stopwatch stopWatch = new Stopwatch();
|
|
stopWatch.Start();
|
|
dbResult = dbController.GetApplicazioni();
|
|
stopWatch.Stop();
|
|
TimeSpan ts = stopWatch.Elapsed;
|
|
Log.Trace($"Effettuata lettura da DB per ApplicativiGetAll: {ts.TotalMilliseconds} ms");
|
|
|
|
return await Task.FromResult(dbResult);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Elenco licenze dato cliente
|
|
/// </summary>
|
|
/// <param name="CodInst">Codice Installaizone /Cliente</param>
|
|
/// <param name="CodApp">Codice Applicazione</param>
|
|
/// <param name="HideData">Indica se nascondere i dati sensibili</param>
|
|
/// <returns></returns>
|
|
public async Task<List<ApplicativoDTO>> ApplicativiSearch(string CodInst, string CodApp, bool HideData)
|
|
{
|
|
List<ApplicativoDTO> dbResult = new List<ApplicativoDTO>();
|
|
Stopwatch stopWatch = new Stopwatch();
|
|
stopWatch.Start();
|
|
dbResult = dbController.GetApplicativiFilt(true, CodApp, CodInst, HideData);
|
|
stopWatch.Stop();
|
|
TimeSpan ts = stopWatch.Elapsed;
|
|
Log.Trace($"Effettuata lettura da DB per ApplicativiByCliente: {ts.TotalMilliseconds} ms");
|
|
|
|
return await Task.FromResult(dbResult);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Aggiornameto/Inserimento record applicativo
|
|
/// </summary>
|
|
/// <param name="newRec">record Release</param>
|
|
/// <returns></returns>
|
|
public async Task<bool> ApplicativoUpsert(ApplicativoModel newRec)
|
|
{
|
|
await Task.Delay(1);
|
|
bool fatto = false;
|
|
Stopwatch stopWatch = new Stopwatch();
|
|
stopWatch.Start();
|
|
// inserisco
|
|
fatto = dbController.ApplicativoUpsert(newRec);
|
|
stopWatch.Stop();
|
|
TimeSpan ts = stopWatch.Elapsed;
|
|
Log.Trace($"Effettuato upsert su DB per ApplicativoUpsert | {newRec.CodApp} | {ts.TotalMilliseconds} ms");
|
|
return fatto;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Elenco licenze dato cliente
|
|
/// </summary>
|
|
/// <param name="Chiave">Licenza MASTER</param>
|
|
/// <param name="CodImpiego">Codice Impiego licenza</param>
|
|
/// <param name="HideData">Indica se nascondere i dati sensibili</param>
|
|
/// <returns></returns>
|
|
public async Task<AttivazioneDTO> AttivazioneSearch(string Chiave, string CodImpiego, bool HideData)
|
|
{
|
|
AttivazioneDTO dbResult = new AttivazioneDTO();
|
|
|
|
Stopwatch stopWatch = new Stopwatch();
|
|
stopWatch.Start();
|
|
|
|
dbResult = dbController.GetAttivazione(Chiave, CodImpiego, HideData);
|
|
stopWatch.Stop();
|
|
TimeSpan ts = stopWatch.Elapsed;
|
|
Log.Trace($"Effettuata lettura da DB per AttivazioniSearch: {ts.TotalMilliseconds} ms");
|
|
|
|
return await Task.FromResult(dbResult);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Elenco Attivaizoni da ID Licenza master
|
|
/// </summary>
|
|
/// <param name="idxLic">Idx Licenza Master</param>
|
|
/// <param name="hideData">Indica se nascondere i dati sensibili</param>
|
|
/// <returns></returns>
|
|
public async Task<List<AttivazioneDTO>> AttivazioniByLic(int idxLic, bool hideData)
|
|
{
|
|
List<AttivazioneDTO> dbResult = new List<AttivazioneDTO>();
|
|
string cacheKey = $"{rKeyAttivByLic}:{hideData}:{idxLic}";
|
|
trackCache(cacheKey);
|
|
string rawData = await getRSV(cacheKey);
|
|
if (!string.IsNullOrEmpty(rawData))
|
|
{
|
|
dbResult = JsonConvert.DeserializeObject<List<AttivazioneDTO>>(rawData);
|
|
}
|
|
else
|
|
{
|
|
Stopwatch stopWatch = new Stopwatch();
|
|
stopWatch.Start();
|
|
dbResult = dbController.GetAttivazioniByLic(idxLic, hideData);
|
|
rawData = JsonConvert.SerializeObject(dbResult);
|
|
await setRSV(cacheKey, rawData, redCacheTtlStd);
|
|
stopWatch.Stop();
|
|
TimeSpan ts = stopWatch.Elapsed;
|
|
Log.Trace($"Effettuata lettura da DB per AttivazioniByLic: {ts.TotalMilliseconds} ms");
|
|
}
|
|
|
|
return await Task.FromResult(dbResult);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Elenco Attivaizoni da valore Licenza master
|
|
/// </summary>
|
|
/// <param name="MasterKey">Licenza Master</param>
|
|
/// <param name="HideData">Indica se nascondere i dati sensibili</param>
|
|
/// <returns></returns>
|
|
public async Task<List<AttivazioneDTO>> AttivazioniByMasterKey(string MasterKey, bool HideData)
|
|
{
|
|
List<AttivazioneDTO> dbResult = new List<AttivazioneDTO>();
|
|
|
|
Stopwatch stopWatch = new Stopwatch();
|
|
stopWatch.Start();
|
|
LicenzaModel licenza = await LicenzaByMasterKey(MasterKey);
|
|
if (licenza != null)
|
|
{
|
|
dbResult = await AttivazioniByLic(licenza.IdxLic, HideData);
|
|
}
|
|
stopWatch.Stop();
|
|
TimeSpan ts = stopWatch.Elapsed;
|
|
Log.Trace($"Effettuata lettura da DB per AttivazioniByMasterKey: {ts.TotalMilliseconds} ms");
|
|
|
|
return await Task.FromResult(dbResult);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Elimina un Attivaizone
|
|
/// </summary>
|
|
/// <param name="MasterKey">Licenza Master</param>
|
|
/// <param name="ParamDict">Elenco delle attivazioni da eliminare</param>
|
|
/// <returns></returns>
|
|
public async Task<bool> AttivazioniDelete(string MasterKey, Dictionary<string, string> ParamDict)
|
|
{
|
|
bool answ = false;
|
|
|
|
Stopwatch stopWatch = new Stopwatch();
|
|
stopWatch.Start();
|
|
LicenzaModel licenza = await LicenzaByMasterKey(MasterKey);
|
|
if (licenza != null)
|
|
{
|
|
answ = dbController.AttivazioniDelete(ParamDict, MasterKey);
|
|
await InvalidateAllCache();
|
|
}
|
|
stopWatch.Stop();
|
|
TimeSpan ts = stopWatch.Elapsed;
|
|
Log.Trace($"Effettuata lettura da DB per AttivazioniDelete: {ts.TotalMilliseconds} ms");
|
|
|
|
return await Task.FromResult(answ);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Elimina attivaizoni con veto scaduto
|
|
/// </summary>
|
|
/// <param name="MasterKey">Licenza Master</param>
|
|
/// <returns></returns>
|
|
public async Task<bool> AttivazioniResetAvail(string MasterKey)
|
|
{
|
|
bool answ = false;
|
|
|
|
Stopwatch stopWatch = new Stopwatch();
|
|
stopWatch.Start();
|
|
LicenzaModel licenza = await LicenzaByMasterKey(MasterKey);
|
|
|
|
if (licenza != null)
|
|
{
|
|
answ = dbController.AttivazioniResetAvail(MasterKey);
|
|
await InvalidateAllCache();
|
|
}
|
|
stopWatch.Stop();
|
|
TimeSpan ts = stopWatch.Elapsed;
|
|
Log.Trace($"Effettuata lettura da DB per AttivazioniResetAvail: {ts.TotalMilliseconds} ms");
|
|
|
|
return await Task.FromResult(answ);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Effettua registrazione (se possibile) delle licenze indicate dall'elenco codici di
|
|
/// impiego indicati
|
|
/// </summary>
|
|
/// <param name="MasterKey">Codice Licenza Master</param>
|
|
/// <param name="ParamDict">Elenco codici impiego (key) + valori in formato dizionari</param>
|
|
/// <param name="DayVeto">Numero giorni x scadenza veto modifica</param>
|
|
/// <param name="TipoLic">Tipo di licenza da registrare</param>
|
|
/// <returns></returns>
|
|
/// <exception cref="NotImplementedException"></exception>
|
|
public async Task<bool> AttivazioniTryAdd(string MasterKey, Dictionary<string, string> ParamDict, int DayVeto, TipoLicenza TipoLic)
|
|
{
|
|
bool taskDone = false;
|
|
|
|
Stopwatch stopWatch = new Stopwatch();
|
|
stopWatch.Start();
|
|
|
|
taskDone = dbController.AttivazioniTryAdd(MasterKey, ParamDict, DayVeto, TipoLic);
|
|
await InvalidateAllCache();
|
|
stopWatch.Stop();
|
|
TimeSpan ts = stopWatch.Elapsed;
|
|
Log.Trace($"Effettuata scrittura + rilettura da DB per AttivazioniTryAdd: {ts.TotalMilliseconds} ms");
|
|
|
|
return await Task.FromResult(taskDone);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Effettua update (se possibile) delle licenze indicate dall'elenco codici di impiego indicati
|
|
/// </summary>
|
|
/// <param name="MasterKey">Codice Licenza Master</param>
|
|
/// <param name="ParamDict">Elenco codici impiego (key) + valori in formato dizionari</param>
|
|
/// <returns></returns>
|
|
/// <exception cref="NotImplementedException"></exception>
|
|
public async Task<bool> AttivazioniTryRefresh(string MasterKey, Dictionary<string, string> ParamDict)
|
|
{
|
|
bool taskDone = false;
|
|
|
|
Stopwatch sw = new Stopwatch();
|
|
sw.Start();
|
|
|
|
taskDone = dbController.AttivazioniTryRefresh(MasterKey, ParamDict);
|
|
await InvalidateAllCache();
|
|
sw.Stop();
|
|
TimeSpan ts = sw.Elapsed;
|
|
Log.Trace($"Effettuata scrittura + rilettura da DB per AttivazioniTryRefresh: {ts.TotalMilliseconds} ms");
|
|
|
|
return await Task.FromResult(taskDone);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Dispose classe
|
|
/// </summary>
|
|
public void Dispose()
|
|
{
|
|
// Clear database controller
|
|
dbController.Dispose();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Crea record richiesta enroll (univoco rispetto richieste correnti)
|
|
/// </summary>
|
|
/// <param name="MachineInfo">Dati da associare alla richeista</param>
|
|
/// <returns></returns>
|
|
public async Task<EnrollRequestModel> EnrollReqCreate(Dictionary<string, string> MachineInfo)
|
|
{
|
|
Stopwatch sw = new Stopwatch();
|
|
sw.Start();
|
|
// svuoto elenco richieste scaduteù
|
|
var cleanDone = await EnrollReqPurgeInvalid();
|
|
// prendo elenco attive x evitare duplicazioni codici TOTP...
|
|
var resList = await EnrollReqGetActive();
|
|
int totpCode = rnd.Next(1, 100000000);
|
|
// verifico che non sia preesistente...
|
|
if (resList.Count > 0)
|
|
{
|
|
// cerco se fosse già presente...
|
|
while (resList.Where(x => x.Passcode == totpCode).Any())
|
|
{
|
|
// genero nuovo...
|
|
await Task.Delay(rnd.Next(50));
|
|
totpCode = rnd.Next(1, 100000000);
|
|
}
|
|
}
|
|
|
|
// serializzo i dati della richiesta..
|
|
string reqPayload = JsonConvert.SerializeObject(MachineInfo);
|
|
|
|
// preparo il record da registrare...
|
|
EnrollRequestModel newReq = new EnrollRequestModel()
|
|
{
|
|
DtReq = DateTime.Now,
|
|
Passcode = totpCode,
|
|
ReqPayload = reqPayload
|
|
};
|
|
|
|
var dbRec = await EnrollReqUpsert(newReq);
|
|
sw.Stop();
|
|
TimeSpan ts = sw.Elapsed;
|
|
Log.Trace($"Effettuata EnrollReqCreate: {ts.TotalMilliseconds} ms");
|
|
|
|
// restituisce elenco
|
|
return dbRec;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Elimino una richiesta enroll (anche se già approvata...)
|
|
/// </summary>
|
|
/// <param name="idReq">ID record</param>
|
|
public async Task<bool> EnrollReqDelete(int idReq)
|
|
{
|
|
bool fatto = false;
|
|
// inserimento!
|
|
Stopwatch sw = new Stopwatch();
|
|
sw.Start();
|
|
fatto = dbController.EnrollReqDelete(idReq);
|
|
// svuota eventuale cache redis...
|
|
await FlushRedisCachePattern("Enroll");
|
|
sw.Stop();
|
|
TimeSpan ts = sw.Elapsed;
|
|
Log.Trace($"Effettuata EnrollReqDelete: {ts.TotalMilliseconds} ms");
|
|
return fatto;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Recupera una richiesta dato suo ID x verificare approvazione e dati associati...
|
|
/// </summary>
|
|
/// <param name="idReq">ID record</param>
|
|
public async Task<EnrollRequestModel> EnrollReqGetById(int idReq)
|
|
{
|
|
string source = "DB";
|
|
EnrollRequestModel dbResult = new EnrollRequestModel();
|
|
try
|
|
{
|
|
string currKey = $"{Const.rKeyConfig}:Enroll:ById:{idReq}";
|
|
Stopwatch sw = new Stopwatch();
|
|
sw.Start();
|
|
string? rawData = await redisDb.StringGetAsync(currKey);
|
|
if (!string.IsNullOrEmpty(rawData))
|
|
{
|
|
source = "REDIS";
|
|
var tempResult = JsonConvert.DeserializeObject<EnrollRequestModel>(rawData);
|
|
if (tempResult == null)
|
|
{
|
|
dbResult = new EnrollRequestModel();
|
|
}
|
|
else
|
|
{
|
|
dbResult = tempResult;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
dbResult = dbController.EnrollReqGetById(idReq);
|
|
rawData = JsonConvert.SerializeObject(dbResult, JSSettings);
|
|
await redisDb.StringSetAsync(currKey, rawData, FastCache);
|
|
}
|
|
if (dbResult == null)
|
|
{
|
|
dbResult = new EnrollRequestModel();
|
|
}
|
|
sw.Stop();
|
|
TimeSpan ts = sw.Elapsed;
|
|
Log.Debug($"EnrollReqGetById | {source} in: {ts.TotalMilliseconds} ms");
|
|
}
|
|
catch (Exception exc)
|
|
{
|
|
Log.Error($"Error during EnrollReqGetById:{Environment.NewLine}{exc}");
|
|
}
|
|
return dbResult;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Elenco richeiste enroll attive al momento
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
public async Task<List<EnrollRequestModel>> EnrollReqGetActive()
|
|
{
|
|
string source = "DB";
|
|
List<EnrollRequestModel> dbResult = new List<EnrollRequestModel>();
|
|
try
|
|
{
|
|
string currKey = $"{Const.rKeyConfig}:Enroll:ActiveList";
|
|
Stopwatch sw = new Stopwatch();
|
|
sw.Start();
|
|
string? rawData = await redisDb.StringGetAsync(currKey);
|
|
if (!string.IsNullOrEmpty(rawData))
|
|
{
|
|
source = "REDIS";
|
|
var tempResult = JsonConvert.DeserializeObject<List<EnrollRequestModel>>(rawData);
|
|
if (tempResult == null)
|
|
{
|
|
dbResult = new List<EnrollRequestModel>();
|
|
}
|
|
else
|
|
{
|
|
dbResult = tempResult;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
dbResult = dbController.EnrollReqGetActive();
|
|
rawData = JsonConvert.SerializeObject(dbResult, JSSettings);
|
|
await redisDb.StringSetAsync(currKey, rawData, LongCache);
|
|
}
|
|
if (dbResult == null)
|
|
{
|
|
dbResult = new List<EnrollRequestModel>();
|
|
}
|
|
sw.Stop();
|
|
TimeSpan ts = sw.Elapsed;
|
|
Log.Debug($"EnrollReqGetActive | {source} in: {ts.TotalMilliseconds} ms");
|
|
}
|
|
catch (Exception exc)
|
|
{
|
|
Log.Error($"Error during EnrollReqGetActive:{Environment.NewLine}{exc}");
|
|
}
|
|
return dbResult;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Elimino eventuali richieste non approvate e scadute
|
|
/// </summary>
|
|
public async Task<bool> EnrollReqPurgeInvalid()
|
|
{
|
|
var reqPurged = dbController.EnrollReqPurgeInvalid();
|
|
// svuota eventuale cache redis...
|
|
await FlushRedisCachePattern("Enroll");
|
|
return await Task.FromResult(reqPurged);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Upsert record richiesta enroll
|
|
/// </summary>
|
|
/// <param name="newRec"></param>
|
|
/// <returns></returns>
|
|
public async Task<EnrollRequestModel> EnrollReqUpsert(EnrollRequestModel newRec)
|
|
{
|
|
int recId = 0;
|
|
// inserimento!
|
|
Stopwatch sw = new Stopwatch();
|
|
sw.Start();
|
|
recId = dbController.EnrollReqUpsert(newRec);
|
|
await FlushRedisCachePattern("Enroll");
|
|
var dbResult = await EnrollReqGetById(recId);
|
|
// svuota eventuale cache redis...
|
|
sw.Stop();
|
|
TimeSpan ts = sw.Elapsed;
|
|
Log.Trace($"Effettuata EnrollReqUpsert: {ts.TotalMilliseconds} ms");
|
|
// restituisce risultato
|
|
return dbResult;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Esegue aggiunta file dato ticket e list uploadResult
|
|
/// </summary>
|
|
/// <param name="idxTicket">Identificativo del ticket</param>
|
|
/// <param name="baseDir">Directory di salvataggio dei file</param>
|
|
/// <param name="fileUploaded">lista risultati della funzione di upload</param>
|
|
/// <returns></returns>
|
|
public async Task<bool> FileAdd(int idxTicket, string baseDir, List<UploadResult> fileUploaded)
|
|
{
|
|
bool fatto = false;
|
|
// inserimento!
|
|
Stopwatch sw = new Stopwatch();
|
|
sw.Start();
|
|
fatto = dbController.FileAdd(idxTicket, baseDir, fileUploaded);
|
|
sw.Stop();
|
|
TimeSpan ts = sw.Elapsed;
|
|
Log.Trace($"Effettuata inserimento con FileAdd: {ts.TotalMilliseconds} ms");
|
|
|
|
// restituisce elenco
|
|
return await Task.FromResult(fatto);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Elenco file registrati dato ticket id
|
|
/// </summary>
|
|
/// <param name="idxTicket">Identificativo del ticket</param>
|
|
/// <returns></returns>
|
|
public async Task<List<FileAttachModel>> FileGetFilt(int idxTicket)
|
|
{
|
|
List<FileAttachModel> dbResult = new List<FileAttachModel>();
|
|
Stopwatch stopWatch = new Stopwatch();
|
|
stopWatch.Start();
|
|
dbResult = dbController.FileGetFilt(idxTicket);
|
|
stopWatch.Stop();
|
|
TimeSpan ts = stopWatch.Elapsed;
|
|
Log.Trace($"Effettuata lettura da DB per FileGetFilt: {ts.TotalMilliseconds} ms");
|
|
return await Task.FromResult(dbResult);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Refresh globale cache Redis
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
public async Task<bool> FlushRedisCache()
|
|
{
|
|
Stopwatch stopWatch = new Stopwatch();
|
|
stopWatch.Start();
|
|
await Task.Delay(1);
|
|
RedisValue pattern = new RedisValue($"{Const.rKeyConfig}:*");
|
|
bool answ = await ExecFlushRedisPattern(pattern);
|
|
stopWatch.Stop();
|
|
Log.Debug($"FlushRedisCache in {stopWatch.Elapsed.TotalMilliseconds} ms");
|
|
return answ;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Refresh cache Redis dato redPattern
|
|
/// </summary>
|
|
/// <param name="pattern">Pattern da eliminare</param>
|
|
/// <returns></returns>
|
|
public async Task<bool> FlushRedisCachePattern(string pattern)
|
|
{
|
|
Stopwatch sw = new Stopwatch();
|
|
sw.Start();
|
|
await Task.Delay(1);
|
|
RedisValue redPattern = new RedisValue($"{Const.rKeyConfig}:{pattern}*");
|
|
bool answ = await ExecFlushRedisPattern(redPattern);
|
|
sw.Stop();
|
|
Log.Debug($"FlushRedisCachePattern in {sw.Elapsed.TotalMilliseconds} ms");
|
|
return answ;
|
|
}
|
|
|
|
/// <summary>
|
|
/// invalida tutta la cache in caso di update
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
public async Task InvalidateAllCache()
|
|
{
|
|
foreach (var item in cachedDataList)
|
|
{
|
|
await _redisCacheClient.GetDbFromConfiguration().RemoveAsync(item);
|
|
}
|
|
cachedDataList = new List<string>();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Elenco licenze dato cliente
|
|
/// </summary>
|
|
/// <param name="chiave">Chiave Licenza x ricerca</param>
|
|
/// <returns></returns>
|
|
public async Task<LicenzaModel> LicenzaByMasterKey(string chiave)
|
|
{
|
|
LicenzaModel dbResult = new LicenzaModel();
|
|
string cacheKey = $"{rKeyLicByMKey}:{chiave}";
|
|
trackCache(cacheKey);
|
|
string rawData = await getRSV(cacheKey);
|
|
if (!string.IsNullOrEmpty(rawData))
|
|
{
|
|
dbResult = JsonConvert.DeserializeObject<LicenzaModel>(rawData);
|
|
}
|
|
else
|
|
{
|
|
Stopwatch stopWatch = new Stopwatch();
|
|
stopWatch.Start();
|
|
dbResult = dbController.LicenzaByKey(chiave);
|
|
if (dbResult != null)
|
|
{
|
|
rawData = JsonConvert.SerializeObject(dbResult);
|
|
await setRSV(cacheKey, rawData, hourTTL);
|
|
}
|
|
stopWatch.Stop();
|
|
TimeSpan ts = stopWatch.Elapsed;
|
|
Log.Trace($"Effettuata lettura da DB per LicenzaByMasterKey: {ts.TotalMilliseconds} ms");
|
|
}
|
|
|
|
return await Task.FromResult(dbResult);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Effettua refresh del payload della licenza dato info + enigma generato dal client
|
|
/// </summary>
|
|
/// <param name="appInfo"></param>
|
|
/// <returns></returns>
|
|
public async Task<ApplicativoDTO> LicenzaRefreshPayload(LicenseCoord appInfo)
|
|
{
|
|
// chiamo metodo x ricalcolare payload dato enigma
|
|
bool done = await dbController.LicenseUpdatePayload(appInfo.CodInst, appInfo.CodApp, appInfo.MasterKey, appInfo.Enigma);
|
|
await InvalidateAllCache();
|
|
// ora recupero i dati
|
|
var licList = await LicenzeSearch(appInfo.CodInst, appInfo.CodApp, appInfo.MasterKey, false);
|
|
return licList.FirstOrDefault();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Elenco licenze dato cliente
|
|
/// </summary>
|
|
/// <param name="cliente"></param>
|
|
/// <returns></returns>
|
|
public async Task<List<LicenzaModel>> LicenzeByCliente(string cliente)
|
|
{
|
|
List<LicenzaModel> dbResult = new List<LicenzaModel>();
|
|
Stopwatch stopWatch = new Stopwatch();
|
|
stopWatch.Start();
|
|
|
|
dbResult = dbController.GetLicenzeFilt(true, "", cliente);
|
|
stopWatch.Stop();
|
|
TimeSpan ts = stopWatch.Elapsed;
|
|
Log.Trace($"Effettuata lettura da DB per LicenzeByCliente: {ts.TotalMilliseconds} ms");
|
|
|
|
return await Task.FromResult(dbResult);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Elenco licenze x data scadenza
|
|
/// </summary>
|
|
/// <param name="minDate">Data minima di scadenza</param>
|
|
/// <param name="maxDate">Data massima di scadenza</param>
|
|
/// <returns></returns>
|
|
public async Task<List<ApplicativoDTO>> LicenzeExpiring(DateTime minDate, DateTime maxDate)
|
|
{
|
|
List<ApplicativoDTO> dbResult = new List<ApplicativoDTO>();
|
|
Stopwatch stopWatch = new Stopwatch();
|
|
stopWatch.Start();
|
|
|
|
dbResult = dbController.GetApplicativiExpiring(minDate, maxDate).ToList();
|
|
stopWatch.Stop();
|
|
TimeSpan ts = stopWatch.Elapsed;
|
|
Log.Trace($"Effettuata lettura da DB per LicenzeExpiring: {ts.TotalMilliseconds} ms");
|
|
|
|
return await Task.FromResult(dbResult);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Elenco licenze dato cliente
|
|
/// </summary>
|
|
/// <param name="CodInst">Codice Installaizone /Cliente</param>
|
|
/// <param name="CodApp">Codice Applicazione</param>
|
|
/// <param name="Chiave">Chiave Licenza da validare</param>
|
|
/// <param name="HideData">Indica se nascondere i dati sensibili</param>
|
|
/// <returns></returns>
|
|
public async Task<List<ApplicativoDTO>> LicenzeSearch(string CodInst, string CodApp, string Chiave, bool HideData)
|
|
{
|
|
List<ApplicativoDTO> dbResult = new List<ApplicativoDTO>();
|
|
Stopwatch stopWatch = new Stopwatch();
|
|
stopWatch.Start();
|
|
|
|
dbResult = dbController.GetApplicativiFilt(true, CodApp, CodInst, HideData).Where(x => x.Chiave == Chiave).ToList();
|
|
stopWatch.Stop();
|
|
TimeSpan ts = stopWatch.Elapsed;
|
|
Log.Trace($"Effettuata lettura da DB per ApplicativiByCliente: {ts.TotalMilliseconds} ms");
|
|
|
|
return await Task.FromResult(dbResult);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Effettua registrazione chiamata verificando se vada messa sul DB o in redis...
|
|
/// </summary>
|
|
/// <param name="codInst"></param>
|
|
/// <param name="codApp"></param>
|
|
/// <param name="targetUrl"></param>
|
|
public async Task<bool> recordCall(string codInst, string codApp, string targetUrl)
|
|
{
|
|
bool fatto = false;
|
|
|
|
// in primis recupero statistiche (e nel mentre eventualmente salvo su DB)
|
|
SampleStats currStats = await getCurrStats();
|
|
|
|
// preparo chiave x dato da loggare
|
|
string currKey = $"{rKeySampleVars}:{codInst}:{codApp}:{targetUrl}";
|
|
|
|
// verifico presenza contatore corrente altrimenti aggiungo e salvo...
|
|
if (!currStats.VList.Contains(currKey))
|
|
{
|
|
currStats.VList.Add(currKey);
|
|
// salvo!
|
|
await setCurrStats(currStats);
|
|
}
|
|
// incremento valore contatore corrente
|
|
await redCountIncr(currKey);
|
|
|
|
return fatto;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Effettua registrazione da codice chiave...
|
|
/// </summary>
|
|
/// <param name="chiave"></param>
|
|
/// <param name="targetUrl"></param>
|
|
public async Task<bool> recordCall(string chiave, string targetUrl)
|
|
{
|
|
// valutare se cache key --> lic...
|
|
var currLic = await LicenzaByMasterKey(chiave);
|
|
var fatto = await recordCall(currLic.CodInst, currLic.CodApp, targetUrl);
|
|
return fatto;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Elenco Release dato Applicativo
|
|
/// </summary>
|
|
/// <param name="CodApp">Codice Applicazione</param>
|
|
/// <returns></returns>
|
|
public async Task<List<ReleaseDTO>> ReleaseGetByApp(string CodApp)
|
|
{
|
|
await Task.Delay(1);
|
|
List<ReleaseDTO> dbResult = new List<ReleaseDTO>();
|
|
Stopwatch stopWatch = new Stopwatch();
|
|
stopWatch.Start();
|
|
dbResult = dbController.ReleaseDtoGetByApp(CodApp);
|
|
stopWatch.Stop();
|
|
TimeSpan ts = stopWatch.Elapsed;
|
|
Log.Trace($"Effettuata lettura da DB per ReleaseDtoGetByApp | {CodApp} | {ts.TotalMilliseconds} ms");
|
|
return dbResult;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Elenco Release dato Applicativo + versione minima
|
|
/// </summary>
|
|
/// <param name="CodApp">Codice Applicazione</param>
|
|
/// <param name="VersMin">Versione minima richiesta</param>
|
|
/// <returns></returns>
|
|
public async Task<List<ReleaseDTO>> ReleaseGetByAppVers(string CodApp, string VersMin)
|
|
{
|
|
await Task.Delay(1);
|
|
List<ReleaseDTO> dbResult = new List<ReleaseDTO>();
|
|
Stopwatch stopWatch = new Stopwatch();
|
|
stopWatch.Start();
|
|
dbResult = dbController.ReleaseDtoGetByAppVers(CodApp, VersMin);
|
|
stopWatch.Stop();
|
|
TimeSpan ts = stopWatch.Elapsed;
|
|
Log.Trace($"Effettuata lettura da DB per ReleaseDtoGetByAppVers | {CodApp} | vers >= {VersMin} | {ts.TotalMilliseconds} ms");
|
|
return dbResult;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Elenco Release dato Applicativo + versione minima
|
|
/// </summary>
|
|
/// <param name="CodApp">Codice Applicazione</param>
|
|
/// <param name="VersMin">Versione minima richiesta</param>
|
|
/// <param name="VersMax">Versione massima consentita</param>
|
|
/// <returns></returns>
|
|
public async Task<List<ReleaseDTO>> ReleaseGetByAppVersLimit(string CodApp, string VersMin, string VersMax)
|
|
{
|
|
await Task.Delay(1);
|
|
List<ReleaseDTO> dbResult = new List<ReleaseDTO>();
|
|
Stopwatch stopWatch = new Stopwatch();
|
|
stopWatch.Start();
|
|
dbResult = dbController.ReleaseDtoGetByAppVersLimit(CodApp, VersMin, VersMax);
|
|
stopWatch.Stop();
|
|
TimeSpan ts = stopWatch.Elapsed;
|
|
Log.Trace($"Effettuata lettura da DB per ReleaseDtoGetByAppVersLimit | {CodApp} | vers >= {VersMin} | {ts.TotalMilliseconds} ms");
|
|
return dbResult;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Elenco di TUTTE le release CRITICAL come dizionario CodApp - release
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
public async Task<Dictionary<string, ReleaseDTO>> ReleaseGetCritical()
|
|
{
|
|
Dictionary<string, ReleaseDTO> dbResult = new Dictionary<string, ReleaseDTO>();
|
|
Stopwatch sw = new Stopwatch();
|
|
sw.Start();
|
|
string cacheKey = $"{rKeyAttivByLic}:AppReleases:CRITICAL";
|
|
string source = "REDIS";
|
|
trackCache(cacheKey);
|
|
string rawData = await getRSV(cacheKey);
|
|
if (!string.IsNullOrEmpty(rawData))
|
|
{
|
|
dbResult = JsonConvert.DeserializeObject<Dictionary<string, ReleaseDTO>>(rawData);
|
|
}
|
|
else
|
|
{
|
|
source = "DB";
|
|
dbResult = dbController.ReleaseGetCritical();
|
|
rawData = JsonConvert.SerializeObject(dbResult);
|
|
await setRSV(cacheKey, rawData, redCacheTtlFast);
|
|
}
|
|
sw.Stop();
|
|
Log.Trace($"Effettuata lettura da DB per ReleaseGetCritical | {source} | # found: {dbResult.Count} | {sw.ElapsedMilliseconds} ms");
|
|
return dbResult;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Aggiornameto/Inserimento record release
|
|
/// </summary>
|
|
/// <param name="newRec">record Release</param>
|
|
/// <returns></returns>
|
|
public async Task<bool> ReleaseUpsert(ReleaseModel newRec)
|
|
{
|
|
await Task.Delay(1);
|
|
bool fatto = false;
|
|
Stopwatch stopWatch = new Stopwatch();
|
|
stopWatch.Start();
|
|
// inserisco
|
|
fatto = await dbController.ReleaseUpsert(newRec);
|
|
await InvalidateAllCache();
|
|
await FlushRedisCache();
|
|
stopWatch.Stop();
|
|
TimeSpan ts = stopWatch.Elapsed;
|
|
Log.Trace($"Effettuato upsert su DB per ReleaseUpsert | {newRec.CodApp} | {newRec.VersNum} | {ts.TotalMilliseconds} ms");
|
|
return fatto;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Registro su DB le statistiche delle chiavi in elenco, resettando i vari contatori quando fatto
|
|
/// </summary>
|
|
/// <param name="keyList">Elenco key nel formato {rKeySampleVars}:{codInst}:{codApp}:{targetUrl}</param>
|
|
public async Task<bool> saveStatsToDb(List<string> keyList)
|
|
{
|
|
bool fatto = false;
|
|
// ciclo x eseguire 1:1
|
|
foreach (var item in keyList)
|
|
{
|
|
// recupero counter...
|
|
var currCount = await redCount(item);
|
|
// scompongo key... senza url di base
|
|
string[] valStr = item.Replace($"{rKeySampleVars}:", "").Split(":");
|
|
if (valStr.Length > 2)
|
|
{
|
|
LogCallModel newRec = new LogCallModel()
|
|
{
|
|
CodInst = valStr[0],
|
|
CodApp = valStr[1],
|
|
TargetUrl = item.Replace($"{rKeySampleVars}:", "").Replace($"{valStr[0]}:{valStr[1]}:", ""),
|
|
DataRif = DateTime.Now,
|
|
NumCall = currCount
|
|
};
|
|
fatto = await dbController.LogCallUpsert(newRec);
|
|
if (fatto)
|
|
{
|
|
await redCountClear(item);
|
|
}
|
|
}
|
|
}
|
|
return fatto;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Invio email richiesta
|
|
/// </summary>
|
|
/// <param name="destEmail"></param>
|
|
/// <param name="oggetto"></param>
|
|
/// <param name="corpo"></param>
|
|
/// <returns></returns>
|
|
public async Task<bool> SendEmail(string destEmail, string oggetto, string corpo)
|
|
{
|
|
bool answ = false;
|
|
try
|
|
{
|
|
await _emailSender.SendEmailAsync(destEmail, oggetto, corpo);
|
|
answ = true;
|
|
}
|
|
catch
|
|
{ }
|
|
|
|
return answ;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Statistiche del LOG chiamate all'API dato filtro
|
|
/// </summary>
|
|
/// <param name="DateFrom">Data minima</param>
|
|
/// <param name="DateTo">DataMax</param>
|
|
/// <param name="SearchVal">Valore cercato, se "" è tutti</param>
|
|
/// <returns></returns>
|
|
public async Task<List<StatsCallModel>> StatsLogCallGetFilt(DateTime DateFrom, DateTime DateTo, string SearchVal = "")
|
|
{
|
|
List<StatsCallModel> dbResult = new List<StatsCallModel>();
|
|
string cacheKey = $"{rKeyStatslogCall}:{DateFrom:yyyyMMdd}:{DateTo:yyyyMMdd}";
|
|
if (!string.IsNullOrEmpty(SearchVal))
|
|
{
|
|
cacheKey += $":{SearchVal}";
|
|
}
|
|
trackCache(cacheKey);
|
|
string rawData = await getRSV(cacheKey);
|
|
if (!string.IsNullOrEmpty(rawData))
|
|
{
|
|
dbResult = JsonConvert.DeserializeObject<List<StatsCallModel>>(rawData);
|
|
}
|
|
else
|
|
{
|
|
Stopwatch stopWatch = new Stopwatch();
|
|
stopWatch.Start();
|
|
var rawResult = dbController.StatsLogCallGetFilt(DateFrom, DateTo, SearchVal);
|
|
dbResult = rawResult
|
|
.OrderByDescending(x => x.YearRef)
|
|
.ThenByDescending(x => x.TotCall)
|
|
.ToList();
|
|
if (dbResult != null)
|
|
{
|
|
rawData = JsonConvert.SerializeObject(dbResult);
|
|
await setRSV(cacheKey, rawData, redCacheTtlStd);
|
|
}
|
|
stopWatch.Stop();
|
|
TimeSpan ts = stopWatch.Elapsed;
|
|
Log.Trace($"Effettuata lettura da DB per StatsLogCallGetFilt: {ts.TotalMilliseconds} ms");
|
|
}
|
|
return await Task.FromResult(dbResult);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Esegue aggiunta Ticket richiesto + restitusice aperti x cliente
|
|
/// </summary>
|
|
/// <param name="currRequest"></param>
|
|
/// <returns></returns>
|
|
/// <exception cref="NotImplementedException"></exception>
|
|
public async Task<bool> TicketAdd(SupportRequest currRequest)
|
|
{
|
|
bool fatto = false;
|
|
// inserimento!
|
|
Stopwatch stopWatch = new Stopwatch();
|
|
stopWatch.Start();
|
|
fatto = dbController.TicketAddNew(currRequest);
|
|
stopWatch.Stop();
|
|
TimeSpan ts = stopWatch.Elapsed;
|
|
Log.Trace($"Effettuata inserimento con TicketAdd: {ts.TotalMilliseconds} ms");
|
|
|
|
// restituisce elenco
|
|
return await Task.FromResult(fatto);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Elenco ticket dato cliente + App + MasterKey
|
|
/// </summary>
|
|
/// <param name="CodInst"></param>
|
|
/// <param name="CodApp"></param>
|
|
/// <param name="MasterKey"></param>
|
|
/// <param name="numRec"></param>
|
|
/// <returns></returns>
|
|
public async Task<List<TicketDTO>> TicketByCliente(string CodInst, string CodApp, string MasterKey, int numRec = 1000)
|
|
{
|
|
List<TicketDTO> dbResult = new List<TicketDTO>();
|
|
Stopwatch stopWatch = new Stopwatch();
|
|
stopWatch.Start();
|
|
|
|
dbResult = dbController.TicketGetFilt(false, TipologiaTicket.ND, CodApp, CodInst, MasterKey, numRec);
|
|
stopWatch.Stop();
|
|
TimeSpan ts = stopWatch.Elapsed;
|
|
Log.Trace($"Effettuata lettura da DB per TicketByCliente: {ts.TotalMilliseconds} ms");
|
|
|
|
return await Task.FromResult(dbResult);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Aggiornamentos tato ticket
|
|
/// </summary>
|
|
/// <param name="IdxTicket"></param>
|
|
/// <param name="NewStatus"></param>
|
|
/// <returns></returns>
|
|
public async Task<bool> TicketUpdateState(int IdxTicket, StatoRichiesta NewStatus)
|
|
{
|
|
bool fatto = false;
|
|
// inserimento!
|
|
Stopwatch stopWatch = new Stopwatch();
|
|
stopWatch.Start();
|
|
fatto = dbController.TicketUpdateState(IdxTicket, NewStatus);
|
|
stopWatch.Stop();
|
|
TimeSpan ts = stopWatch.Elapsed;
|
|
Log.Trace($"Effettuata update con TicketUpdateState: {ts.TotalMilliseconds} ms");
|
|
|
|
// restituisce elenco
|
|
return await Task.FromResult(fatto);
|
|
}
|
|
|
|
#endregion Public Methods
|
|
|
|
#region Protected Fields
|
|
|
|
/// <summary>
|
|
/// TTL da 1 h x cache Redis
|
|
/// </summary>
|
|
protected const int hourTTL = 60 * 60;
|
|
|
|
/// <summary>
|
|
/// TTL da 1 min x cache Redis
|
|
/// </summary>
|
|
protected const int redCacheTtlFast = 60 * 1;
|
|
|
|
/// <summary>
|
|
/// TTL da 5 min x cache Redis
|
|
/// </summary>
|
|
protected const int redCacheTtlStd = 60 * 5;
|
|
|
|
/// <summary>
|
|
/// Chiave redis x attivazioni da IdxLic
|
|
/// </summary>
|
|
protected const string rKeyAttivByLic = "LiMan.UI:Licenze:AttByIdxLic";
|
|
|
|
/// <summary>
|
|
/// Chiave redis x licenze da MasterKey
|
|
/// </summary>
|
|
protected const string rKeyLicByMKey = "LiMan.UI:Licenze:ListByKey";
|
|
|
|
/// <summary>
|
|
/// Chiave redis x statistiche in acquisizione
|
|
/// </summary>
|
|
protected const string rKeySampleStats = "LiMan.UI:SampleStats:Curr";
|
|
|
|
/// <summary>
|
|
/// Chiave redis x statistiche in acquisizione
|
|
/// </summary>
|
|
protected const string rKeySampleVars = "LiMan.UI:SampleStats:Vars";
|
|
|
|
/// <summary>
|
|
/// Chiave redis x statistiche chiamate
|
|
/// </summary>
|
|
protected const string rKeyStatslogCall = "LiMan.UI:StatsLogCall";
|
|
|
|
protected static JsonSerializerSettings? JSSettings;
|
|
|
|
/// <summary>
|
|
/// Durata cache lunga IN SECONDI
|
|
/// </summary>
|
|
protected int cacheTtlLong = 60 * 5;
|
|
|
|
/// <summary>
|
|
/// Durata cache breve IN SECONDI
|
|
/// </summary>
|
|
protected int cacheTtlShort = 60 * 1;
|
|
|
|
/// <summary>
|
|
/// Oggetto per connessione a REDIS
|
|
/// </summary>
|
|
protected IConnectionMultiplexer redisConn = null!;
|
|
|
|
/// <summary>
|
|
/// Oggetto DB redis da impiegare x chiamate R/W
|
|
/// </summary>
|
|
protected IDatabase redisDb = null!;
|
|
|
|
protected Random rnd = new Random();
|
|
|
|
#endregion Protected Fields
|
|
|
|
#region Protected Properties
|
|
|
|
/// <summary>
|
|
/// Durata cache breve (1 min circa + perturbazione percentuale +/-10%)
|
|
/// </summary>
|
|
protected TimeSpan FastCache
|
|
{
|
|
get => TimeSpan.FromSeconds(cacheTtlShort * rnd.Next(900, 1100) / 1000);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Durata cache lunga (+ perturbazione percentuale +/-10%)
|
|
/// </summary>
|
|
protected TimeSpan LongCache
|
|
{
|
|
get => TimeSpan.FromSeconds(cacheTtlLong * rnd.Next(900, 1100) / 1000);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Durata cache MOLTO breve (10 sec circa + perturbazione percentuale +/-10%)
|
|
/// </summary>
|
|
protected TimeSpan UltraFastCache
|
|
{
|
|
get => TimeSpan.FromSeconds(cacheTtlShort / 6 * rnd.Next(900, 1100) / 1000);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Durata cache MOLTO lunga (+ perturbazione percentuale +/-10%)
|
|
/// </summary>
|
|
protected TimeSpan UltraLongCache
|
|
{
|
|
get => TimeSpan.FromSeconds(cacheTtlLong * 10 * rnd.Next(900, 1100) / 1000);
|
|
}
|
|
|
|
#endregion Protected Properties
|
|
|
|
#region Protected Methods
|
|
|
|
/// <summary>
|
|
/// Esegue flush memoria redis dato redPattern
|
|
/// </summary>
|
|
/// <param name="pattern"></param>
|
|
/// <returns></returns>
|
|
protected 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);
|
|
}
|
|
answ = true;
|
|
}
|
|
}
|
|
|
|
return answ;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Recupera statistiche correnti
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
protected async Task<SampleStats> getCurrStats()
|
|
{
|
|
DateTime adesso = DateTime.Now;
|
|
SampleStats answ = new SampleStats()
|
|
{
|
|
Name = "ApiStats"
|
|
};
|
|
// in primis check data/ora prima/ultima scrittura del set... (2 date, lista chiavi gestite)
|
|
string rawData = await getRSV(rKeySampleStats);
|
|
if (rawData != null)
|
|
{
|
|
answ = JsonConvert.DeserializeObject<SampleStats>(rawData);
|
|
// aggiorno ultimo controllo e salvo...
|
|
answ.DtLast = adesso;
|
|
// salvo!
|
|
await setCurrStats(answ);
|
|
}
|
|
// controllo se scadute...
|
|
if (adesso.Subtract(answ.DtFirst).TotalMinutes > 60)
|
|
{
|
|
// se scaduto --> registrazione set sul DB (async), resettando i vari contatori...
|
|
bool salvato = await saveStatsToDb(answ.VList);
|
|
// inizio NUOVO set vuoto con record corrente
|
|
answ = new SampleStats()
|
|
{
|
|
Name = "ApiStats"
|
|
};
|
|
// salvo!
|
|
await setCurrStats(answ);
|
|
}
|
|
// restituisco record!
|
|
return answ;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Recupero chiave da redis
|
|
/// </summary>
|
|
/// <param name="rKey"></param>
|
|
/// <returns></returns>
|
|
protected async Task<string> getRSV(string rKey)
|
|
{
|
|
string answ = await _redisCacheClient.GetDbFromConfiguration().GetAsync<string>(rKey);
|
|
return answ;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Recupera contatore x la chiave redis indicata...
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
protected async Task<int> redCount(string rKey)
|
|
{
|
|
int currCount = 0;
|
|
string rawVal = await getRSV(rKey);
|
|
if (!string.IsNullOrEmpty(rawVal))
|
|
{
|
|
int.TryParse(rawVal, out currCount);
|
|
}
|
|
return currCount;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Resetta contatore x la chiave redis indicata...
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
protected async Task<bool> redCountClear(string rKey)
|
|
{
|
|
bool answ = false;
|
|
int currCount = 0;
|
|
answ = await setRSV(rKey, currCount, 2 * hourTTL);
|
|
return answ;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Incrementa contatore x la chiave redis indicata...
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
protected async Task<bool> redCountIncr(string rKey)
|
|
{
|
|
bool answ = false;
|
|
int currCount = 0;
|
|
string rawVal = await getRSV(rKey);
|
|
if (!string.IsNullOrEmpty(rawVal))
|
|
{
|
|
int.TryParse(rawVal, out currCount);
|
|
}
|
|
currCount++;
|
|
answ = await setRSV(rKey, currCount, 2 * hourTTL);
|
|
return answ;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Salva statistiche correnti
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
protected async Task<bool> setCurrStats(SampleStats newVal)
|
|
{
|
|
bool answ = false;
|
|
string rawData = JsonConvert.SerializeObject(newVal);
|
|
answ = await setRSV(rKeySampleStats, rawData, 24 * hourTTL);
|
|
return answ;
|
|
}
|
|
|
|
/// <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 _redisCacheClient.GetDbFromConfiguration().AddAsync(rKey, rVal, DateTimeOffset.Now.AddSeconds(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 _redisCacheClient.GetDbFromConfiguration().AddAsync<int>(rKey, rValInt, DateTimeOffset.Now.AddSeconds(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;
|
|
|
|
private static ILogger<ApiDataService> _logger;
|
|
|
|
private static NLog.Logger Log = LogManager.GetCurrentClassLogger();
|
|
|
|
private readonly IEmailSender _emailSender;
|
|
|
|
//private readonly IDistributedCache distributedCache;
|
|
private readonly IRedisCacheClient _redisCacheClient;
|
|
|
|
/// <summary>
|
|
/// Elenco obj in cache
|
|
/// </summary>
|
|
private List<string> cachedDataList = new List<string>();
|
|
|
|
/// <summary>
|
|
/// Durata assoluta massima della cache IN SECONDI
|
|
/// </summary>
|
|
private int chAbsExp = 60 * 5;
|
|
|
|
/// <summary>
|
|
/// Durata della cache IN SECONDI in modalità inattiva (non acceduta) prima di venire
|
|
/// rimossa NON estende oltre il tempo massimo di validità della cache (chAbsExp)
|
|
/// </summary>
|
|
private int chSliExp = 60 * 2;
|
|
|
|
#endregion Private Fields
|
|
|
|
#region Private Methods
|
|
|
|
/// <summary>
|
|
/// Parametri per generare opzioni cache
|
|
/// </summary>
|
|
/// <param name="multFact">Fattore di moltiplica cache (se 1 --> 2 e 5 min)</param>
|
|
/// <returns></returns>
|
|
private DistributedCacheEntryOptions cacheOpt(int multFact)
|
|
{
|
|
var numSecAbsExp = multFact <= 0 ? chAbsExp : chAbsExp * multFact;
|
|
var numSecSliExp = multFact <= 0 ? chSliExp : chSliExp * multFact;
|
|
return new DistributedCacheEntryOptions().SetAbsoluteExpiration(DateTime.Now.AddSeconds(numSecAbsExp)).SetSlidingExpiration(TimeSpan.FromSeconds(numSecSliExp));
|
|
}
|
|
|
|
#endregion Private Methods
|
|
}
|
|
} |