Files
mapo-mono/MP.MONO.UI/Data/CurrentDataService.cs
T
2022-03-07 17:24:08 +01:00

263 lines
9.2 KiB
C#

using Microsoft.Extensions.Caching.Distributed;
using Microsoft.Extensions.Caching.Memory;
using MP.MONO.Core.DTO;
using MP.MONO.Data;
using MP.MONO.Data.Controllers;
using Newtonsoft.Json;
using NLog;
using StackExchange.Redis;
using System.Diagnostics;
using System.Text;
using StackExchange.Redis;
namespace MP.MONO.UI.Data
{
public class CurrentDataService : IDisposable
{
#region Private Fields
private static IConfiguration _configuration;
private static ILogger<CurrentDataService> _logger;
private static NLog.Logger Log = LogManager.GetCurrentClassLogger();
private readonly IDistributedCache distributedCache;
/// <summary>
/// Oggetto per connessione a REDIS
/// </summary>
private ConnectionMultiplexer redisConn = null!;
//ISubscriber sub = redis.GetSubscriber();
/// <summary>
/// Oggetto DB redis da impiegare x chiamate R/W
/// </summary>
private IDatabase redisDb = null!;
/// <summary>
/// Durata assoluta massima della cache IN SECONDI
/// </summary>
private int chAbsExp = 60 * 5;
/// <summary>
/// Durata della cache IN SECONDI in modalità inattiva (non acceduta) prima di venire rimossa
/// NON estende oltre il tempo massimo di validità della cache (chAbsExp)
/// </summary>
private int chSliExp = 60 * 1;
#endregion Private Fields
#region Public Fields
/// <summary>
/// Controller dati da DB
/// </summary>
public static MpDbController dbController;
/// <summary>
/// Controller dati simulati
/// </summary>
public static SimController simGen;
#endregion Public Fields
public MessagePipe alarmPipe { get; set; } = null!;
public MessagePipe parametersPipe { get; set; } = null!;
public MessagePipe statusPipe { get; set; } = null!;
#region Public Constructors
public CurrentDataService(IConfiguration configuration, ILogger<CurrentDataService> logger, IDistributedCache distributedCache, IConnectionMultiplexer redisConn)
{
_logger = logger;
_configuration = configuration;
// setup compoenti REDIS
this.redisConn = ConnectionMultiplexer.Connect(_configuration.GetConnectionString("Redis"));
this.redisDb = this.redisConn.GetDatabase();
// setup canali pub/sub
alarmPipe = new MessagePipe(redisConn, "allarms");
parametersPipe = new MessagePipe(redisConn, "parameters");
statusPipe = new MessagePipe(redisConn, "status");
// conf cache
this.distributedCache = distributedCache;
// conf DB
string connStr = _configuration.GetConnectionString("MP.MONO.Data");
if (string.IsNullOrEmpty(connStr))
{
_logger.LogError("ConnString empty!");
}
else
{
dbController = new MpDbController(configuration);
_logger.LogInformation("DbController OK");
}
simGen = new SimController();
}
#endregion Public Constructors
#region Protected Properties
#if false
protected Dictionary<string, string>? ParametersList { get; set; } = new Dictionary<string, string>();
#endif
#endregion Protected Properties
#region Private Methods
/// <summary>
/// Hash Redis contenente i dati MP di una specifico TYPE (es StatusMacchina, StateMachineIngressi, ...)
/// </summary>
/// <param name="dataType"></param>
/// <returns></returns>
private static string mHash(string dataType)
{
return $"MAPO-MONO:{dataType}";
}
private DistributedCacheEntryOptions cacheOpt(bool fastCache)
{
var numSecAbsExp = fastCache ? chAbsExp : chAbsExp * 10;
var numSecSliExp = fastCache ? chSliExp : chSliExp * 10;
return new DistributedCacheEntryOptions().SetAbsoluteExpiration(DateTime.Now.AddSeconds(numSecAbsExp)).SetSlidingExpiration(TimeSpan.FromSeconds(numSecSliExp));
}
#endregion Private Methods
#region Public Methods
public void Dispose()
{
// Clear database controller
dbController.Dispose();
}
#if false
public async Task<Dictionary<string, string>> GetCurrentParameters()
{
ParametersList = new Dictionary<string, string>();
string cacheKey = mHash("Machine:Parameters:Current");
string rawData = await redisDb.StringGetAsync(cacheKey);
if (!string.IsNullOrEmpty(rawData))
{
ParametersList = JsonConvert.DeserializeObject<Dictionary<string, string>>(rawData);
}
else
{
ParametersList = simGen.GetCurrentParameters();
rawData = JsonConvert.SerializeObject(ParametersList);
await redisDb.StringSetAsync(cacheKey, rawData);
}
return ParametersList;
}
#endif
public async Task<List<DisplayDataDTO>> MachineDisplay()
{
List<DisplayDataDTO>? dbResult = new List<DisplayDataDTO>();
string cacheKey = mHash("Machine:Parameters:Current");
string rawData = await redisDb.StringGetAsync(cacheKey);
if (!string.IsNullOrEmpty(rawData))
{
dbResult = JsonConvert.DeserializeObject<List<DisplayDataDTO>>(rawData);
}
#if false
else
{
dbResult = simGen.MachineGetParameters();
rawData = JsonConvert.SerializeObject(dbResult);
await redisDb.StringSetAsync(cacheKey, rawData);
}
#endif
if (dbResult == null)
{
dbResult = new List<DisplayDataDTO>();
}
#if false
string rawData;
var redisDataList = await distributedCache.GetAsync(cacheKey);
if (redisDataList != null)
{
rawData = Encoding.UTF8.GetString(redisDataList);
dbResult = JsonConvert.DeserializeObject<List<DisplayDataDTO>>(rawData);
}
else
{
Stopwatch stopWatch = new Stopwatch();
stopWatch.Start();
dbResult = dbController.MachineGetDisplay();
rawData = JsonConvert.SerializeObject(dbResult);
redisDataList = Encoding.UTF8.GetBytes(rawData);
// tolgo salvataggio x sim meglio
//await distributedCache.SetAsync(cacheKey, redisDataList, cacheOpt(true));
stopWatch.Stop();
TimeSpan ts = stopWatch.Elapsed;
Log.Trace($"Effettuata lettura da DB + caching per MachineDisplay: {ts.TotalMilliseconds} ms");
}
if (dbResult == null)
{
dbResult = new List<DisplayDataDTO>();
}
#endif
return await Task.FromResult(dbResult);
}
public async Task<ProductionDTO> MachineProd()
{
ProductionDTO? dbResult = new ProductionDTO();
string cacheKey = mHash("DATA:Machine:Prod");
string rawData;
var redisDataList = await distributedCache.GetAsync(cacheKey);
if (redisDataList != null)
{
rawData = Encoding.UTF8.GetString(redisDataList);
dbResult = JsonConvert.DeserializeObject<ProductionDTO>(rawData);
}
else
{
Stopwatch stopWatch = new Stopwatch();
stopWatch.Start();
dbResult = dbController.MachineGetProd();
rawData = JsonConvert.SerializeObject(dbResult);
redisDataList = Encoding.UTF8.GetBytes(rawData);
// tolgo salvataggio x sim meglio
//await distributedCache.SetAsync(cacheKey, redisDataList, cacheOpt(true));
stopWatch.Stop();
TimeSpan ts = stopWatch.Elapsed;
Log.Trace($"Effettuata lettura da DB + caching per MachineProd: {ts.TotalMilliseconds} ms");
}
if (dbResult == null)
{
dbResult = new ProductionDTO();
}
return await Task.FromResult(dbResult);
}
public async Task<MachineDTO> MachineStatus()
{
MachineDTO? dbResult = new MachineDTO();
string cacheKey = mHash("Machine:Status:Current");
string rawData = await redisDb.StringGetAsync(cacheKey);
if (!string.IsNullOrEmpty(rawData))
{
dbResult = JsonConvert.DeserializeObject<MachineDTO>(rawData);
}
#if false
else
{
dbResult = simGen.MachineGetStatus();
rawData = JsonConvert.SerializeObject(dbResult);
redisDb.StringSetAsync(cacheKey, rawData);
}
#endif
if (dbResult == null)
{
dbResult = new MachineDTO();
}
return await Task.FromResult(dbResult);
}
#endregion Public Methods
}
}