using GPW.CORE.Data;
using GPW.CORE.Data.DbModels;
using Microsoft.AspNetCore.Identity.UI.Services;
using Newtonsoft.Json;
using NLog;
using StackExchange.Redis;
using System.Diagnostics;
namespace GPW.CORE.Api.Data
{
public class ApiDataService : IDisposable
{
#region Public Fields
///
/// Classe Accesso metodi DB
///
public static CORE.Data.Controllers.GPWController dbController = null!;
#endregion Public Fields
#region Public Constructors
///
/// Init classe
///
///
///
///
///
public ApiDataService(IConfiguration configuration, ILogger logger, IEmailSender emailSender, IConnectionMultiplexer redisConn)
{
_logger = logger;
_configuration = configuration;
_emailSender = emailSender;
// setup compoenti REDIS
var redConnString = _configuration.GetConnectionString("Redis");
if (redConnString == null)
{
_logger.LogError("REDIS ConnString empty!");
}
else
{
this.redisConn = ConnectionMultiplexer.Connect(redConnString);
this.redisDb = this.redisConn.GetDatabase();
}
// Conf DB
var connStrDB = _configuration.GetConnectionString("GPW.DB");
if (string.IsNullOrEmpty(connStrDB))
{
_logger.LogError("ConnString empty!");
}
else
{
dbController = new CORE.Data.Controllers.GPWController(configuration);
_logger.LogInformation("DbController OK");
}
}
#endregion Public Constructors
#region Public Methods
///
/// Recupera l'elenco fasi (ATTIVE)
///
///
public async Task> AnagFasiActiv()
{
List? dbResult = new List();
string cacheKey = $"{rKeyFasiAct}";
trackCache(cacheKey);
string rawData = await getRSV(cacheKey);
if (!string.IsNullOrEmpty(rawData))
{
dbResult = JsonConvert.DeserializeObject>(rawData);
}
else
{
Stopwatch stopWatch = new Stopwatch();
stopWatch.Start();
dbResult = dbController.AnagFasiAll(true);
rawData = JsonConvert.SerializeObject(dbResult, Formatting.None, new JsonSerializerSettings() { ReferenceLoopHandling = ReferenceLoopHandling.Ignore });
await setRSV(cacheKey, rawData, shortTTL);
stopWatch.Stop();
TimeSpan ts = stopWatch.Elapsed;
Log.Trace($"Effettuata lettura da DB per AnagFasiActiv: {ts.TotalMilliseconds} ms");
}
if (dbResult == null)
{
dbResult = new List();
}
return await Task.FromResult(dbResult);
}
///
/// Recupera l'elenco progetti (ATTIVI)
///
///
public async Task> AnagProjActiv()
{
List? dbResult = new List();
string cacheKey = $"{rKeyProjAct}";
trackCache(cacheKey);
string rawData = await getRSV(cacheKey);
if (!string.IsNullOrEmpty(rawData))
{
dbResult = JsonConvert.DeserializeObject>(rawData);
}
else
{
Stopwatch stopWatch = new Stopwatch();
stopWatch.Start();
dbResult = dbController.AnagProjAll(true);
rawData = JsonConvert.SerializeObject(dbResult, Formatting.None, new JsonSerializerSettings() { ReferenceLoopHandling = ReferenceLoopHandling.Ignore });
await setRSV(cacheKey, rawData, shortTTL);
stopWatch.Stop();
TimeSpan ts = stopWatch.Elapsed;
Log.Trace($"Effettuata lettura da DB per AnagProjActiv: {ts.TotalMilliseconds} ms");
}
if (dbResult == null)
{
dbResult = new List();
}
return await Task.FromResult(dbResult);
}
///
/// Vista dati per FASE (tipicamente master...) con totalizzaizone ore budget/real e stato fase
///
///
///
public async Task CalcOreFase(int idxFase, bool doLog)
{
CalcOreFasiModel? dbResult = new CalcOreFasiModel();
string cacheKey = $"{rKeyCalcOreFase}:{idxFase}";
trackCache(cacheKey);
string rawData = await getRSV(cacheKey);
if (!string.IsNullOrEmpty(rawData))
{
dbResult = JsonConvert.DeserializeObject(rawData);
}
else
{
Stopwatch stopWatch = new Stopwatch();
stopWatch.Start();
dbResult = dbController.CalcOreFase(idxFase);
rawData = JsonConvert.SerializeObject(dbResult, Formatting.None, new JsonSerializerSettings() { ReferenceLoopHandling = ReferenceLoopHandling.Ignore });
await setRSV(cacheKey, rawData, shortTTL);
stopWatch.Stop();
TimeSpan ts = stopWatch.Elapsed;
if (doLog)
{
Log.Trace($"Effettuata lettura da DB per CalcOreFase: {ts.TotalMilliseconds} ms");
}
}
if (dbResult == null)
{
dbResult = new CalcOreFasiModel();
}
return await Task.FromResult(dbResult);
}
public async Task> ChecksGetByDip(int idxDip)
{
DateTime dtFine = DateTime.Today.AddDays(1);
List dbResult = new List();
Stopwatch stopWatch = new Stopwatch();
stopWatch.Start();
dbResult = dbController.GetChecksVC19Filt(idxDip, dtFine.AddMonths(-1), dtFine);
stopWatch.Stop();
TimeSpan ts = stopWatch.Elapsed;
Log.Trace($"Effettuata lettura da DB per ChecksGetByDip: {ts.TotalMilliseconds} ms");
return await Task.FromResult(dbResult);
}
public async Task> ChecksGetLast(int numRecord)
{
List dbResult = new List();
Stopwatch stopWatch = new Stopwatch();
stopWatch.Start();
dbResult = dbController.GetChecksVC19(numRecord);
stopWatch.Stop();
TimeSpan ts = stopWatch.Elapsed;
Log.Trace($"Effettuata lettura da DB per ChecksGetLast: {ts.TotalMilliseconds} ms");
return await Task.FromResult(dbResult);
}
///
/// Recupera record anomalie dipendenti
///
///
///
///
///
///
public async Task> DipAndAnomGetAll(DateTime inizio, DateTime fine, bool notOkApp, bool notOkTim, bool notOkLav)
{
List dbResult = new List();
Stopwatch stopWatch = new Stopwatch();
stopWatch.Start();
dbResult = dbController.DipAndAnomGetAll(inizio, fine, notOkApp, notOkTim, notOkLav);
stopWatch.Stop();
TimeSpan ts = stopWatch.Elapsed;
Log.Trace($"Effettuata lettura da DB per DipAndAnomGetAll: {ts.TotalMilliseconds} ms");
return await Task.FromResult(dbResult);
}
public async Task> DipendentiGetAll()
{
List dbResult = new List();
Stopwatch stopWatch = new Stopwatch();
stopWatch.Start();
dbResult = dbController.DipendentiGetAll();
stopWatch.Stop();
TimeSpan ts = stopWatch.Elapsed;
Log.Trace($"Effettuata lettura da DB per DipendentiGetAll: {ts.TotalMilliseconds} ms");
return await Task.FromResult(dbResult);
}
public void Dispose()
{
// Clear database controller
dbController.Dispose();
}
///
/// Imposta stato di una fase
///
/// ID
///
/// Stato attivo true/false (se è amster -_> aggiorna sottofasi x trigger su DB
///
///
public async Task FasiSetActive(int idxFase, bool isActive)
{
return await dbController.FasiSetActive(idxFase, isActive);
}
public async Task InsertCheck(DCCDecode updItem, string clientIp)
{
bool done = false;
Stopwatch stopWatch = new Stopwatch();
stopWatch.Start();
done = dbController.InsertCheck(updItem, clientIp);
stopWatch.Stop();
TimeSpan ts = stopWatch.Elapsed;
Log.Trace($"Effettuata operazione InsertCheck: {ts.TotalMilliseconds} ms");
return await Task.FromResult(done);
}
public async Task InsertManual(int idxDip, string clientIp)
{
bool done = false;
Stopwatch stopWatch = new Stopwatch();
stopWatch.Start();
done = dbController.InsertManual(idxDip, clientIp);
stopWatch.Stop();
TimeSpan ts = stopWatch.Elapsed;
Log.Trace($"Effettuata operazione InsertManual: {ts.TotalMilliseconds} ms");
return await Task.FromResult(done);
}
///
/// invalida tutta la cache in caso di update
///
///
public async Task InvalidateAllCache()
{
foreach (var item in cachedDataList)
{
await redisDb.StringSetAsync(item, "", TimeSpan.FromMilliseconds(5));
}
cachedDataList = new List();
}
///
/// Recupera eventi dato criteri filtro
///
///
///
///
///
public async Task> RegEventiGetFilt(DateTime inizio, DateTime fine, string evento)
{
List dbResult = new List();
Stopwatch stopWatch = new Stopwatch();
stopWatch.Start();
dbResult = dbController.RegEventiGetFilt(inizio, fine, evento);
stopWatch.Stop();
TimeSpan ts = stopWatch.Elapsed;
Log.Trace($"Effettuata lettura da DB per RegEventiGetFilt: {ts.TotalMilliseconds} ms");
return await Task.FromResult(dbResult);
}
///
/// Insert/Update di un record in Registro Eventi
///
///
///
public async Task RegEventiUpdate(RegistroEventiModel currItem)
{
bool done = false;
Stopwatch stopWatch = new Stopwatch();
stopWatch.Start();
done = dbController.RegEventiUpdate(currItem);
stopWatch.Stop();
TimeSpan ts = stopWatch.Elapsed;
Log.Trace($"Effettuata operazione RegEventiUpdate: {ts.TotalMilliseconds} ms");
return await Task.FromResult(done);
}
///
/// Recupera record anomalie dipendenti
///
/// singolo idx oppure 0 = tutti
///
///
///
///
///
///
///
public async Task> TeRaExplGetAll(int idxDipendente, DateTime dataFrom, DateTime dataTo, bool inatt, bool showWE, int maxErrMin, int maxErrPlus)
{
List dbResult = new List();
Stopwatch stopWatch = new Stopwatch();
stopWatch.Start();
dbResult = dbController.TeRaExplGetAll(idxDipendente, dataFrom, dataTo, inatt, showWE, maxErrMin, maxErrPlus);
stopWatch.Stop();
TimeSpan ts = stopWatch.Elapsed;
Log.Trace($"Effettuata lettura da DB per TeRaExplGetAll: {ts.TotalMilliseconds} ms");
return await Task.FromResult(dbResult);
}
///
/// Recupera record anomalie dipendenti
///
/// singolo idx oppure 0 = tutti
///
///
///
///
///
///
public async Task> TimbExplGetAnomalie(int idxDipendente, DateTime inizio, DateTime fine, bool notOkApp, bool notOkTim, bool notOkLav)
{
List dbResult = new List();
Stopwatch stopWatch = new Stopwatch();
stopWatch.Start();
dbResult = dbController.TimbExplGetAnomalie(idxDipendente, inizio, fine, notOkApp, notOkTim, notOkLav);
stopWatch.Stop();
TimeSpan ts = stopWatch.Elapsed;
Log.Trace($"Effettuata lettura da DB per TimbExplGetAnomalie: {ts.TotalMilliseconds} ms");
return await Task.FromResult(dbResult);
}
///
/// Recupera record anomalie dipendenti
///
/// singolo idx oppure 0 = tutti
///
///
///
public async Task> TimbExplGetContinuato(int idxDipendente, DateTime inizio, DateTime fine)
{
List dbResult = new List();
Stopwatch stopWatch = new Stopwatch();
stopWatch.Start();
dbResult = dbController.TimbExplGetContinuato(idxDipendente, inizio, fine);
stopWatch.Stop();
TimeSpan ts = stopWatch.Elapsed;
Log.Trace($"Effettuata lettura da DB per TimbExplGetContinuato: {ts.TotalMilliseconds} ms");
return await Task.FromResult(dbResult);
}
///
/// Recupera elenco anomalie x timbrature future
///
///
public async Task> TimbratureAnomalieFuture()
{
List dbResult = new List();
Stopwatch stopWatch = new Stopwatch();
stopWatch.Start();
dbResult = dbController.TimbratureAnomalieFuture();
stopWatch.Stop();
TimeSpan ts = stopWatch.Elapsed;
Log.Trace($"Effettuata lettura da DB per TimbratureAnomalieFuture: {ts.TotalMilliseconds} ms");
return await Task.FromResult(dbResult);
}
#endregion Public Methods
#region Protected Fields
protected const string rKeyCalcOreFase = "Check:OreFasi";
protected const string rKeyFasiAct = "Check:FasiAct";
protected const string rKeyProjAct = "Check:ProjAct";
///
/// TTL da 1 min x cache Redis
///
protected const int shortTTL = 60 * 5;
#endregion Protected Fields
#region Protected Methods
///
/// Recupero chiave da redis
///
///
///
protected async Task getRSV(string rKey)
{
string answ = "";
var rawData = await redisDb.StringGetAsync(rKey);
if (rawData.HasValue)
{
answ = $"{rawData}";
}
return answ;
}
///
/// Salvataggio chiave in redis
///
///
///
///
///
protected async Task setRSV(string rKey, string rVal, int ttlSec)
{
bool fatto = false;
await redisDb.StringSetAsync(rKey, rVal, TimeSpan.FromSeconds(ttlSec));
fatto = true;
return fatto;
}
///
/// Salvataggio chiave in redis
///
///
///
///
///
protected async Task setRSV(string rKey, int rValInt, int ttlSec)
{
bool fatto = false;
await redisDb.StringSetAsync(rKey, rValInt, TimeSpan.FromSeconds(ttlSec));
fatto = true;
return fatto;
}
///
/// Registra in cache chiave se non fosse già in elenco
///
///
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 ILogger _logger = null!;
private static NLog.Logger Log = LogManager.GetCurrentClassLogger();
private readonly IEmailSender _emailSender;
//private readonly IDistributedCache distributedCache;
//private readonly IRedisCacheClient _redisCacheClient;
///
/// Elenco obj in cache
///
private List cachedDataList = new List();
///
/// Oggetto per connessione a REDIS
///
private ConnectionMultiplexer redisConn = null!;
///
/// Oggetto DB redis da impiegare x chiamate R/W
///
private IDatabase redisDb = null!;
#endregion Private Fields
}
}