626 lines
27 KiB
C#
626 lines
27 KiB
C#
using EgwCoreLib.Lux.Core.Generic;
|
|
using EgwCoreLib.Lux.Core.RestPayload;
|
|
using EgwCoreLib.Lux.Data.Controllers;
|
|
using EgwCoreLib.Lux.Data.DbModel.Job;
|
|
using EgwCoreLib.Lux.Data.DbModel.Production;
|
|
using EgwCoreLib.Lux.Data.DbModel.Sales;
|
|
using EgwCoreLib.Lux.Data.Services.Config;
|
|
using EgwCoreLib.Lux.Data.Services.Production;
|
|
using EgwCoreLib.Lux.Data.Services.Sales;
|
|
using EgwMultiEngineManager.Data;
|
|
using Microsoft.Extensions.Configuration;
|
|
using Microsoft.Extensions.DependencyInjection;
|
|
using Newtonsoft.Json;
|
|
using NLog;
|
|
using StackExchange.Redis;
|
|
using System.Diagnostics;
|
|
using System.Runtime.CompilerServices;
|
|
using System.Text;
|
|
using static EgwCoreLib.Lux.Core.Enums;
|
|
|
|
namespace EgwCoreLib.Lux.Data.Services
|
|
{
|
|
public class DataLayerServices : BaseServ
|
|
{
|
|
#region Public Constructors
|
|
|
|
public DataLayerServices(
|
|
IConfiguration configuration,
|
|
IConnectionMultiplexer RedisConn,
|
|
IServiceProvider serviceProvider) : base(configuration, RedisConn)
|
|
{
|
|
_serviceProvider = serviceProvider;
|
|
// conf DB
|
|
string connStr = _config.GetConnectionString("Lux.All") ?? "";
|
|
if (string.IsNullOrEmpty(connStr))
|
|
{
|
|
Log.Error("ConnString empty!");
|
|
}
|
|
else
|
|
{
|
|
StringBuilder sb = new StringBuilder();
|
|
//dbController = new Controllers.LuxController(_config);
|
|
dbController = new LuxController();
|
|
sb.AppendLine($"LuxController OK");
|
|
dataSimController = new DataSimulatorController();
|
|
sb.AppendLine($"DataSimController OK");
|
|
sb.AppendLine($"LuxController OK");
|
|
Log.Info(sb.ToString());
|
|
}
|
|
}
|
|
|
|
#endregion Public Constructors
|
|
|
|
#region Public Properties
|
|
|
|
public IConfProfileService ConfProfServ => _serviceProvider.GetRequiredService<IConfProfileService>();
|
|
public IOfferRowService OfferRowServ => _serviceProvider.GetRequiredService<IOfferRowService>();
|
|
public IOrderRowService OrderRowServ => _serviceProvider.GetRequiredService<IOrderRowService>();
|
|
public IProductionGroupService PrGrpServ => _serviceProvider.GetRequiredService<IProductionGroupService>();
|
|
public IProductionOdlService PrOdlServ => _serviceProvider.GetRequiredService<IProductionOdlService>();
|
|
|
|
#endregion Public Properties
|
|
|
|
#region Public Methods
|
|
|
|
/// <summary>
|
|
/// Sistema gli item che mancassero di ItemID leggendo da DB
|
|
/// </summary>
|
|
/// <param name="listOrg"></param>
|
|
/// <returns></returns>
|
|
public List<BomItemDTO> BomFixItemId(List<BomItemDTO> listOrg)
|
|
{
|
|
using var activity = StartActivity();
|
|
string source = "DB";
|
|
List<BomItemDTO> listFix = listOrg;
|
|
// sistemo ItemID per gli item della BOM...
|
|
var listItemDB = dbController.ItemGetFilt("", ItemClassType.Bom);
|
|
// cerco i record da sistemare ed 1:1 li fixo...
|
|
foreach (var item in listFix.Where(x => x.ItemID == 0))
|
|
{
|
|
var dbRec = listItemDB.FirstOrDefault(x => x.ExtItemCode == item.ItemCode);
|
|
if ((dbRec != null))
|
|
{
|
|
item.ItemID = dbRec.ItemID;
|
|
}
|
|
}
|
|
activity?.SetTag("data.source", source);
|
|
LogTrace($"{source} | trace: {activity?.TraceId} | {activity?.Duration.TotalMilliseconds}ms");
|
|
return listFix;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Reset completo cache sistema
|
|
/// </summary>
|
|
public bool FlushCache()
|
|
{
|
|
using var activity = StartActivity();
|
|
string source = "REDIS";
|
|
bool answ = false;
|
|
RedisValue pattern = new RedisValue($"{redisBaseKey}:*");
|
|
answ = ExecFlushRedisPattern(pattern);
|
|
activity?.SetTag("data.source", source);
|
|
LogTrace($"{source} | trace: {activity?.TraceId} | {activity?.Duration.TotalMilliseconds}ms");
|
|
return answ;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Reset completo cache sistema modalità async
|
|
/// </summary>
|
|
public async Task<bool> FlushCacheAsync()
|
|
{
|
|
using var activity = StartActivity();
|
|
string source = "REDIS";
|
|
bool answ = false;
|
|
RedisValue pattern = new RedisValue($"{redisBaseKey}:*");
|
|
answ = await ExecFlushRedisPatternAsync(pattern);
|
|
activity?.SetTag("data.source", source);
|
|
LogTrace($"{source} | trace: {activity?.TraceId} | {activity?.Duration.TotalMilliseconds}ms");
|
|
return answ;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Reset cache sistema x Offerte modalità async
|
|
/// </summary>
|
|
public async Task<bool> FlushCacheOffersAsync()
|
|
{
|
|
using var activity = StartActivity();
|
|
string source = "REDIS";
|
|
bool answ = false;
|
|
await ExecFlushRedisPatternAsync((RedisValue)$"{redisBaseKey}:Offers:*");
|
|
await ExecFlushRedisPatternAsync((RedisValue)$"{redisBaseKey}:OfferRows:*");
|
|
activity?.SetTag("data.source", source);
|
|
LogTrace($"{source} | trace: {activity?.TraceId} | {activity?.Duration.TotalMilliseconds}ms");
|
|
return answ;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Reset cache sistema x Ordini modalità async
|
|
/// </summary>
|
|
public async Task<bool> FlushCacheOrdersAsync()
|
|
{
|
|
using var activity = StartActivity();
|
|
string source = "REDIS";
|
|
bool answ = false;
|
|
await ExecFlushRedisPatternAsync((RedisValue)$"{redisBaseKey}:Orders:*");
|
|
await ExecFlushRedisPatternAsync((RedisValue)$"{redisBaseKey}:OrderRows:*");
|
|
activity?.SetTag("data.source", source);
|
|
LogTrace($"{source} | trace: {activity?.TraceId} | {activity?.Duration.TotalMilliseconds}ms");
|
|
return answ;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Verifica offerte scadute, con update sul DB
|
|
/// </summary>
|
|
public async Task<bool> OffersCheckExpired()
|
|
{
|
|
using var activity = StartActivity();
|
|
string source = "DB+REDIS";
|
|
// calcolo
|
|
bool fatto = await dbController.OffersCheckExpired();
|
|
// svuoto cache...
|
|
await ExecFlushRedisPatternAsync((RedisValue)$"{redisBaseKey}:Offers:*");
|
|
await ExecFlushRedisPatternAsync((RedisValue)$"{redisBaseKey}:OfferRows:*");
|
|
activity?.SetTag("data.source", source);
|
|
LogTrace($"{source} | trace: {activity?.TraceId} | {activity?.Duration.TotalMilliseconds}ms");
|
|
return fatto;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Converte il campo raw della BOM in lista oggetti da gestire
|
|
/// </summary>
|
|
/// <param name="currRec"></param>
|
|
/// <returns></returns>
|
|
public List<BomItemDTO> OrderGetBomList(OrderRowModel currRec)
|
|
{
|
|
List<BomItemDTO> answ = new List<BomItemDTO>();
|
|
var bomList = JsonConvert.DeserializeObject<List<BomItemDTO>>(currRec.ItemBOM);
|
|
if (bomList != null)
|
|
{
|
|
answ = bomList;
|
|
}
|
|
return answ;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Elenco completo Fasi
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
public async Task<List<PhaseModel>> PhasesGetAllAsync()
|
|
{
|
|
using var activity = StartActivity();
|
|
string source = "DB";
|
|
List<PhaseModel>? result = new List<PhaseModel>();
|
|
// cerco in redis...
|
|
string currKey = $"{redisBaseKey}:Phases:ALL";
|
|
RedisValue rawData = await _redisDb.StringGetAsync(currKey);
|
|
if (rawData.HasValue)
|
|
{
|
|
result = JsonConvert.DeserializeObject<List<PhaseModel>>($"{rawData}");
|
|
source = "REDIS";
|
|
}
|
|
else
|
|
{
|
|
result = await dbController.PhasesGetAllAsync();
|
|
// serializzo e salvo con config x evitare loop...
|
|
rawData = JsonConvert.SerializeObject(result, JSSettings);
|
|
await _redisDb.StringSetAsync(currKey, rawData, LongCache);
|
|
}
|
|
if (result == null)
|
|
{
|
|
result = new List<PhaseModel>();
|
|
}
|
|
activity?.SetTag("data.source", source);
|
|
LogTrace($"{source} | trace: {activity?.TraceId} | {activity?.Duration.TotalMilliseconds}ms");
|
|
return result;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Restituisce un dizionario di <CodFase,EventDto> da usare nel planner
|
|
/// </summary>
|
|
/// <param name="dtStart"></param>
|
|
/// <param name="dtEnd"></param>
|
|
/// <returns></returns>
|
|
public async Task<Dictionary<string, List<EventDto>>?> PlannerGetEvents(DateTime dtStart, DateTime dtEnd)
|
|
{
|
|
using var activity = StartActivity();
|
|
string source = "DB";
|
|
Dictionary<string, List<EventDto>>? result = null;
|
|
// cerco in redis...
|
|
string currKey = $"{redisBaseKey}:PlannerData:{dtStart:yyyyMMdd}:{dtEnd:yyyyMMdd}";
|
|
RedisValue rawData = await _redisDb.StringGetAsync(currKey);
|
|
//if (!string.IsNullOrEmpty($"{rawData}"))
|
|
if (rawData.HasValue && rawData.Length() > 2)
|
|
{
|
|
result = JsonConvert.DeserializeObject<Dictionary<string, List<EventDto>>>($"{rawData}");
|
|
source = "REDIS";
|
|
}
|
|
else
|
|
{
|
|
result = dataSimController.PlannerGetEvents(dtStart, dtEnd);
|
|
// serializzo e salvo...
|
|
rawData = JsonConvert.SerializeObject(result);
|
|
await _redisDb.StringSetAsync(currKey, rawData, LongCache);
|
|
}
|
|
activity?.SetTag("data.source", source);
|
|
LogTrace($"{source} | trace: {activity?.TraceId} | {activity?.Duration.TotalMilliseconds}ms");
|
|
return result;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Assegnazione in blocco degli item agli ODL corrispondenti
|
|
/// </summary>
|
|
/// <param name="dbList"></param>
|
|
/// <param name="dictParts"></param>
|
|
/// <returns></returns>
|
|
public async Task<int> ProdItem2ODL_AssignAsync(List<ProductionODLModel> dbList, Dictionary<(int phaseId, int resId, string machine, int index), List<string>> dictParts)
|
|
{
|
|
using var activity = StartActivity();
|
|
string source = "DB+REDIS";
|
|
// calcolo
|
|
int fatto = await dbController.ProdItem2ODL_AssignAsync(dbList, dictParts);
|
|
// svuoto cache...
|
|
//await ExecFlushRedisPatternAsync((RedisValue)$"{_redisBaseKey}:ProdItems:*");
|
|
await ExecFlushRedisPatternAsync((RedisValue)$"{redisBaseKey}:ProdItems:OrdRowId:*");
|
|
await ExecFlushRedisPatternAsync((RedisValue)$"{redisBaseKey}:ProdGroup:OrdRowId:*");
|
|
await ExecFlushRedisPatternAsync((RedisValue)$"{redisBaseKey}:OrderRows:*");
|
|
await ExecFlushRedisPatternAsync((RedisValue)$"{redisBaseKey}:OrderRowsByState:*");
|
|
activity?.SetTag("data.source", source);
|
|
LogTrace($"{source} | trace: {activity?.TraceId} | {activity?.Duration.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="qMode">Mode della chiamata (x decidere cosa/dove salvare)</param>
|
|
/// <param name="execEnvironment">Environment dell'item</param>
|
|
/// <param name="bomContent">BOM serializzata</param>
|
|
/// <returns></returns>
|
|
public async Task SaveBomAsync(string uID, Egw.Window.Data.Enums.QuestionModes qMode, Constants.EXECENVIRONMENTS execEnvironment, string bomContent)
|
|
{
|
|
using var activity = StartActivity();
|
|
string source = "DB";
|
|
// salvo sul DB il risultato della BOM
|
|
if (!string.IsNullOrEmpty(bomContent))
|
|
{
|
|
List<BomItemDTO>? bomList = null;
|
|
try
|
|
{
|
|
// deserializzo la Bom...
|
|
bomList = JsonConvert.DeserializeObject<List<BomItemDTO>>(bomContent);
|
|
}
|
|
catch { }
|
|
if (bomList != null)
|
|
{
|
|
// verifico 1:1 gli item ricevuti dalla BOM sul DB con eventuale insert in anagrafica dei nuovi
|
|
dbController.ItemUpsertFromBom(bomList);
|
|
// se mode = 2 è offerta, se 5 = ODL...
|
|
switch (qMode)
|
|
{
|
|
case Egw.Window.Data.Enums.QuestionModes.NULL:
|
|
break;
|
|
|
|
case Egw.Window.Data.Enums.QuestionModes.PREVIEW:
|
|
break;
|
|
|
|
// BOM in offerta
|
|
case Egw.Window.Data.Enums.QuestionModes.BOM:
|
|
// salvo la BOM nel record Offer del DB relativo all'oggetto richiesto
|
|
await OfferRowServ.UpdateBomAsync(uID, bomList);
|
|
break;
|
|
|
|
case Egw.Window.Data.Enums.QuestionModes.HARDWARE:
|
|
break;
|
|
|
|
case Egw.Window.Data.Enums.QuestionModes.CONFIG:
|
|
break;
|
|
|
|
// BOM in ODL
|
|
case Egw.Window.Data.Enums.QuestionModes.ORDER:
|
|
// salvo la BOM nel record ProdODL del DB relativo all'oggetto richiesto
|
|
await PrOdlServ.UpdateBomAsync(uID, bomContent);
|
|
// salvo in cache BOM aggiornata...
|
|
string currKey = $"{redisBaseKey}:ProdOdl:{uID}";
|
|
await _redisDb.StringSetAsync(currKey, bomContent, LongCache);
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
activity?.SetTag("data.source", source);
|
|
LogTrace($"{source} | trace: {activity?.TraceId} | {activity?.Duration.TotalMilliseconds}ms");
|
|
}
|
|
|
|
/// <summary>
|
|
/// Esegue salvataggio HardwareModelList 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="rawContent">HardwareModelList serializzata</param>
|
|
/// <returns></returns>
|
|
public async Task SaveHmlAsync(string uID, Constants.EXECENVIRONMENTS execEnvironment, string rawContent)
|
|
{
|
|
// non effettuo salvataggio sul DB perché master del dato è esterno e lo lasceremo solo in cache REDIS
|
|
await Task.Delay(1);
|
|
using var activity = StartActivity();
|
|
string source = "NONE";
|
|
activity?.SetTag("data.source", source);
|
|
LogTrace($"{source} | trace: {activity?.TraceId} | {activity?.Duration.TotalMilliseconds}ms");
|
|
}
|
|
|
|
/// <summary>
|
|
/// Esegue salvataggio ProdBalance (di un gruppo lavorazioni per riga ordine) sul DB
|
|
/// </summary>
|
|
/// <param name="uID">UID dell'item offerta di cui si è ricevuto l'oggetto Balance'</param>
|
|
/// <param name="rGroup">Prod Group di riferimento</param>
|
|
/// <param name="execEnvironment">Environment dell'item</param>
|
|
/// <param name="balance">Stima Balance serializzata</param>
|
|
/// <returns></returns>
|
|
public async Task<bool> SaveProdBalanceAsync(string uID, string rGroup, Constants.EXECENVIRONMENTS execEnvironment, string balance)
|
|
{
|
|
var result = await PrGrpServ.UpsertBalanceAsync(uID, rGroup, balance);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Esegue salvataggio ProdEstimate (per riga ordine) sul DB
|
|
/// </summary>
|
|
/// <param name="uID">UID dell'item offerta di cui si è ricevuto la ProdEstim</param>
|
|
/// <param name="execEnvironment">Environment dell'item</param>
|
|
/// <param name="prodEstim">Stima ProdEstimate serializzata</param>
|
|
/// <returns></returns>
|
|
public async Task<bool> SaveProdEstimateAsync(string uID, Constants.EXECENVIRONMENTS execEnvironment, string prodEstim)
|
|
{
|
|
var result = await OrderRowServ.SaveProdEstAsync(uID, prodEstim);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>
|
|
/// MockUp (fake) salvataggio ProfileList sul DB
|
|
/// </summary>
|
|
/// <param name="uID">UID ricezione (default tipicamente)</param>
|
|
/// <param name="execEnvironment">Environment dell'item</param>
|
|
/// <param name="rawContent">ProfileList serializzata</param>
|
|
/// <returns></returns>
|
|
public async Task<bool> SaveProfileListAsync(string uID, Constants.EXECENVIRONMENTS execEnvironment, string rawContent)
|
|
{
|
|
var result = await ConfProfServ.SaveProfileListAsync(uID, execEnvironment, rawContent);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>
|
|
/// MockUp (fake) salvataggio ProfileThreshold sul DB
|
|
/// </summary>
|
|
/// <param name="uID">UID del profilo</param>
|
|
/// <param name="execEnvironment">Environment dell'item</param>
|
|
/// <param name="rawThreshold">ThresholdList serializzata</param>
|
|
/// <param name="rawData">Info profile data serializzati</param>
|
|
/// <returns></returns>
|
|
public async Task<bool> SaveProfileThreshAsync(string uID, Constants.EXECENVIRONMENTS execEnvironment, string rawThreshold, string rawData)
|
|
{
|
|
var result = await ConfProfServ.SaveProfileThreshAsync(uID, execEnvironment, rawThreshold, rawData);
|
|
return result;
|
|
}
|
|
|
|
#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>
|
|
/// Helper avvio attività per la funzione tracciata
|
|
/// </summary>
|
|
/// <param name="methodName"></param>
|
|
/// <returns></returns>
|
|
protected new static Activity? StartActivity([CallerMemberName] string? methodName = null)
|
|
{
|
|
var activity = ActivitySource.StartActivity(methodName ?? "UNDEF");
|
|
activity?.SetTag("host.name", Environment.MachineName);
|
|
return activity;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Esegue flush memoria redis dato pat2Flush
|
|
/// </summary>
|
|
/// <param name="pat2Flush"></param>
|
|
/// <returns></returns>
|
|
protected bool ExecFlushRedisPattern(RedisValue pat2Flush)
|
|
{
|
|
bool answ = false;
|
|
using var activity = StartActivity();
|
|
string source = "REDIS";
|
|
/*******************************
|
|
* Recupero elenco dei server da cui cancellare le chiavi:
|
|
* - 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)
|
|
.FirstOrDefault();
|
|
if (connServ != null)
|
|
{
|
|
try
|
|
{
|
|
// sepattern è "*" elimino intero DB...
|
|
if ((pat2Flush.Equals(new RedisValue("*")) || pat2Flush == RedisValue.Null))
|
|
{
|
|
connServ.FlushDatabase(database: _redisDb.Database);
|
|
}
|
|
else
|
|
{
|
|
var keys = connServ.Keys(database: _redisDb.Database, pattern: pat2Flush, pageSize: 1000);
|
|
var batch = new List<RedisKey>();
|
|
foreach (var key in keys)
|
|
{
|
|
batch.Add(key);
|
|
|
|
// Flush in batches of 1000
|
|
if (batch.Count >= 1000)
|
|
{
|
|
foreach (var item in batch)
|
|
_redisDb.KeyDelete(item);
|
|
|
|
batch.Clear();
|
|
}
|
|
}
|
|
|
|
// Flush remaining keys
|
|
foreach (var item in batch)
|
|
_redisDb.KeyDelete(item);
|
|
}
|
|
answ = true;
|
|
}
|
|
catch (Exception exc)
|
|
{
|
|
string exMsg = $"Eccezione durante ExecFlushRedisPattern | pat2Flush: {pat2Flush}";
|
|
LogTrace($"{exMsg}{Environment.NewLine}{exc}", LogLevel.Error);
|
|
// traccio errore
|
|
activity?.SetStatus(ActivityStatusCode.Error, exc.Message);
|
|
activity?.AddEvent(new ActivityEvent("exception", tags: new ActivityTagsCollection {
|
|
{ "exception.type", exc.GetType().Name },
|
|
{ "exception.message", exc.Message },
|
|
{ "exception.stacktrace", exc.StackTrace }
|
|
}));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
LogTrace($"Server REDIS master non trovato", LogLevel.Error);
|
|
}
|
|
// aggiunta tags + log
|
|
activity?.SetTag("data.source", source);
|
|
activity?.SetTag("param.pat2Flush", pat2Flush);
|
|
LogTrace($"{pat2Flush} | {source} | trace: {activity?.TraceId} | {activity?.Duration.TotalMilliseconds}ms");
|
|
return answ;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Esegue flush memoria redis dato pat2Flush
|
|
/// </summary>
|
|
/// <param name="pat2Flush"></param>
|
|
/// <returns></returns>
|
|
protected async Task<bool> ExecFlushRedisPatternAsync(RedisValue pat2Flush)
|
|
{
|
|
bool answ = false;
|
|
using var activity = StartActivity();
|
|
string source = "REDIS";
|
|
/*******************************
|
|
* 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 / prendo primo o default
|
|
*******************************/
|
|
var connServ = _redisConn.GetEndPoints()
|
|
.Select(endpoint =>
|
|
{
|
|
var server = _redisConn.GetServer(endpoint);
|
|
return server;
|
|
})
|
|
.Where(x => x.IsConnected && !x.IsReplica)
|
|
.FirstOrDefault();
|
|
if (connServ != null)
|
|
{
|
|
// ciclo (anche se me ne aspetto 1 solo)
|
|
// se pat2Flush è "*" elimino intero DB...
|
|
if ((pat2Flush.Equals(new RedisValue("*")) || pat2Flush == RedisValue.Null))
|
|
{
|
|
connServ.FlushDatabase(database: _redisDb.Database);
|
|
}
|
|
else
|
|
{
|
|
try
|
|
{
|
|
var keys = connServ.Keys(database: _redisDb.Database, pattern: pat2Flush, pageSize: 1000);
|
|
|
|
var deleteTasks = new List<Task>();
|
|
foreach (var key in keys)
|
|
{
|
|
deleteTasks.Add(_redisDb.KeyDeleteAsync(key));
|
|
if (deleteTasks.Count >= 1000)
|
|
{
|
|
await Task.WhenAll(deleteTasks);
|
|
deleteTasks.Clear();
|
|
}
|
|
}
|
|
if (deleteTasks.Count > 0)
|
|
{
|
|
await Task.WhenAll(deleteTasks);
|
|
}
|
|
answ = true;
|
|
}
|
|
catch (Exception exc)
|
|
{
|
|
string exMsg = $"Eccezione durante ExecFlushRedisPatternAsync | pat2Flush: {pat2Flush}";
|
|
LogTrace($"{exMsg}{Environment.NewLine}{exc}", LogLevel.Error);
|
|
// traccio errore
|
|
activity?.SetStatus(ActivityStatusCode.Error, exc.Message);
|
|
activity?.AddEvent(new ActivityEvent("exception", tags: new ActivityTagsCollection {
|
|
{ "exception.type", exc.GetType().Name },
|
|
{ "exception.message", exc.Message },
|
|
{ "exception.stacktrace", exc.StackTrace }
|
|
}));
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
LogTrace($"Server REDIS master non trovato", LogLevel.Error);
|
|
}
|
|
// aggiunta tags + log
|
|
activity?.SetTag("data.source", source);
|
|
activity?.SetTag("param.pat2Flush", pat2Flush);
|
|
LogTrace($"{pat2Flush} | {source} | trace: {activity?.TraceId} | {activity?.Duration.TotalMilliseconds}ms");
|
|
return answ;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Helper trace messaggio log (SE abilitato)
|
|
/// </summary>
|
|
/// <param name="traceMsg"></param>
|
|
protected new void LogTrace(string traceMsg, NLog.LogLevel? reqLevel = null, [CallerMemberName] string? methodName = null)
|
|
{
|
|
if (!_traceEnabled)
|
|
return;
|
|
|
|
reqLevel ??= NLog.LogLevel.Debug;
|
|
|
|
// Loggo!
|
|
Log.Log(reqLevel, $"{methodName} | {traceMsg}");
|
|
}
|
|
|
|
#endregion Protected Methods
|
|
|
|
#region Private Fields
|
|
|
|
private new static Logger Log = LogManager.GetCurrentClassLogger();
|
|
private readonly IServiceProvider _serviceProvider;
|
|
private string redisBaseKey = "Lux:Cache";
|
|
|
|
#endregion Private Fields
|
|
|
|
#region Private Properties
|
|
|
|
private static DataSimulatorController dataSimController { get; set; } = null!;
|
|
private static LuxController dbController { get; set; } = null!;
|
|
|
|
#endregion Private Properties
|
|
}
|
|
} |