562 lines
21 KiB
C#
562 lines
21 KiB
C#
using MP.Data;
|
|
using MP.Data.Conf;
|
|
using MP.Data.DatabaseModels;
|
|
using Newtonsoft.Json;
|
|
using NLog;
|
|
using StackExchange.Redis;
|
|
using System.Diagnostics;
|
|
|
|
namespace MP.SPEC.Data
|
|
{
|
|
public class MpDataService : IDisposable
|
|
{
|
|
#region Public Constructors
|
|
|
|
public MpDataService(IConfiguration configuration, ILogger<MpDataService> logger)
|
|
{
|
|
_logger = logger;
|
|
_logger.LogInformation("Starting MpDataService INIT");
|
|
_configuration = configuration;
|
|
|
|
// setup compoenti REDIS
|
|
redisConn = ConnectionMultiplexer.Connect(_configuration.GetConnectionString("Redis"));
|
|
redisDb = redisConn.GetDatabase();
|
|
|
|
// leggo cache lungo periodo
|
|
int.TryParse(_configuration.GetValue<string>("ServerConf:redisLongTimeCache"), out redisLongTimeCache);
|
|
|
|
_logger.LogInformation("Redis INIT");
|
|
|
|
// setup canali pub/sub
|
|
dataPipe = new MessagePipe(redisConn, Constants.ACT_MSE_DATA_KEY);
|
|
blinkPipe = new MessagePipe(redisConn, Constants.ACT_BLINK_KEY);
|
|
|
|
// conf DB
|
|
string connStr = _configuration.GetConnectionString("Mp.Data");
|
|
if (string.IsNullOrEmpty(connStr))
|
|
{
|
|
_logger.LogError("DbController: ConnString empty!");
|
|
}
|
|
else
|
|
{
|
|
dbController = new MP.Data.Controllers.MpSpecController(configuration);
|
|
_logger.LogInformation("DbController OK");
|
|
}
|
|
}
|
|
|
|
#endregion Public Constructors
|
|
|
|
#region Public Properties
|
|
|
|
public static MP.Data.Controllers.MpSpecController dbController { get; set; } = null!;
|
|
|
|
public MessagePipe blinkPipe { get; set; } = null!;
|
|
|
|
/// <summary>
|
|
/// Dizionario dei tag configurati per IOB
|
|
/// </summary>
|
|
public Dictionary<string, List<TagData>> currTagConf { get; set; } = new Dictionary<string, List<TagData>>();
|
|
|
|
public MessagePipe dataPipe { get; set; } = null!;
|
|
|
|
#endregion Public Properties
|
|
|
|
#region Public Methods
|
|
|
|
public async Task<List<ListValues>> AnagStatiComm()
|
|
{
|
|
Stopwatch stopWatch = new Stopwatch();
|
|
stopWatch.Start();
|
|
List<ListValues>? result = new List<ListValues>();
|
|
// cerco in redis...
|
|
RedisValue rawData = await redisDb.StringGetAsync(redisStatoCom);
|
|
if (!string.IsNullOrEmpty($"{rawData}"))
|
|
{
|
|
result = JsonConvert.DeserializeObject<List<ListValues>>($"{rawData}");
|
|
stopWatch.Stop();
|
|
TimeSpan ts = stopWatch.Elapsed;
|
|
Log.Debug($"AnagStatiComm Read from REDIS: {ts.TotalMilliseconds}ms");
|
|
}
|
|
else
|
|
{
|
|
result = await Task.FromResult(dbController.AnagStatiComm());
|
|
// serializzp e salvo...
|
|
rawData = JsonConvert.SerializeObject(result);
|
|
await redisDb.StringSetAsync(redisStatoCom, rawData, getRandTOut(redisLongTimeCache));
|
|
stopWatch.Stop();
|
|
TimeSpan ts = stopWatch.Elapsed;
|
|
Log.Debug($"AnagStatiComm Read from DB: {ts.TotalMilliseconds}ms");
|
|
}
|
|
if (result == null)
|
|
{
|
|
result = new List<ListValues>();
|
|
}
|
|
return result;
|
|
}
|
|
|
|
public async Task<List<ListValues>> AnagTipoArtLV()
|
|
{
|
|
Stopwatch stopWatch = new Stopwatch();
|
|
stopWatch.Start();
|
|
List<ListValues>? result = new List<ListValues>();
|
|
// cerco in redis...
|
|
RedisValue rawData = await redisDb.StringGetAsync(redisTipoArt);
|
|
if (!string.IsNullOrEmpty($"{rawData}"))
|
|
{
|
|
result = JsonConvert.DeserializeObject<List<ListValues>>($"{rawData}");
|
|
stopWatch.Stop();
|
|
TimeSpan ts = stopWatch.Elapsed;
|
|
Log.Debug($"AnagTipoArtLV Read from REDIS: {ts.TotalMilliseconds}ms");
|
|
}
|
|
else
|
|
{
|
|
result = await Task.FromResult(dbController.AnagTipoArtLV());
|
|
// serializzp e salvo...
|
|
rawData = JsonConvert.SerializeObject(result);
|
|
await redisDb.StringSetAsync(redisTipoArt, rawData, getRandTOut(redisLongTimeCache));
|
|
stopWatch.Stop();
|
|
TimeSpan ts = stopWatch.Elapsed;
|
|
Log.Debug($"AnagTipoArtLV Read from DB: {ts.TotalMilliseconds}ms");
|
|
}
|
|
if (result == null)
|
|
{
|
|
result = new List<ListValues>();
|
|
}
|
|
return result;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Eliminazione record selezionato
|
|
/// </summary>
|
|
/// <param name="currRec"></param>
|
|
/// <returns></returns>
|
|
public async Task<bool> ArticoliDeleteRecord(AnagArticoli currRec)
|
|
{
|
|
return await dbController.ArticoliDeleteRecord(currRec);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Restitusice elenco articoli cercati
|
|
/// </summary>
|
|
/// <param name="numRecord"></param>
|
|
/// <param name="searchVal"></param>
|
|
/// <returns></returns>
|
|
public async Task<List<AnagArticoli>> ArticoliGetSearch(int numRecord, string azienda, string searchVal)
|
|
{
|
|
return await Task.FromResult(dbController.ArticoliGetSearch(numRecord, azienda, searchVal));
|
|
}
|
|
|
|
/// <summary>
|
|
/// Aggiornamento record selezionato
|
|
/// </summary>
|
|
/// <param name="currRec"></param>
|
|
/// <returns></returns>
|
|
public async Task<bool> ArticoliUpdateRecord(AnagArticoli currRec)
|
|
{
|
|
return await dbController.ArticoliUpdateRecord(currRec);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Verifica se sia possiubile cancellare articolo dato suo CodArt cercando su redis o su
|
|
/// tab veto da DB
|
|
/// </summary>
|
|
/// <param name="CodArt"></param>
|
|
/// <returns></returns>
|
|
public bool ArticoloDelEnabled(object CodArt)
|
|
{
|
|
bool answ = false;
|
|
string codArticolo = $"{CodArt}";
|
|
int cacheCheckArtUsato = 1;
|
|
int.TryParse(_configuration.GetValue<string>("ServerConf:cacheCheckArtUsato"), out cacheCheckArtUsato);
|
|
TimeSpan TTLCache = getRandTOut(cacheCheckArtUsato);
|
|
// cerco in cache redis...
|
|
string redKeyArtUsed = $"{Utils.redKeyArtUsed}:{codArticolo}";
|
|
string redKeyTabCheckArt = Utils.redKeyTabCheckArt;
|
|
string rawData = redisDb.StringGet(redKeyArtUsed);
|
|
if (!string.IsNullOrEmpty(rawData))
|
|
{
|
|
bool.TryParse(rawData, out answ);
|
|
}
|
|
else
|
|
{
|
|
// controllo non sia stato mai prodotto sennò non posso cancellare...
|
|
try
|
|
{
|
|
// cerco in cache se ci sia la tabella con gli articoli impiegati...
|
|
string rawTable = redisDb.StringGet(redKeyTabCheckArt);
|
|
List<string> artList = new List<string>();
|
|
if (!string.IsNullOrEmpty(rawTable))
|
|
{
|
|
artList = JsonConvert.DeserializeObject<List<string>>(rawTable);
|
|
}
|
|
// rileggo...
|
|
if (artList == null || artList.Count == 0)
|
|
{
|
|
artList = new List<string>();
|
|
var tabArticoli = dbController.ArticoliGetUsed();
|
|
var codList = tabArticoli.Select(x => x.CodArticolo);
|
|
foreach (string cod in codList)
|
|
{
|
|
artList.Add(cod);
|
|
}
|
|
// SE fosse vuoto aggiungo comunque il cado "ND"...
|
|
if (artList.Count == 0)
|
|
{
|
|
artList.Add("ND");
|
|
}
|
|
// salvo
|
|
rawTable = JsonConvert.SerializeObject(artList);
|
|
redisDb.StringSet(redKeyTabCheckArt, rawTable, TTLCache);
|
|
}
|
|
// cerco nella tabella: se ci fosse --> disabilitato delete
|
|
bool usato = false;
|
|
if (artList != null && artList.Count > 0)
|
|
{
|
|
usato = artList.Contains(codArticolo);
|
|
}
|
|
answ = !usato;
|
|
redisDb.StringSet(redKeyArtUsed, $"{answ}", TTLCache);
|
|
}
|
|
catch
|
|
{ }
|
|
}
|
|
return answ;
|
|
}
|
|
|
|
private int redisLongTimeCache = 5;
|
|
|
|
public async Task<List<ConfigModel>> ConfigGetAll()
|
|
{
|
|
Stopwatch stopWatch = new Stopwatch();
|
|
stopWatch.Start();
|
|
List<ConfigModel>? result = new List<ConfigModel>();
|
|
// cerco in redis...
|
|
RedisValue rawData = await redisDb.StringGetAsync(redisConfKey);
|
|
if (!string.IsNullOrEmpty($"{rawData}"))
|
|
{
|
|
result = JsonConvert.DeserializeObject<List<ConfigModel>>($"{rawData}");
|
|
stopWatch.Stop();
|
|
TimeSpan ts = stopWatch.Elapsed;
|
|
Log.Debug($"ConfigGetAll Read from REDIS: {ts.TotalMilliseconds}ms");
|
|
}
|
|
else
|
|
{
|
|
result = await Task.FromResult(dbController.ConfigGetAll());
|
|
// serializzp e salvo...
|
|
rawData = JsonConvert.SerializeObject(result);
|
|
await redisDb.StringSetAsync(redisConfKey, rawData, getRandTOut(redisLongTimeCache));
|
|
stopWatch.Stop();
|
|
TimeSpan ts = stopWatch.Elapsed;
|
|
Log.Debug($"ConfigGetAll Read from DB: {ts.TotalMilliseconds}ms");
|
|
}
|
|
if (result == null)
|
|
{
|
|
result = new List<ConfigModel>();
|
|
}
|
|
return result;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Reset dati cache config
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
public async Task ConfigResetCache()
|
|
{
|
|
await redisDb.StringSetAsync(redisConfKey, "");
|
|
}
|
|
|
|
/// <summary>
|
|
/// Update chiave config
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
public async Task<bool> ConfigUpdate(ConfigModel updRec)
|
|
{
|
|
return await Task.FromResult(dbController.ConfigUpdate(updRec));
|
|
}
|
|
|
|
public void Dispose()
|
|
{
|
|
// Clear database controller
|
|
dbController.Dispose();
|
|
redisConn.Dispose();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Restitusice elenco aziende
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
public Task<List<AnagGruppi>> ElencoAziende()
|
|
{
|
|
return Task.FromResult(dbController.AnagGruppiAziende());
|
|
}
|
|
|
|
/// <summary>
|
|
/// Restitusice elenco fasi
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
public Task<List<AnagGruppi>> ElencoGruppiFase()
|
|
{
|
|
return Task.FromResult(dbController.AnagGruppiFase());
|
|
}
|
|
|
|
public Task<List<LinkMenu>> ElencoLink()
|
|
{
|
|
return Task.FromResult(dbController.ElencoLink());
|
|
}
|
|
|
|
/// <summary>
|
|
/// Elenco ultimi n record flux log dato macchina e flusso (ordinato x data registrazione)
|
|
/// </summary>
|
|
/// <param name="IdxMacchina">* = tutte, altrimenti solo x una data macchina</param>
|
|
/// <param name="CodFlux">*=tutti, altrimenti solo selezionato</param>
|
|
/// <param name="MaxRec">numero massimo record da restituire</param>
|
|
/// <returns></returns>
|
|
public async Task<List<FluxLog>> FluxLogGetLastFilt(string IdxMacchina, string CodFlux, int MaxRec)
|
|
{
|
|
Stopwatch stopWatch = new Stopwatch();
|
|
stopWatch.Start();
|
|
var results = await Task.FromResult(dbController.FluxLogGetLastFilt(IdxMacchina, CodFlux, MaxRec));
|
|
stopWatch.Stop();
|
|
TimeSpan ts = stopWatch.Elapsed;
|
|
Log.Debug($"FluxLogGetLastFilt | Read from DB: {ts.TotalMilliseconds}ms");
|
|
return results;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Elenco setup dei tag conf correnti
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
public Task<Dictionary<string, List<TagData>>> getAllTags()
|
|
{
|
|
return Task.FromResult(currTagConf);
|
|
}
|
|
|
|
/// <summary>
|
|
/// restituisce il valore da REDIS associato al tag richeisto
|
|
/// </summary>
|
|
/// <param name="redKey">Chiave in cui cercare il valore</param>
|
|
/// <returns></returns>
|
|
public string getTagConf(string redKey)
|
|
{
|
|
string outVal = "";
|
|
// cerco in REDIS la conf x l'IOB
|
|
var rawData = redisDb.StringGet(redKey);
|
|
if (!string.IsNullOrEmpty(rawData))
|
|
{
|
|
outVal = $"{rawData}";
|
|
}
|
|
return outVal;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Elenco ODL filtrati x stato, articolo, KeyRich (che contiene stato)
|
|
/// </summary>
|
|
/// <param name="inCorso">Stato ODL: true=in corso/completato</param>
|
|
/// <param name="codArt">Cod articolo</param>
|
|
/// <param name="keyRichPart">KeyRich (parziale) da cercare (es cod stato x yacht)</param>
|
|
/// <returns></returns>
|
|
public async Task<List<ODLModel>> ListODLFilt(bool inCorso, string codArt, string keyRichPart)
|
|
{
|
|
return await Task.FromResult(dbController.ListODLFilt(inCorso, codArt, keyRichPart));
|
|
}
|
|
|
|
/// <summary>
|
|
/// Elenco PODL non avviati filtrati x articolo, KeyRich (che contiene stato)
|
|
/// </summary>
|
|
/// <param name="codArt">Cod articolo</param>
|
|
/// <param name="keyRichPart">KeyRich (parziale) da cercare (es cod stato x yacht)</param>
|
|
/// <returns></returns>
|
|
public async Task<List<PODLModel>> ListPODLFilt(string codArt, string keyRichPart)
|
|
{
|
|
return await Task.FromResult(dbController.ListPODLFilt(codArt, keyRichPart));
|
|
}
|
|
|
|
/// <summary>
|
|
/// Elenco di tutte le macchine gestite
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
public async Task<List<Macchine>> MacchineGetAll()
|
|
{
|
|
List<Macchine>? result = new List<Macchine>();
|
|
Stopwatch stopWatch = new Stopwatch();
|
|
stopWatch.Start();
|
|
string readType = "DB";
|
|
string currKey = redisMacList;
|
|
// cerco in redis dato valore sel macchina...
|
|
RedisValue rawData = redisDb.StringGet(currKey);
|
|
if (rawData.HasValue)
|
|
{
|
|
result = JsonConvert.DeserializeObject<List<Macchine>>($"{rawData}");
|
|
readType = "REDIS";
|
|
}
|
|
else
|
|
{
|
|
result = await Task.FromResult(dbController.MacchineGetAll());
|
|
// serializzp e salvo...
|
|
rawData = JsonConvert.SerializeObject(result);
|
|
redisDb.StringSet(currKey, rawData, getRandTOut(redisLongTimeCache));
|
|
}
|
|
if (result == null)
|
|
{
|
|
result = new List<Macchine>();
|
|
}
|
|
stopWatch.Stop();
|
|
TimeSpan ts = stopWatch.Elapsed;
|
|
Log.Debug($"MacchineGetAll | Read from {readType}: {ts.TotalMilliseconds}ms");
|
|
return result;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Elenco ID macchine con dati FluxLog gestite
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
public async Task<List<string>> MacchineWithFlux()
|
|
{
|
|
List<string>? result = new List<string>();
|
|
Stopwatch stopWatch = new Stopwatch();
|
|
stopWatch.Start();
|
|
string readType = "DB";
|
|
string currKey = redisMacByFlux;
|
|
// cerco in redis dato valore sel macchina...
|
|
RedisValue rawData = redisDb.StringGet(currKey);
|
|
if (rawData.HasValue)
|
|
{
|
|
result = JsonConvert.DeserializeObject<List<string>>($"{rawData}");
|
|
readType = "REDIS";
|
|
}
|
|
else
|
|
{
|
|
result = await Task.FromResult(dbController.MacchineWithFlux());
|
|
// serializzp e salvo...
|
|
rawData = JsonConvert.SerializeObject(result);
|
|
redisDb.StringSet(currKey, rawData, getRandTOut(redisLongTimeCache));
|
|
}
|
|
if (result == null)
|
|
{
|
|
result = new List<string>();
|
|
}
|
|
stopWatch.Stop();
|
|
TimeSpan ts = stopWatch.Elapsed;
|
|
Log.Debug($"MacchineWithFlux | Read from {readType}: {ts.TotalMilliseconds}ms");
|
|
return result;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Elenco di tutti i parametri filtrati x macchina
|
|
/// </summary>
|
|
/// <param name="IdxMacchina">* = tutte, altrimenti solo x una data macchina</param>
|
|
/// <returns></returns>
|
|
public async Task<List<string>> ParametriGetFilt(string IdxMacchina)
|
|
{
|
|
List<string>? result = new List<string>();
|
|
Stopwatch stopWatch = new Stopwatch();
|
|
stopWatch.Start();
|
|
string readType = "DB";
|
|
string currKey = $"{redisFluxByMac}:{IdxMacchina}";
|
|
// cerco in redis dato valore sel macchina...
|
|
RedisValue rawData = redisDb.StringGet(currKey);
|
|
if (rawData.HasValue)
|
|
{
|
|
result = JsonConvert.DeserializeObject<List<string>>($"{rawData}");
|
|
readType = "REDIS";
|
|
}
|
|
else
|
|
{
|
|
result = await Task.FromResult(dbController.ParametriGetFilt(IdxMacchina));
|
|
// serializzp e salvo...
|
|
rawData = JsonConvert.SerializeObject(result);
|
|
redisDb.StringSet(currKey, rawData, getRandTOut(redisLongTimeCache));
|
|
}
|
|
if (result == null)
|
|
{
|
|
result = new List<string>();
|
|
}
|
|
stopWatch.Stop();
|
|
TimeSpan ts = stopWatch.Elapsed;
|
|
Log.Debug($"ParametriGetFilt | Read from {readType}: {ts.TotalMilliseconds}ms");
|
|
return result;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Eliminazione record selezionato
|
|
/// </summary>
|
|
/// <param name="currRec"></param>
|
|
/// <returns></returns>
|
|
public async Task<bool> PODLDeleteRecord(PODLModel currRec)
|
|
{
|
|
return await dbController.PODLDeleteRecord(currRec);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Aggiornamento record selezionato
|
|
/// </summary>
|
|
/// <param name="currRec"></param>
|
|
/// <returns></returns>
|
|
public async Task<bool> POdlUpdateRecord(PODLModel currRec)
|
|
{
|
|
return await dbController.PODLUpdateRecord(currRec);
|
|
}
|
|
|
|
public async Task<bool> FlushRedisCache()
|
|
{
|
|
bool answ = false;
|
|
var server = redisConn.GetServer("localhost:6379");
|
|
//await Task.Delay(1);
|
|
if (server != null)
|
|
{
|
|
await server.FlushDatabaseAsync();
|
|
answ = true;
|
|
}
|
|
return answ;
|
|
}
|
|
|
|
#endregion Public Methods
|
|
|
|
#region Protected Fields
|
|
|
|
protected Random rand = new Random();
|
|
|
|
#endregion Protected Fields
|
|
|
|
#region Protected Methods
|
|
|
|
/// <summary>
|
|
/// Restituisce un timeout dai minuti richiesti + tempo random 1..60 sec
|
|
/// </summary>
|
|
/// <param name="stdMinutes"></param>
|
|
/// <returns></returns>
|
|
protected TimeSpan getRandTOut(int stdMinutes)
|
|
{
|
|
double rndValue = (double)stdMinutes + (double)rand.Next(1, 60) / 60;
|
|
return TimeSpan.FromMinutes(rndValue);
|
|
}
|
|
|
|
#endregion Protected Methods
|
|
|
|
#region Private Fields
|
|
|
|
private const string redisConfKey = "MP:SPEC:Cache:Config";
|
|
private const string redisFluxByMac = "MP:SPEC:Cache:FluxByMac";
|
|
private const string redisMacByFlux = "MP:SPEC:Cache:MacByFlux";
|
|
private const string redisMacList = "MP:SPEC:Cache:MacList";
|
|
private const string redisStatoCom = "MP:SPEC:Cache:StatoCom";
|
|
private const string redisTipoArt = "MP:SPEC:Cache:TipoArt";
|
|
private static IConfiguration _configuration = null!;
|
|
|
|
private static ILogger<MpDataService> _logger = null!;
|
|
|
|
private static Logger Log = LogManager.GetCurrentClassLogger();
|
|
|
|
/// <summary>
|
|
/// Oggetto per connessione a REDIS
|
|
/// </summary>
|
|
private ConnectionMultiplexer redisConn = null!;
|
|
|
|
/// <summary>
|
|
/// Oggetto DB redis da impiegare x chiamate R/W
|
|
/// </summary>
|
|
private IDatabase redisDb = null!;
|
|
|
|
#endregion Private Fields
|
|
}
|
|
} |