Files
lux/EgwCoreLib.Lux.Data/Services/DataLayerServices.cs
T
Samuele Locatelli aa8d768b56 Update migrazione DB
2025-08-08 16:11:39 +02:00

400 lines
14 KiB
C#

using EgwCoreLib.Lux.Core.RestPayload;
using EgwCoreLib.Lux.Data.Controllers;
using EgwCoreLib.Lux.Data.DbModel;
using EgwMultiEngineManager.Data;
using Microsoft.Extensions.Configuration;
using Newtonsoft.Json;
using NLog;
using StackExchange.Redis;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using static System.Runtime.InteropServices.JavaScript.JSType;
namespace EgwCoreLib.Lux.Data.Services
{
public class DataLayerServices : BaseServ
{
#region Public Constructors
public DataLayerServices(IConfiguration configuration, IConnectionMultiplexer RedisConn) : base(configuration, RedisConn)
{
// conf DB
string connStr = BaseServ.configuration.GetConnectionString("Lux.All") ?? "";
if (string.IsNullOrEmpty(connStr))
{
Log.Error("ConnString empty!");
}
else
{
dbController = new LuxController();
//dbController = new Controllers.LuxController(configuration);
StringBuilder sb = new StringBuilder();
sb.AppendLine($"DataLayerServices | LuxController OK");
Log.Info(sb.ToString());
}
}
#endregion Public Constructors
#region Public Properties
public static LuxController dbController { get; set; } = null!;
#endregion Public Properties
#region Public Methods
/// <summary>
/// Elenco completo Customers
/// </summary>
/// <returns></returns>
public List<CustomerModel> CustomersGetAll()
{
string source = "DB";
Stopwatch sw = new Stopwatch();
sw.Start();
List<CustomerModel>? result = new List<CustomerModel>();
// cerco in redis...
string currKey = $"{redisBaseKey}:Customers:ALL";
RedisValue rawData = redisDb.StringGet(currKey);
if (rawData.HasValue)
{
result = JsonConvert.DeserializeObject<List<CustomerModel>>($"{rawData}");
source = "REDIS";
}
else
{
result = dbController.CustomersGetAll();
// serializzo e salvo...
rawData = JsonConvert.SerializeObject(result);
redisDb.StringSet(currKey, rawData, LongCache);
}
if (result == null)
{
result = new List<CustomerModel>();
}
sw.Stop();
Log.Debug($"CustomersGetAll | {source} | {sw.Elapsed.TotalMilliseconds}ms");
return result;
}
/// <summary>
/// Elenco completo dealers
/// </summary>
/// <returns></returns>
public List<DealerModel> DealersGetAll()
{
string source = "DB";
Stopwatch sw = new Stopwatch();
sw.Start();
List<DealerModel>? result = new List<DealerModel>();
// cerco in redis...
string currKey = $"{redisBaseKey}:Dealers:ALL";
RedisValue rawData = redisDb.StringGet(currKey);
if (rawData.HasValue)
{
result = JsonConvert.DeserializeObject<List<DealerModel>>($"{rawData}");
source = "REDIS";
}
else
{
result = dbController.DealersGetAll();
// serializzo e salvo...
rawData = JsonConvert.SerializeObject(result);
redisDb.StringSet(currKey, rawData, LongCache);
}
if (result == null)
{
result = new List<DealerModel>();
}
sw.Stop();
Log.Debug($"DealersGetAll | {source} | {sw.Elapsed.TotalMilliseconds}ms");
return result;
}
/// <summary>
/// Reset completo cache sistema
/// </summary>
public bool FlushCache()
{
bool answ = false;
Stopwatch stopWatch = new Stopwatch();
stopWatch.Start();
RedisValue pattern = new RedisValue($"{redisBaseKey}:*");
answ = ExecFlushRedisPattern(pattern);
stopWatch.Stop();
Log.Debug($"FlushCache in {stopWatch.Elapsed.TotalMilliseconds} ms");
return answ;
}
/// <summary>
/// Reset completo cache sistema modalità async
/// </summary>
public async Task<bool> FlushCacheAsync()
{
bool answ = false;
Stopwatch sw = new Stopwatch();
sw.Start();
RedisValue pattern = new RedisValue($"{redisBaseKey}:*");
answ = await ExecFlushRedisPatternAsync(pattern);
sw.Stop();
Log.Debug($"FlushCacheAsync in {sw.Elapsed.TotalMilliseconds} ms");
return answ;
}
/// <summary>
/// Elenco completo offerte da DB
/// </summary>
/// <returns></returns>
public List<OfferModel> OfferGetAll()
{
string source = "DB";
Stopwatch sw = new Stopwatch();
sw.Start();
List<OfferModel>? result = new List<OfferModel>();
// cerco in redis...
string currKey = $"{redisBaseKey}:Offers:ALL";
RedisValue rawData = redisDb.StringGet(currKey);
//if (!string.IsNullOrEmpty($"{rawData}"))
if (rawData.HasValue)
{
result = JsonConvert.DeserializeObject<List<OfferModel>>($"{rawData}");
source = "REDIS";
}
else
{
result = dbController.OfferGetAll();
// serializzo e salvo...
rawData = JsonConvert.SerializeObject(result);
redisDb.StringSet(currKey, rawData, LongCache);
}
if (result == null)
{
result = new List<OfferModel>();
}
sw.Stop();
Log.Debug($"OfferGetAll | {source} | {sw.Elapsed.TotalMilliseconds}ms");
return result;
}
/// <summary>
/// Elenco righe offerta specificata
/// </summary>
/// <param name="OfferID"></param>
/// <returns></returns>
public async Task<List<OfferRowModel>> OfferRowGetByOffer(int OfferID)
{
string source = "DB";
Stopwatch sw = new Stopwatch();
sw.Start();
List<OfferRowModel>? result = new List<OfferRowModel>();
// cerco in redis...
string currKey = $"{redisBaseKey}:OfferRows:{OfferID}";
RedisValue rawData = await redisDb.StringGetAsync(currKey);
//if (!string.IsNullOrEmpty($"{rawData}"))
if (rawData.HasValue)
{
result = JsonConvert.DeserializeObject<List<OfferRowModel>>($"{rawData}");
source = "REDIS";
}
else
{
result = dbController.OfferRowGetByOffer(OfferID);
// serializzo e salvo...
rawData = JsonConvert.SerializeObject(result);
await redisDb.StringSetAsync(currKey, rawData, LongCache);
}
if (result == null)
{
result = new List<OfferRowModel>();
}
sw.Stop();
Log.Debug($"OfferRowGetByOffer | {source} | {sw.Elapsed.TotalMilliseconds}ms");
return result;
}
/// <summary>
/// Effettua update dei costi di tutte le righe dell'offerta indicata
/// </summary>
/// <param name="OfferID">Key</param>
/// <returns></returns>
public async Task<bool> OffertUpdateCost(int OfferID)
{
Stopwatch sw = new Stopwatch();
sw.Start();
// calcolo
bool fatto = await dbController.OffertUpdateCost(OfferID);
// svuoto cache...
await ExecFlushRedisPatternAsync((RedisValue)$"{redisBaseKey}:Offers:*");
await ExecFlushRedisPatternAsync((RedisValue)$"{redisBaseKey}:OfferRows:*");
sw.Stop();
Log.Debug($"OffertUpdateCost in {sw.Elapsed.TotalMilliseconds} ms");
return fatto;
}
/// <summary>
/// Esegue salvataggio BOM sul DB
/// </summary>
/// <param name="uID">UID dell'item offerta di cui si è ricevuto la BOM</param>
/// <param name="execEnvironment">Environment dell'item</param>
/// <param name="bomContent">BOM serializzata</param>
/// <returns></returns>
public async Task SaveBomAsync(string uID, Constants.EXECENVIRONMENTS execEnvironment, string bomContent)
{
// salvo sul DB il risultato della BOM
if (!string.IsNullOrEmpty(bomContent))
{
try
{
// deserializzo la Bom...
var bomList = JsonConvert.DeserializeObject<List<BomItemDTO>>(bomContent);
if (bomList != null)
{
// verifico 1:1 gli item ricevuti dalla BOM sul DB con eventuale insert
dbController.ItemUpsertFromBom(bomList);
// salvo la BOM nel record del DB relativo all'oggetto richiesto
dbController.OfferUpsertFromBom(uID, bomList);
}
}
catch { }
}
await Task.Delay(1);
}
#endregion Public Methods
#region Protected Fields
/// <summary>
/// Numero di operazioni parallele che si possono svolgere... (se 0 NON usa cicli paralleli)
/// </summary>
protected int numPar = 0;
#endregion Protected Fields
#region Protected Methods
/// <summary>
/// Esegue flush memoria redis dato pattern
/// </summary>
/// <param name="pattern"></param>
/// <returns></returns>
protected bool ExecFlushRedisPattern(RedisValue pattern)
{
bool answ = false;
/*******************************
* Recupero elenco dei server da cui cancellare le chaivi:
* - prendo solo i server connessi
* - prendo solo NON repliche (= master)
* - me ne aspetto 1 in uscita cmq
*******************************/
var connServ = redisConn.GetEndPoints()
.Select(endpoint =>
{
var server = redisConn.GetServer(endpoint);
return server;
})
.Where(x => x.IsConnected && !x.IsReplica)
.ToList();
// ciclo (anche se me ne aspetto 1 solo)
foreach (var mServer in connServ)
{
try
{
var keyList = mServer.Keys(redisDb.Database, pattern);
if (numPar > 0)
{
var options = new ParallelOptions { MaxDegreeOfParallelism = numPar };
Parallel.ForEachAsync(keyList, async (item, token) =>
{
// cancello
redisDb.KeyDelete(item);
});
}
else
{
foreach (var item in keyList)
{
redisDb.KeyDelete(item);
}
}
answ = true;
}
catch (Exception exc)
{
Log.Error($"Eccezione durante ExecFlushRedisPattern | pattern: {pattern}{Environment.NewLine}{exc}");
}
}
return answ;
}
/// <summary>
/// Esegue flush memoria redis dato pattern
/// </summary>
/// <param name="pattern"></param>
/// <returns></returns>
protected async Task<bool> ExecFlushRedisPatternAsync(RedisValue pattern)
{
bool answ = false;
/*******************************
* Recupero elenco dei server da cui cancellare le chaivi:
* - prendo solo i server connessi
* - prendo solo NON repliche (= master)
* - me ne aspetto 1 in uscita cmq
*******************************/
var connServ = redisConn.GetEndPoints()
.Select(endpoint =>
{
var server = redisConn.GetServer(endpoint);
return server;
})
.Where(x => x.IsConnected && !x.IsReplica)
.ToList();
// ciclo (anche se me ne aspetto 1 solo)
foreach (var mServer in connServ)
{
try
{
var keyList = mServer.Keys(redisDb.Database, pattern);
if (numPar > 0)
{
var options = new ParallelOptions { MaxDegreeOfParallelism = numPar };
await Parallel.ForEachAsync(keyList, async (item, token) =>
{
// cancello
await redisDb.KeyDeleteAsync(item);
});
}
else
{
foreach (var item in keyList)
{
await redisDb.KeyDeleteAsync(item);
}
}
answ = true;
}
catch (Exception exc)
{
Log.Error($"Eccezione durante ExecFlushRedisPatternAsync | pattern: {pattern}{Environment.NewLine}{exc}");
}
}
return answ;
}
#endregion Protected Methods
#region Private Fields
private static Logger Log = LogManager.GetCurrentClassLogger();
private string redisBaseKey = "Lux:Cache";
#endregion Private Fields
}
}