Aggiunta gestione salvataggio range statistiche

This commit is contained in:
2025-12-16 14:19:59 +01:00
parent c71f9f9da2
commit dfee4cd1d8
3 changed files with 179 additions and 12 deletions
@@ -4,6 +4,7 @@ using EgwCoreLib.Lux.Data.DbModel.Cost;
using EgwCoreLib.Lux.Data.DbModel.Items;
using EgwCoreLib.Lux.Data.DbModel.Production;
using EgwCoreLib.Lux.Data.DbModel.Sales;
using EgwCoreLib.Lux.Data.DbModel.Stats;
using EgwCoreLib.Lux.Data.DbModel.Task;
using EgwCoreLib.Lux.Data.DbModel.Utils;
using Microsoft.EntityFrameworkCore;
@@ -2519,7 +2520,7 @@ namespace EgwCoreLib.Lux.Data.Controllers
/// <returns></returns>
internal async Task<OrderModel?> OrderFromOffer(OfferModel rec2clone)
{
OrderModel? newRec = null;
OrderModel? newRec = null;
//using (DataLayerContext dbCtx = new DataLayerContext(_config))
using (DataLayerContext dbCtx = new DataLayerContext())
{
@@ -2610,7 +2611,7 @@ namespace EgwCoreLib.Lux.Data.Controllers
if (numSave > 0 && newRec != null)
{
#if false
orderId = newRec.OrderID;
orderId = newRec.OrderID;
#endif
// sistemo UID...
foreach (var item in newRec.OrderRowNav)
@@ -2660,7 +2661,7 @@ namespace EgwCoreLib.Lux.Data.Controllers
}
return newRec;
#if false
return orderId;
return orderId;
#endif
}
@@ -3282,6 +3283,94 @@ namespace EgwCoreLib.Lux.Data.Controllers
}
#endif
/// <summary>
/// Esegue insert statistiche aggregate sul DB
/// </summary>
/// <param name="listRecords">Elenco dei record da inserire</param>
/// <param name="removeOld">Se true preventivamente elimina record nel periodo richiesto</param>
/// <returns></returns>
internal async Task<long> StatsAggrUpsertAsync(List<StatsAggregated> listRecords, bool removeOld)
{
int answ = 0;
//using (DataLayerContext dbCtx = new DataLayerContext(_config))
using (DataLayerContext dbCtx = new DataLayerContext())
{
// in primis se richiesto calcolo range periodo e svuoto...
if (removeOld)
{
var firstRec = listRecords.OrderBy(x => x.Hour).FirstOrDefault();
var lastRec = listRecords.OrderByDescending(x => x.Hour).FirstOrDefault();
if (firstRec != null && lastRec != null)
{
DateTime startDate = firstRec.Hour;
DateTime endDate = lastRec.Hour;
// uso direttamente ExecuteDelete
await dbCtx
.DbSetStatsAggr
.Where(x => x.Hour >= startDate && x.Hour < endDate)
.ExecuteDeleteAsync();
}
}
// ora preparo inserimento massivo
await dbCtx
.DbSetStatsAggr
.AddRangeAsync(listRecords);
// salvo!
answ = await dbCtx.SaveChangesAsync();
// libero memoria del changeTracker
dbCtx.ChangeTracker.Clear();
}
return answ;
}
/// <summary>
/// Esegue insert statistiche di dettaglio sul DB
/// </summary>
/// <param name="listRecords">Elenco dei record da inserire</param>
/// <param name="removeOld">Se true preventivamente elimina record nel periodo richiesto</param>
/// <returns></returns>
internal async Task<long> StatsDetailUpsertAsync(List<StatsDetail> listRecords, bool removeOld)
{
int answ = 0;
//using (DataLayerContext dbCtx = new DataLayerContext(_config))
using (DataLayerContext dbCtx = new DataLayerContext())
{
// in primis se richiesto calcolo range periodo e svuoto...
if (removeOld)
{
var firstRec = listRecords.OrderBy(x => x.Hour).FirstOrDefault();
var lastRec = listRecords.OrderByDescending(x => x.Hour).FirstOrDefault();
if (firstRec != null && lastRec != null)
{
DateTime startDate = firstRec.Hour;
DateTime endDate = lastRec.Hour;
// uso direttamente ExecuteDelete
await dbCtx
.DbSetStatsDet
.Where(x => x.Hour >= startDate && x.Hour < endDate)
.ExecuteDeleteAsync();
}
}
// ora preparo inserimento massivo
await dbCtx
.DbSetStatsDet
.AddRangeAsync(listRecords);
// salvo!
answ = await dbCtx.SaveChangesAsync();
// libero memoria del changeTracker
dbCtx.ChangeTracker.Clear();
}
return answ;
}
/// <summary>
/// Elenco completo Tags
/// </summary>
+3 -2
View File
@@ -3,6 +3,7 @@ using EgwCoreLib.Lux.Data.DbModel.Cost;
using EgwCoreLib.Lux.Data.DbModel.Items;
using EgwCoreLib.Lux.Data.DbModel.Production;
using EgwCoreLib.Lux.Data.DbModel.Sales;
using EgwCoreLib.Lux.Data.DbModel.Stats;
using EgwCoreLib.Lux.Data.DbModel.Stock;
using EgwCoreLib.Lux.Data.DbModel.Task;
using EgwCoreLib.Lux.Data.DbModel.Utils;
@@ -77,8 +78,8 @@ namespace EgwCoreLib.Lux.Data
public virtual DbSet<StockMovModel> DbSetStockMov { get; set; }
public virtual DbSet<GenClassModel> DbSetGenClass { get; set; }
public virtual DbSet<GenValueModel> DbSetGenVal { get; set; }
public virtual DbSet<StatsDetail> DbSetStatsDet { get; set; }
public virtual DbSet<StatsAggregated> DbSetStatsAggr { get; set; }
partial void OnModelCreatingPartial(ModelBuilder modelBuilder);
@@ -1,8 +1,14 @@
using EgwCoreLib.Lux.Core.Stats;
using EgwCoreLib.Lux.Data.Controllers;
using EgwCoreLib.Lux.Data.DbModel.Stats;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using NLog;
using StackExchange.Redis;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace EgwCoreLib.Lux.Data.Services
@@ -10,16 +16,30 @@ namespace EgwCoreLib.Lux.Data.Services
/// <summary>
/// Gestione servizio indice richieste
/// </summary>
public class CalcRuidService
public class CalcRuidService : BaseServ
{
#region Public Constructors
public CalcRuidService(ConnectionMultiplexer redis, TimeSpan retention, string redisBaseKey)
public CalcRuidService(IConfiguration configuration, IConnectionMultiplexer redisConn, string redisBaseKey, TimeSpan retention, TimeSpan archivePeriod) : base(configuration, redisConn)
{
_db = redis.GetDatabase();
_retention = retention;
_db = redisConn.GetDatabase();
_base = redisBaseKey.TrimEnd(':');
//_base = redisBaseKey.EndsWith(":") ? redisBaseKey : redisBaseKey + ":";
_retention = retention;
_archivePeriod = archivePeriod;
// conf DB
string connStr = BaseServ._config.GetConnectionString("Lux.All") ?? "";
if (string.IsNullOrEmpty(connStr))
{
Log.Error("ConnString empty!");
}
else
{
//dbController = new Controllers.LuxController(_config);
dbController = new LuxController();
StringBuilder sb = new StringBuilder();
sb.AppendLine($"CalcRuidService | LuxController OK");
Log.Info(sb.ToString());
}
}
#endregion Public Constructors
@@ -75,7 +95,6 @@ namespace EgwCoreLib.Lux.Data.Services
return ruid;
}
/// <summary>
/// Metodo di Cleanup periodico
/// </summary>
@@ -126,6 +145,57 @@ namespace EgwCoreLib.Lux.Data.Services
await Task.WhenAll(tasks);
}
/// <summary>
/// Metodo di Cleanup dato periodo limite prima del quale va eliminato l'elenco dei dati
/// </summary>
/// <param name="environment">Environment calcolo</param>
/// <param name="tipo">Tipologia richiesta</param>
/// <param name="timeLimit">Limite temporale dati da eliminare</param>
/// <returns></returns>
public async Task CleanupOldRequestsAsync(string environment, string tipo, TimeSpan timeLimit)
{
var cutoff = DateTimeOffset.UtcNow.Add(-timeLimit).ToUnixTimeMilliseconds();
var setKey = GetSortedSetKey(environment, tipo);
var oldIds = await _db.SortedSetRangeByScoreAsync(setKey, stop: cutoff);
if (oldIds.Length == 0) return;
var batch = _db.CreateBatch();
var tasks = new List<Task>();
foreach (var id in oldIds)
{
var ruid = id.ToString();
var hashKey = GetRequestKey(ruid);
var uid = await _db.HashGetAsync(hashKey, "UID");
if (!uid.IsNull)
{
var uidKey = GetUidSetKey(uid);
tasks.Add(batch.SetRemoveAsync(uidKey, ruid));
tasks.Add(batch.SetLengthAsync(uidKey).ContinueWith(t =>
{
if (t.Result == 0)
_db.KeyDelete(uidKey);
}));
}
tasks.Add(batch.KeyDeleteAsync(hashKey));
}
tasks.Add(batch.SortedSetRemoveRangeByScoreAsync(setKey, double.NegativeInfinity, cutoff));
tasks.Add(batch.SortedSetLengthAsync(setKey).ContinueWith(t =>
{
if (t.Result == 0)
_db.KeyDelete(setKey);
}));
batch.Execute();
await Task.WhenAll(tasks);
}
/// <summary>
/// Metodo di Aggiornamento richiesta esistente
/// </summary>
@@ -174,7 +244,6 @@ namespace EgwCoreLib.Lux.Data.Services
await Task.WhenAll(t1, t2, t3);
}
/// <summary>
/// Metodo Recupero combinazioni envir/tipo
/// </summary>
@@ -290,6 +359,8 @@ namespace EgwCoreLib.Lux.Data.Services
#region Private Fields
private static Logger Log = LogManager.GetCurrentClassLogger();
private readonly TimeSpan _archivePeriod;
private readonly string _base;
private readonly IDatabase _db;
private readonly TimeSpan _retention;
@@ -297,6 +368,12 @@ namespace EgwCoreLib.Lux.Data.Services
#endregion Private Fields
#region Private Properties
private static LuxController dbController { get; set; } = null!;
#endregion Private Properties
#region Private Methods
/// <summary>