diff --git a/EgwCoreLib.Lux.Data/Controllers/LuxController.cs b/EgwCoreLib.Lux.Data/Controllers/LuxController.cs
index 438ab67..69fef0f 100644
--- a/EgwCoreLib.Lux.Data/Controllers/LuxController.cs
+++ b/EgwCoreLib.Lux.Data/Controllers/LuxController.cs
@@ -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
///
internal async Task 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
+ ///
+ /// Esegue insert statistiche aggregate sul DB
+ ///
+ /// Elenco dei record da inserire
+ /// Se true preventivamente elimina record nel periodo richiesto
+ ///
+ internal async Task StatsAggrUpsertAsync(List 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;
+ }
+
+ ///
+ /// Esegue insert statistiche di dettaglio sul DB
+ ///
+ /// Elenco dei record da inserire
+ /// Se true preventivamente elimina record nel periodo richiesto
+ ///
+ internal async Task StatsDetailUpsertAsync(List 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;
+ }
+
///
/// Elenco completo Tags
///
diff --git a/EgwCoreLib.Lux.Data/DataLayerContext.cs b/EgwCoreLib.Lux.Data/DataLayerContext.cs
index 0ae8606..30ecb1e 100644
--- a/EgwCoreLib.Lux.Data/DataLayerContext.cs
+++ b/EgwCoreLib.Lux.Data/DataLayerContext.cs
@@ -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 DbSetStockMov { get; set; }
public virtual DbSet DbSetGenClass { get; set; }
public virtual DbSet DbSetGenVal { get; set; }
-
-
+ public virtual DbSet DbSetStatsDet { get; set; }
+ public virtual DbSet DbSetStatsAggr { get; set; }
partial void OnModelCreatingPartial(ModelBuilder modelBuilder);
diff --git a/EgwCoreLib.Lux.Data/Services/CalcRuidService.cs b/EgwCoreLib.Lux.Data/Services/CalcRuidService.cs
index 15ab203..2c4c78a 100644
--- a/EgwCoreLib.Lux.Data/Services/CalcRuidService.cs
+++ b/EgwCoreLib.Lux.Data/Services/CalcRuidService.cs
@@ -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
///
/// Gestione servizio indice richieste
///
- 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;
}
-
///
/// Metodo di Cleanup periodico
///
@@ -126,6 +145,57 @@ namespace EgwCoreLib.Lux.Data.Services
await Task.WhenAll(tasks);
}
+ ///
+ /// Metodo di Cleanup dato periodo limite prima del quale va eliminato l'elenco dei dati
+ ///
+ /// Environment calcolo
+ /// Tipologia richiesta
+ /// Limite temporale dati da eliminare
+ ///
+ 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();
+
+ 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);
+ }
+
///
/// Metodo di Aggiornamento richiesta esistente
///
@@ -174,7 +244,6 @@ namespace EgwCoreLib.Lux.Data.Services
await Task.WhenAll(t1, t2, t3);
}
-
///
/// Metodo Recupero combinazioni envir/tipo
///
@@ -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
///