using Microsoft.AspNetCore.Identity.UI.Services;
using Newtonsoft.Json;
using NLog;
using StackExchange.Redis;
using System.Diagnostics;
using WebDoorCreator.Data.Controllers;
using WebDoorCreator.Data.DbModels;
using EgwCoreLib.Razor.Data;
using WebDoorCreator.Data.DTO;
using WebDoorCreator.Data;
namespace WebDoorCreator.UI.Data
{
public class WebDoorCreatorService
{
#region Public Fields
public static WebDoorCreatorController dbController = null!;
#endregion Public Fields
#region Public Constructors
public WebDoorCreatorService(IConfiguration configuration, IConnectionMultiplexer redisConnMult, IEmailSender emailSender)
{
_configuration = configuration;
_emailSender = emailSender;
// 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
};
// cod app
CodApp = _configuration["CodApp"];
// Conf DB
string connStr = _configuration.GetConnectionString("WDC.DB");
if (string.IsNullOrEmpty(connStr))
{
Log.Info("ConnString empty!");
}
else
{
dbController = new WebDoorCreatorController(configuration);
}
Log.Info("Avviata classe WebDoorCreatorService");
}
#endregion Public Constructors
#region Public Properties
public string CodApp { get; set; } = "";
#endregion Public Properties
#region Public Methods
#region Company methods
///
/// Company list
///
public async Task?> CompanyGetAll()
{
string source = "DB";
List? dbResult = new List();
// cerco da cache
string currKey = rKeyCompany;
Stopwatch stopWatch = new Stopwatch();
stopWatch.Start();
string? rawData = await redisDb.StringGetAsync(currKey);
if (!string.IsNullOrEmpty(rawData))
{
source = "REDIS";
var tempResult = JsonConvert.DeserializeObject>(rawData);
if (tempResult == null)
{
dbResult = new List();
}
else
{
dbResult = tempResult;
}
}
else
{
dbResult = dbController.CompanyAll();
rawData = JsonConvert.SerializeObject(dbResult, JSSettings);
await redisDb.StringSetAsync(currKey, rawData, UltraLongCache);
}
if (dbResult == null)
{
dbResult = new List();
}
stopWatch.Stop();
TimeSpan ts = stopWatch.Elapsed;
Log.Debug($"CompanyGetAll | {source} in: {ts.TotalMilliseconds} ms");
return dbResult;
}
///
/// Update company
///
///
///
public async Task CompanyAddMod(CompanyModel currRec)
{
var dbResult = await dbController.CompanyAddMod(currRec);
// elimino cache redis...
RedisValue pattern = new RedisValue($"{rKeyCompany}");
bool answ = await ExecFlushRedisPattern(pattern);
await Task.Delay(1);
return dbResult;
}
#endregion Company methods
/*----------------------------------------------------------------------------------------------------------------------*/
#region Cache methods
///
/// Esegue flush memoria redis dato pattern
///
///
///
private async Task 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;
}
public async Task FlushRedisCache()
{
await Task.Delay(1);
RedisValue pattern = new RedisValue($"{redisBaseAddr}");
bool answ = await ExecFlushRedisPattern(pattern);
return answ;
}
#endregion Cache methods
/*----------------------------------------------------------------------------------------------------------------------*/
#region Security Methods
public string DecriptData(string encData)
{
return SteamCrypto.DecryptString(encData, passPhrase);
}
public string EncriptData(string rawData)
{
return SteamCrypto.EncryptString(rawData, passPhrase);
}
#endregion Security Methods
/*----------------------------------------------------------------------------------------------------------------------*/
#region User Methods
///
/// Users roles list
///
public async Task?> GetUserView()
{
string source = "DB";
List? dbResult = new List();
// cerco da cache
string currKey = rKeyUsersView;
Stopwatch stopWatch = new Stopwatch();
stopWatch.Start();
string? rawData = await redisDb.StringGetAsync(currKey);
if (!string.IsNullOrEmpty(rawData))
{
source = "REDIS";
var tempResult = JsonConvert.DeserializeObject>(rawData);
if (tempResult == null)
{
dbResult = new List();
}
else
{
dbResult = tempResult;
}
}
else
{
dbResult = dbController.GetUserView();
rawData = JsonConvert.SerializeObject(dbResult, JSSettings);
await redisDb.StringSetAsync(currKey, rawData, UltraLongCache);
}
if (dbResult == null)
{
dbResult = new List();
}
stopWatch.Stop();
TimeSpan ts = stopWatch.Elapsed;
Log.Debug($"GetUserView | {source} in: {ts.TotalMilliseconds} ms");
return dbResult;
}
///
/// Users roles list
///
public async Task?> GetUsersAll()
{
string source = "DB";
List? dbResult = new List();
// cerco da cache
string currKey = rKeyUsers;
Stopwatch stopWatch = new Stopwatch();
stopWatch.Start();
string? rawData = await redisDb.StringGetAsync(currKey);
if (!string.IsNullOrEmpty(rawData))
{
source = "REDIS";
var tempResult = JsonConvert.DeserializeObject>(rawData);
if (tempResult == null)
{
dbResult = new List();
}
else
{
dbResult = tempResult;
}
}
else
{
dbResult = dbController.GetUsersAll();
rawData = JsonConvert.SerializeObject(dbResult, JSSettings);
await redisDb.StringSetAsync(currKey, rawData, UltraLongCache);
}
if (dbResult == null)
{
dbResult = new List();
}
stopWatch.Stop();
TimeSpan ts = stopWatch.Elapsed;
Log.Debug($"GetUsersAll | {source} in: {ts.TotalMilliseconds} ms");
return dbResult;
}
///
/// Users roles list
///
public async Task GetUsersById(string userId)
{
string source = "DB";
AspNetUsers dbResult = new AspNetUsers();
// cerco da cache
string currKey = $"{rKeyUsers}:{userId}";
Stopwatch stopWatch = new Stopwatch();
stopWatch.Start();
string? rawData = await redisDb.StringGetAsync(currKey);
if (!string.IsNullOrEmpty(rawData))
{
source = "REDIS";
var tempResult = JsonConvert.DeserializeObject(rawData);
if (tempResult == null)
{
dbResult = new AspNetUsers();
}
else
{
dbResult = tempResult;
}
}
else
{
dbResult = dbController.GetUsersById(userId);
rawData = JsonConvert.SerializeObject(dbResult, JSSettings);
await redisDb.StringSetAsync(currKey, rawData, UltraLongCache);
}
if (dbResult == null)
{
dbResult = new AspNetUsers();
}
stopWatch.Stop();
TimeSpan ts = stopWatch.Elapsed;
Log.Debug($"GetUsersById | {source} in: {ts.TotalMilliseconds} ms");
return dbResult;
}
#endregion User Methods
/*----------------------------------------------------------------------------------------------------------------------*/
#region Roles Methods
///
/// roles list
///
public async Task?> GetRolesAll()
{
string source = "DB";
List? dbResult = new List();
// cerco da cache
string currKey = rKeyRoles;
Stopwatch stopWatch = new Stopwatch();
stopWatch.Start();
string? rawData = await redisDb.StringGetAsync(currKey);
if (!string.IsNullOrEmpty(rawData))
{
source = "REDIS";
var tempResult = JsonConvert.DeserializeObject>(rawData);
if (tempResult == null)
{
dbResult = new List();
}
else
{
dbResult = tempResult;
}
}
else
{
dbResult = dbController.GetRolesAll();
rawData = JsonConvert.SerializeObject(dbResult, JSSettings);
await redisDb.StringSetAsync(currKey, rawData, UltraLongCache);
}
if (dbResult == null)
{
dbResult = new List();
}
stopWatch.Stop();
TimeSpan ts = stopWatch.Elapsed;
Log.Debug($"GetRolesAll | {source} in: {ts.TotalMilliseconds} ms");
return dbResult;
}
#endregion Roles Methods
/*----------------------------------------------------------------------------------------------------------------------*/
#region Order status Methods
public async Task?> GetOrderStatus(int companyId, int orderStatus, DateTime dataFrom, DateTime dataTo)
{
string source = "DB";
List? dbResult = new List();
// cerco da cache
string currKey = rKeyOrderStatus;
Stopwatch stopWatch = new Stopwatch();
stopWatch.Start();
string? rawData = await redisDb.StringGetAsync(currKey);
if (!string.IsNullOrEmpty(rawData))
{
source = "REDIS";
var tempResult = JsonConvert.DeserializeObject>(rawData);
if (tempResult == null)
{
dbResult = new List();
}
else
{
dbResult = tempResult;
}
}
else
{
dbResult = dbController.GetOrderStatus(companyId, orderStatus, dataFrom, dataTo);
rawData = JsonConvert.SerializeObject(dbResult, JSSettings);
await redisDb.StringSetAsync(currKey, rawData, UltraLongCache);
}
if (dbResult == null)
{
dbResult = new List();
}
stopWatch.Stop();
TimeSpan ts = stopWatch.Elapsed;
Log.Debug($"GetOrderStatus | {source} in: {ts.TotalMilliseconds} ms");
return dbResult;
}
#endregion Order status Methods
/*----------------------------------------------------------------------------------------------------------------------*/
#region Order Methods
///
/// Add new order
///
///
///
public async Task OrderAdd(OrderModel currRec)
{
var dbResult = await dbController.OrderAdd(currRec);
// elimino cache redis...
RedisValue pattern = new RedisValue($"{rKeyOrderStatus}");
bool answ = await ExecFlushRedisPattern(pattern);
await Task.Delay(1);
return dbResult;
}
#endregion Order Methods
/*----------------------------------------------------------------------------------------------------------------------*/
#region Door Methods
///
/// Doors list by orderId
///
public async Task?> DoorsGetByOrderId(int orderId)
{
string source = "DB";
List? dbResult = new List();
// cerco da cache
string currKey = $"{rKeyDoor}:{orderId}";
Stopwatch stopWatch = new Stopwatch();
stopWatch.Start();
string? rawData = await redisDb.StringGetAsync(currKey);
if (!string.IsNullOrEmpty(rawData))
{
source = "REDIS";
var tempResult = JsonConvert.DeserializeObject>(rawData);
if (tempResult == null)
{
dbResult = new List();
}
else
{
dbResult = tempResult;
}
}
else
{
dbResult = dbController.DoorsGetByOrderId(orderId);
rawData = JsonConvert.SerializeObject(dbResult, JSSettings);
await redisDb.StringSetAsync(currKey, rawData, UltraLongCache);
}
if (dbResult == null)
{
dbResult = new List();
}
stopWatch.Stop();
TimeSpan ts = stopWatch.Elapsed;
Log.Debug($"DoorsGetByOrderId | {source} in: {ts.TotalMilliseconds} ms");
return dbResult;
}
///
/// Update or add door
///
///
///
public async Task DoorsAddMod(DoorModel currRec)
{
var dbResult = await dbController.DoorUpsert(currRec);
// elimino cache redis dati porta...
RedisValue pattern = new RedisValue($"{rKeyDoor}");
bool answ = await ExecFlushRedisPattern(pattern);
// elimino cache redis dati ordine...
pattern = new RedisValue($"{rKeyOrderStatus}");
answ = await ExecFlushRedisPattern(pattern);
await Task.Delay(1);
return dbResult;
}
#endregion Door Methods
#endregion Public Methods
#region Protected Fields
#region Private Properties
///
/// Durata cache lunga (+ perturbazione percentuale +/-10%)
///
private TimeSpan FastCache
{
get => TimeSpan.FromSeconds(cacheTtlShort * rnd.Next(900, 1100) / 1000);
}
///
/// Durata cache lunga (+ perturbazione percentuale +/-10%)
///
private TimeSpan LongCache
{
get => TimeSpan.FromSeconds(cacheTtlLong * rnd.Next(900, 1100) / 1000);
}
///
/// Durata cache lunga (+ perturbazione percentuale +/-10%)
///
private TimeSpan UltraLongCache
{
get => TimeSpan.FromSeconds(cacheTtlLong * 10 * rnd.Next(900, 1100) / 1000);
}
#endregion Private Properties
protected const string passPhrase = "9eb4660f-8753-46bc-b23b-08759ba03fe9";
//#region Protected Fields
protected const string redisBaseAddr = "WDC";
//#endregion Public Methods
protected const string rKeyCompany = $"{redisBaseAddr}:Cache:Company";
protected const string rKeyOrderStatus = $"{redisBaseAddr}:Cache:OrderStatus";
protected const string rKeyUsers = $"{redisBaseAddr}:Cache:Users";
protected const string rKeyUsersView = $"{redisBaseAddr}:Cache:UsersView";
protected const string rKeyRoles = $"{redisBaseAddr}:Cache:Roles";
protected const string rKeyDoor = $"{redisBaseAddr}:Cache:Doors";
protected Random rnd = new Random();
#endregion Protected Fields
#region Private Fields
private static IConfiguration _configuration = null!;
private static JsonSerializerSettings? JSSettings;
private static NLog.Logger Log = LogManager.GetCurrentClassLogger();
private readonly IEmailSender _emailSender;
///
/// Durata cache lunga IN SECONDI
///
private int cacheTtlLong = 60 * 5;
///
/// Durata cache breve IN SECONDI
///
private int cacheTtlShort = 60 * 1;
///
/// Oggetto per connessione a REDIS
///
private IConnectionMultiplexer redisConn;
//ISubscriber sub = redis.GetSubscriber();
///
/// Oggetto DB redis da impiegare x chiamate R/W
///
private IDatabase redisDb = null!;
#endregion Private Fields
}
}