diff --git a/MP.Core/Objects/MachDataItem.cs b/MP.Core/Objects/MachDataItem.cs new file mode 100644 index 00000000..dd89ab85 --- /dev/null +++ b/MP.Core/Objects/MachDataItem.cs @@ -0,0 +1,25 @@ +namespace MP.Core.Objects +{ + public class MachDataItem + { + public enum DataItemCategory + { + CONDITION = 0, + EVENT = 1, + SAMPLE = 2 + } + + public string Uuid { get; set; } = ""; + + public DataItemCategory Category { get; set; } + + public string? Name { get; set; } = ""; + + public string? SubType { get; set; } = ""; + + public string? Type { get; set; } = ""; + + public string? Units { get; set; } = ""; + + } +} diff --git a/MP.Data/DataServiceCollectionExtensions.cs b/MP.Data/DataServiceCollectionExtensions.cs new file mode 100644 index 00000000..4fa52ee2 --- /dev/null +++ b/MP.Data/DataServiceCollectionExtensions.cs @@ -0,0 +1,48 @@ +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; +using MP.Data.Repository.Mtc; +using MP.Data.Repository.Utils; +using MP.Data.Services.Mtc; +using MP.Data.Services.Utils; + +namespace MP.Data +{ + public static class DataServiceCollectionExtensions + { + public static IServiceCollection AddIocDataLayer(this IServiceCollection services) + { + //// DbContextFactory: preferibile in Blazor Server e scenari concorrenti + //services.AddDbContextFactory(options => + // options.UseMySql(connectionString, ServerVersion.AutoDetect(connectionString))); + + //// servizi preliminari + ////services.TryAddSingleton(redisConn); + //services.TryAddSingleton(); + //services.TryAddSingleton(); + + // Repository Singleton + services.TryAddSingleton(); + + // Repository Scoped + services.TryAddScoped(); + services.TryAddScoped(); + + // Servizi Singleton + services.TryAddSingleton(); + + // Servizi Scoped + services.TryAddScoped(); + services.TryAddScoped(); + + //// aggiunta servizi finali Singleton... + //services.TryAddSingleton(); + //services.TryAddSingleton(); + //services.TryAddSingleton(); + //services.TryAddSingleton(); + //services.TryAddSingleton(); + + + return services; + } + } +} diff --git a/MP.Data/DbModels/Mtc/MtcSetupModel.cs b/MP.Data/DbModels/Mtc/MtcSetupModel.cs new file mode 100644 index 00000000..a6faef44 --- /dev/null +++ b/MP.Data/DbModels/Mtc/MtcSetupModel.cs @@ -0,0 +1,24 @@ +using MP.Core.Objects; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations.Schema; +using System.Text.Json; + +namespace MP.Data.DbModels.Mtc +{ + [Table("mtc_setup")] + public class MtcSetupModel + { + [Key] + public string IdxMacchina { get; set; } + + public string MtcDataItemsRaw { get; set; } = ""; + + [NotMapped] + public List MtcDataItems + { + get => string.IsNullOrWhiteSpace(MtcDataItemsRaw) ? new List() : JsonSerializer.Deserialize>(MtcDataItemsRaw) ?? new(); + set => MtcDataItemsRaw = JsonSerializer.Serialize(value); + } + } +} diff --git a/MP.Data/Migrations/MoonPro_Utils/20260423153623_AddMtcSetupModel.Designer.cs b/MP.Data/Migrations/MoonPro_Utils/20260423153623_AddMtcSetupModel.Designer.cs new file mode 100644 index 00000000..d8ac5a54 --- /dev/null +++ b/MP.Data/Migrations/MoonPro_Utils/20260423153623_AddMtcSetupModel.Designer.cs @@ -0,0 +1,127 @@ +// +using System; +using MP.Data; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace MP.Data.Migrations.MoonPro_Utils +{ + [DbContext(typeof(MoonPro_UtilsContext))] + [Migration("20260423153623_AddMtcSetupModel")] + partial class AddMtcSetupModel + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .UseCollation("SQL_Latin1_General_CP1_CI_AS") + .HasAnnotation("ProductVersion", "6.0.36") + .HasAnnotation("Relational:MaxIdentifierLength", 128); + + SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder, 1L, 1); + + modelBuilder.Entity("MP.Data.DbModels.Mtc.MtcSetupModel", b => + { + b.Property("IdxMacchina") + .HasColumnType("nvarchar(450)"); + + b.Property("MtcDataItemsRaw") + .HasColumnType("nvarchar(max)"); + + b.HasKey("IdxMacchina"); + + b.ToTable("mtc_setup"); + }); + + modelBuilder.Entity("MP.Data.DbModels.Utils.StatsAggregatedModel", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id"), 1L, 1); + + b.Property("AvgDuration") + .HasColumnType("float"); + + b.Property("Destination") + .HasColumnType("nvarchar(450)"); + + b.Property("Hour") + .HasColumnType("datetime2"); + + b.Property("MachineId") + .HasColumnType("nvarchar(450)"); + + b.Property("MaxDuration") + .HasColumnType("float"); + + b.Property("MinDuration") + .HasColumnType("float"); + + b.Property("NoReply") + .HasColumnType("bigint"); + + b.Property("RequestCount") + .HasColumnType("bigint"); + + b.HasKey("Id"); + + b.HasIndex("Destination", "MachineId", "Hour") + .IsUnique() + .HasDatabaseName("idx_statsaggr_env_mach_hour") + .HasFilter("[Destination] IS NOT NULL AND [MachineId] IS NOT NULL"); + + b.ToTable("stats_aggr"); + }); + + modelBuilder.Entity("MP.Data.DbModels.Utils.StatsDetailModel", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id"), 1L, 1); + + b.Property("AvgDuration") + .HasColumnType("float"); + + b.Property("Destination") + .HasColumnType("nvarchar(450)"); + + b.Property("Hour") + .HasColumnType("datetime2"); + + b.Property("MaxDuration") + .HasColumnType("float"); + + b.Property("MinDuration") + .HasColumnType("float"); + + b.Property("NoReply") + .HasColumnType("bigint"); + + b.Property("RequestCount") + .HasColumnType("bigint"); + + b.Property("Type") + .HasColumnType("nvarchar(450)"); + + b.HasKey("Id"); + + b.HasIndex("Destination", "Type", "Hour") + .IsUnique() + .HasDatabaseName("idx_statsdet_hour_env_type") + .HasFilter("[Destination] IS NOT NULL AND [Type] IS NOT NULL"); + + b.ToTable("stats_detail"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/MP.Data/Migrations/MoonPro_Utils/20260423153623_AddMtcSetupModel.cs b/MP.Data/Migrations/MoonPro_Utils/20260423153623_AddMtcSetupModel.cs new file mode 100644 index 00000000..5873df04 --- /dev/null +++ b/MP.Data/Migrations/MoonPro_Utils/20260423153623_AddMtcSetupModel.cs @@ -0,0 +1,30 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace MP.Data.Migrations.MoonPro_Utils +{ + public partial class AddMtcSetupModel : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "mtc_setup", + columns: table => new + { + IdxMacchina = table.Column(type: "nvarchar(450)", nullable: false), + MtcDataItemsRaw = table.Column(type: "nvarchar(max)", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_mtc_setup", x => x.IdxMacchina); + }); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "mtc_setup"); + } + } +} diff --git a/MP.Data/Migrations/MoonPro_Utils/MoonPro_UtilsContextModelSnapshot.cs b/MP.Data/Migrations/MoonPro_Utils/MoonPro_UtilsContextModelSnapshot.cs index f935fcb6..531fb160 100644 --- a/MP.Data/Migrations/MoonPro_Utils/MoonPro_UtilsContextModelSnapshot.cs +++ b/MP.Data/Migrations/MoonPro_Utils/MoonPro_UtilsContextModelSnapshot.cs @@ -23,6 +23,19 @@ namespace MP.Data.Migrations.MoonPro_Utils SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder, 1L, 1); + modelBuilder.Entity("MP.Data.DbModels.Mtc.MtcSetupModel", b => + { + b.Property("IdxMacchina") + .HasColumnType("nvarchar(450)"); + + b.Property("MtcDataItemsRaw") + .HasColumnType("nvarchar(max)"); + + b.HasKey("IdxMacchina"); + + b.ToTable("mtc_setup"); + }); + modelBuilder.Entity("MP.Data.DbModels.Utils.StatsAggregatedModel", b => { b.Property("Id") diff --git a/MP.Data/MoonProContext.cs b/MP.Data/MoonProContext.cs index 975aaedd..70fb8f40 100644 --- a/MP.Data/MoonProContext.cs +++ b/MP.Data/MoonProContext.cs @@ -108,7 +108,6 @@ namespace MP.Data public virtual DbSet DbSetTksScore { get; set; } public virtual DbSet DbSetRemRebLog { get; set; } - #endregion Public Properties #region Private Methods @@ -151,27 +150,27 @@ namespace MP.Data modelBuilder.HasAnnotation("Relational:Collation", "SQL_Latin1_General_CP1_CI_AS"); modelBuilder.Entity(entity => - { - entity.HasKey(e => e.CodArticolo); + { + entity.HasKey(e => e.CodArticolo); - entity.ToView("v_UI_AnagArticoli"); + entity.ToView("v_UI_AnagArticoli"); - entity.Property(e => e.CodArticolo) - .IsRequired() - .HasMaxLength(50); + entity.Property(e => e.CodArticolo) + .IsRequired() + .HasMaxLength(50); - entity.Property(e => e.DescArticolo) - .IsRequired() - .HasMaxLength(250); + entity.Property(e => e.DescArticolo) + .IsRequired() + .HasMaxLength(250); - entity.Property(e => e.Disegno) - .IsRequired() - .HasMaxLength(50); + entity.Property(e => e.Disegno) + .IsRequired() + .HasMaxLength(50); - entity.Property(e => e.Tipo) - .IsRequired() - .HasMaxLength(50); - }); + entity.Property(e => e.Tipo) + .IsRequired() + .HasMaxLength(50); + }); modelBuilder.Entity(entity => { entity.HasKey(e => e.CodArticolo); diff --git a/MP.Data/MoonPro_UtilsContext.cs b/MP.Data/MoonPro_UtilsContext.cs index bbcc6ac7..2875ed97 100644 --- a/MP.Data/MoonPro_UtilsContext.cs +++ b/MP.Data/MoonPro_UtilsContext.cs @@ -1,5 +1,6 @@ using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Configuration; +using MP.Data.DbModels.Mtc; using MP.Data.DbModels.Utils; using NLog; using System; @@ -47,6 +48,7 @@ namespace MP.Data public virtual DbSet DbSetStatsDet { get; set; } public virtual DbSet DbSetStatsAggr { get; set; } + public virtual DbSet DbSetMtcSetup { get; set; } #endregion Public Properties diff --git a/MP.Data/Repository/Mtc/IMtcSetupRepository.cs b/MP.Data/Repository/Mtc/IMtcSetupRepository.cs new file mode 100644 index 00000000..8ccda387 --- /dev/null +++ b/MP.Data/Repository/Mtc/IMtcSetupRepository.cs @@ -0,0 +1,36 @@ +using MP.Data.DbModels.Mtc; +using System.Threading.Tasks; + +namespace MP.Data.Repository.Mtc +{ + public interface IMtcSetupRepository + { + /// + /// Recupero record richiesto + /// + /// + /// + Task GetByIdxAsync(string idxMacchina); + + /// + /// Inserimento nuovo record + /// + /// + /// + Task InsertAsync(MtcSetupModel newRec); + + /// + /// Eliminazione record esistente + /// + /// + /// + Task DeleteAsync(string idxMacchina); + + /// + /// Update record esistente + /// + /// + /// + Task UpdateAsync(MtcSetupModel updRec); + } +} diff --git a/MP.Data/Repository/Mtc/MtcSetupRepository.cs b/MP.Data/Repository/Mtc/MtcSetupRepository.cs new file mode 100644 index 00000000..4912f651 --- /dev/null +++ b/MP.Data/Repository/Mtc/MtcSetupRepository.cs @@ -0,0 +1,64 @@ +using Microsoft.EntityFrameworkCore; +using MP.Data.DbModels.Mtc; +using System.Threading.Tasks; + +namespace MP.Data.Repository.Mtc +{ + public class MtcSetupRepository : BaseRepository, IMtcSetupRepository + { + #region Public Constructors + + public MtcSetupRepository(IDbContextFactory ctxFactory) : base(ctxFactory) + { + } + + #endregion Public Constructors + + #region Public Methods + + /// + public async Task DeleteAsync(string idxMacchina) + { + bool actRes = false; + await using var dbCtx = await CreateContextAsync(); + var existing = await GetByIdxAsync(idxMacchina); + if (existing != null) + { + dbCtx.DbSetMtcSetup.Remove(existing); + actRes = await dbCtx.SaveChangesAsync() > 0; + } + return actRes; + } + + /// + public async Task GetByIdxAsync(string idxMacchina) + { + await using var dbCtx = await CreateContextAsync(); + return await dbCtx.DbSetMtcSetup + //.Include(s => s.MtcDataItems) + .FirstOrDefaultAsync(s => s.IdxMacchina == idxMacchina); + } + + /// + public async Task InsertAsync(MtcSetupModel newRec) + { + bool actRes = false; + await using var dbCtx = await CreateContextAsync(); + dbCtx.DbSetMtcSetup.Add(newRec); + actRes = await dbCtx.SaveChangesAsync() > 0; + return actRes; + } + + /// + public async Task UpdateAsync(MtcSetupModel updRec) + { + bool actRes = false; + await using var dbCtx = await CreateContextAsync(); + dbCtx.DbSetMtcSetup.Update(updRec); + actRes = await dbCtx.SaveChangesAsync() > 0; + return actRes; + } + + #endregion Public Methods + } +} \ No newline at end of file diff --git a/MP.Data/Services/Mtc/IMtcSetupService.cs b/MP.Data/Services/Mtc/IMtcSetupService.cs new file mode 100644 index 00000000..010597d1 --- /dev/null +++ b/MP.Data/Services/Mtc/IMtcSetupService.cs @@ -0,0 +1,23 @@ +using MP.Core.Objects; +using MP.Data.DbModels.Mtc; +using System.Collections.Generic; +using System.Threading.Tasks; + +namespace MP.Data.Services.Mtc +{ + public interface IMtcSetupService + { + + /// + /// Replace the data set for the specified machine. + /// Deletes existing record then inserts new one. + /// + Task ReplaceMachineDataAsync(string idxMacchina, List items); + + + /// + /// Retrieve all data for a given machine. + /// + Task GetMachineDataAsync(string idxMacchina); + } +} diff --git a/MP.Data/Services/Mtc/MtcSetupService.cs b/MP.Data/Services/Mtc/MtcSetupService.cs new file mode 100644 index 00000000..8ea00bf4 --- /dev/null +++ b/MP.Data/Services/Mtc/MtcSetupService.cs @@ -0,0 +1,75 @@ +using Microsoft.Extensions.Configuration; +using MP.Core.Objects; +using MP.Data.DbModels.Mtc; +using MP.Data.Repository.Mtc; +using StackExchange.Redis; +using System.Collections.Generic; +using System.Threading.Tasks; + +namespace MP.Data.Services.Mtc +{ + // A lightweight service that mirrors the old Mongo based archive + public class MtcSetupService : BaseServ, IMtcSetupService + { + + private readonly string _className; + private readonly IMtcSetupRepository _repo; + + public MtcSetupService( + IConfiguration config, + IConnectionMultiplexer redis, + IMtcSetupRepository repo) : base(config, redis) + { + _className = "MtcSetup"; + _repo = repo; + } + + /// + public async Task ReplaceMachineDataAsync(string idxMacchina, List items) + { + return await TraceAsync($"{_className}.ReplaceMachineData", async (activity) => + { + // cerso sul DB + var currRec = await _repo.GetByIdxAsync(idxMacchina); + + var upsRec = new MtcSetupModel + { + IdxMacchina = idxMacchina, + MtcDataItems = items + }; + + string operation = "UPDATE"; + bool success = false; + + if (currRec != null) + { + success = await _repo.UpdateAsync(upsRec); + } + else + { + operation = "INSERT"; + success = await _repo.InsertAsync(upsRec); + } + + activity?.SetTag("db.operation", operation); + + await ClearCacheAsync($"{_redisBaseKey}:{_className}:*"); + return success; + }); + } + + /// + public async Task GetMachineDataAsync(string idxMacchina) + { + return await TraceAsync($"{_className}.GetMachineData", async (activity) => + { + string cacheKey = $"{_redisBaseKey}:{_className}:MachData:{idxMacchina}"; + return await GetOrSetCacheAsync( + cacheKey, + async () => await _repo.GetByIdxAsync(idxMacchina), + LongCache + ); + }); + } + } +} diff --git a/MP.IOC/Components/Pages/Index.razor.cs b/MP.IOC/Components/Pages/Index.razor.cs index 1424145f..b5415b74 100644 --- a/MP.IOC/Components/Pages/Index.razor.cs +++ b/MP.IOC/Components/Pages/Index.razor.cs @@ -43,7 +43,9 @@ namespace MP.IOC.Components.Pages DateTime oggi = DateTime.Today; DateTime adesso = DateTime.Now; var paretoDayCall = await StatsAggrService.GetParetoStatsDayAsync(0); - ListGlobalCall = paretoDayCall["Mach.Duration (ms)"]; + ListGlobalCall.Clear(); + var rawMachPareto = paretoDayCall["Mach.Duration (ms)"]; + ListGlobalCall = rawMachPareto.Take(10).ToList(); ListParetoCall = await StatsDetService.GetParetoAsync(adesso.AddHours(-1), adesso, 10); paretoWeek = await StatsAggrService.GetParetoStatsWeekAsync(); } diff --git a/MP.IOC/Controllers/IOBController.cs b/MP.IOC/Controllers/IOBController.cs index 5a21b239..bf34f9b0 100644 --- a/MP.IOC/Controllers/IOBController.cs +++ b/MP.IOC/Controllers/IOBController.cs @@ -1003,6 +1003,35 @@ namespace MP.IOC.Controllers return Ok(answ); } + /// + /// Processa una chiamata POST per l'invio di un array Json di oggetti di conf DataItems (es + /// per MTC) + /// PUT: IOB/saveDataItems/SIMUL_03 + /// + /// ID dell'IOB + /// + [HttpPost("saveDataItems/{id}")] + public async Task SaveDataItems(string id, [FromBody] List dataList) + { + if (string.IsNullOrEmpty(id)) return BadRequest("Missing ID"); + + // Multi: gestione carattere "|" trasformato in "#" + id = id.Replace("|", "#"); + + string answ = ""; + try + { + bool done = await DService.SaveDataItemsAsync(id, dataList); + answ = done ? "OK" : "KO"; + } + catch (Exception exc) + { + Log.Error($"Errore in SaveDataItems{Environment.NewLine}{exc}"); + return StatusCode(StatusCodes.Status500InternalServerError, "NO"); + } + return Ok(answ); + } + /// /// Processa una chiamata POST per l'invio di una Dictionary HashList da salvare in redis /// POST: IOB/saveMachineIobConf/SIMUL_03 diff --git a/MP.IOC/Data/MpDataService.cs b/MP.IOC/Data/MpDataService.cs index d140c18a..9e0b53b7 100644 --- a/MP.IOC/Data/MpDataService.cs +++ b/MP.IOC/Data/MpDataService.cs @@ -3,9 +3,12 @@ using MP.Core.Conf; using MP.Core.DTO; using MP.Core.Objects; using MP.Data; +using MP.Data.Controllers; using MP.Data.DbModels; using MP.Data.DbModels.Anag; using MP.Data.MgModels; +using MP.Data.Repository.Mtc; +using MP.Data.Services.Mtc; using Newtonsoft.Json; using NLog; using StackExchange.Redis; @@ -20,11 +23,17 @@ namespace MP.IOC.Data { #region Public Constructors - public MpDataService(IConfiguration configuration, ILogger logger) + public MpDataService( + IConfiguration configuration, + ILogger logger, + IServiceScopeFactory scopeFactory, + IMtcSetupRepository mtcRepo, + IMtcSetupService mtcServ) { _logger = logger; _logger.LogInformation("Starting MpDataService INIT"); _configuration = configuration; + _scopeFactory = scopeFactory; // setup compoenti REDIS redisConn = ConnectionMultiplexer.Connect(_configuration.GetConnectionString("Redis")); @@ -35,6 +44,8 @@ namespace MP.IOC.Data int.TryParse(_configuration.GetValue("ServerConf:redisLongTimeCache"), out redisLongTimeCache); int.TryParse(_configuration.GetValue("ServerConf:redisShortTimeCache"), out redisShortTimeCache); + // gestione scope factory + useFactory = _configuration.GetValue("ServerConf:useFactory"); // conf base x servizi condivisi IO/IOC MpIoNS = _configuration.GetValue("ServerConf:MpIoNS") ?? "MP"; @@ -53,6 +64,9 @@ namespace MP.IOC.Data _logger.LogInformation("DbControllers INIT OK"); } + MtcRepo = mtcRepo; + MtcService = mtcServ; + // conf mongo... connStr = _configuration.GetConnectionString("mdbConnString"); if (string.IsNullOrEmpty(connStr)) @@ -73,6 +87,8 @@ namespace MP.IOC.Data public static MP.Data.Controllers.MpIocController IocDbController { get; set; } = null!; public static MP.Data.Controllers.MpMongoController mongoController { get; set; } = null!; public static MP.Data.Controllers.MpSpecController SpecDbController { get; set; } = null!; + private static MP.Data.Services.Mtc.IMtcSetupService MtcService = null!; + private static MP.Data.Repository.Mtc.IMtcSetupRepository MtcRepo; public MessagePipe BroadastMsgPipe { get; set; } = null!; /// @@ -1883,7 +1899,7 @@ namespace MP.IOC.Data TimeSpan ts = stopWatch.Elapsed; Log.Debug($"Macchine2SlaveGetAll | Read from {readType}: {ts.TotalMilliseconds}ms"); return result; - } + } #endif /// @@ -1914,45 +1930,6 @@ namespace MP.IOC.Data return result; } - private async Task> ListMasterAsync() - { - HashSet result = new(); - string currKey = $"{Utils.redisBaseAddr}:ListMaster"; - RedisValue rawData = await redisDb.StringGetAsync(currKey); - if (rawData.HasValue) - { - result = JsonConvert.DeserializeObject>($"{rawData}") ?? new(); - } - else - { - var fullList = await Macchine2SlaveGetAllAsync(); - result = fullList.Select(x => x.IdxMacchina).ToHashSet(); - // serializzo e salvo... - rawData = JsonConvert.SerializeObject(result); - await redisDb.StringSetAsync(currKey, rawData, getRandTOut(redisLongTimeCache * 10)); - } - return result; - } - private async Task> ListSlaveAsync() - { - HashSet result = new(); - string currKey = $"{Utils.redisBaseAddr}:ListSlave"; - RedisValue rawData = await redisDb.StringGetAsync(currKey); - if (rawData.HasValue) - { - result = JsonConvert.DeserializeObject>($"{rawData}") ?? new(); - } - else - { - var fullList = await Macchine2SlaveGetAllAsync(); - result = fullList.Select(x => x.IdxMacchinaSlave).Distinct().ToHashSet(); - // serializzo e salvo... - rawData = JsonConvert.SerializeObject(result); - await redisDb.StringSetAsync(currKey, rawData, getRandTOut(redisLongTimeCache * 10)); - } - return result; - } - /// /// Elenco di tutte le macchine gestite /// @@ -2235,7 +2212,6 @@ namespace MP.IOC.Data return answ; } - /// /// Restitusice elenco KVP dei campi DatiMacchine + StatoMacchine per l'impianto indicato /// @@ -3788,6 +3764,24 @@ namespace MP.IOC.Data return answ; } + public async Task SaveDataItemsAsync(string id, List dataList) + { + bool answ = false; + + if (useFactory) + { + await using var scope = _scopeFactory.CreateAsyncScope(); + var mtcService = scope.ServiceProvider.GetRequiredService(); + answ = await mtcService.ReplaceMachineDataAsync(id, dataList); + } + else + { + answ = await MtcService.ReplaceMachineDataAsync(id, dataList); + } + + return answ; + } + public async Task SaveMachine2Iob(string idxMacchina, string serData) { bool fatto = false; @@ -4164,10 +4158,9 @@ namespace MP.IOC.Data #region Private Fields private static IConfiguration _configuration = null!; - private static ILogger _logger = null!; - private static Logger Log = LogManager.GetCurrentClassLogger(); + private readonly IServiceScopeFactory _scopeFactory; /// /// MS max age x dato MSE @@ -4200,6 +4193,8 @@ namespace MP.IOC.Data private int redisShortTimeCache = 2; + private bool useFactory = false; + /// /// Generatore random classe /// @@ -4419,6 +4414,46 @@ namespace MP.IOC.Data return answ; } + private async Task> ListMasterAsync() + { + HashSet result = new(); + string currKey = $"{Utils.redisBaseAddr}:ListMaster"; + RedisValue rawData = await redisDb.StringGetAsync(currKey); + if (rawData.HasValue) + { + result = JsonConvert.DeserializeObject>($"{rawData}") ?? new(); + } + else + { + var fullList = await Macchine2SlaveGetAllAsync(); + result = fullList.Select(x => x.IdxMacchina).ToHashSet(); + // serializzo e salvo... + rawData = JsonConvert.SerializeObject(result); + await redisDb.StringSetAsync(currKey, rawData, getRandTOut(redisLongTimeCache * 10)); + } + return result; + } + + private async Task> ListSlaveAsync() + { + HashSet result = new(); + string currKey = $"{Utils.redisBaseAddr}:ListSlave"; + RedisValue rawData = await redisDb.StringGetAsync(currKey); + if (rawData.HasValue) + { + result = JsonConvert.DeserializeObject>($"{rawData}") ?? new(); + } + else + { + var fullList = await Macchine2SlaveGetAllAsync(); + result = fullList.Select(x => x.IdxMacchinaSlave).Distinct().ToHashSet(); + // serializzo e salvo... + rawData = JsonConvert.SerializeObject(result); + await redisDb.StringSetAsync(currKey, rawData, getRandTOut(redisLongTimeCache * 10)); + } + return result; + } + private async Task POdlFlushCache() { bool answ = false; @@ -4499,8 +4534,17 @@ namespace MP.IOC.Data private async Task> ResetDatiMacchinaAsync(string idxMacc) { Dictionary result = new Dictionary(); - - var dbResult = await IocDbController.VMSFDGetByMaccAsync(idxMacc); + VMSFDModel? dbResult = null; + if (useFactory) + { + await using var scope = _scopeFactory.CreateAsyncScope(); + var mtcService = scope.ServiceProvider.GetRequiredService(); + dbResult = await mtcService.VMSFDGetByMaccAsync(idxMacc); + } + else + { + dbResult = await IocDbController.VMSFDGetByMaccAsync(idxMacc); + } if (dbResult == null) return new Dictionary(); diff --git a/MP.IOC/MP.IOC.csproj b/MP.IOC/MP.IOC.csproj index 971bdd3a..75c40bf1 100644 --- a/MP.IOC/MP.IOC.csproj +++ b/MP.IOC/MP.IOC.csproj @@ -4,7 +4,7 @@ net8.0 enable enable - 6.16.2604.2308 + 6.16.2604.2407 diff --git a/MP.IOC/Program.cs b/MP.IOC/Program.cs index 178dce5c..226dd3a4 100644 --- a/MP.IOC/Program.cs +++ b/MP.IOC/Program.cs @@ -3,8 +3,6 @@ using Microsoft.EntityFrameworkCore; using Microsoft.OpenApi.Models; using MP.Core.Conf; using MP.Data; -using MP.Data.Repository.Utils; -using MP.Data.Services.Utils; using MP.IOC.Components; using MP.IOC.Data; using MP.IOC.Services; @@ -64,6 +62,9 @@ builder.Services.Configure( builder.Configuration.GetSection("RedisScripts")); logger.Info("RedisScript Provider configured"); +// MP.Data Services Utils - Statistiche DB +builder.Services.AddIocDataLayer(); + // base services builder.Services.AddSingleton(); builder.Services.AddSingleton(); @@ -83,12 +84,6 @@ string utilsConnString = builder.Configuration.GetConnectionString("MP.Utils") ? builder.Services.AddDbContextFactory(options => options.UseSqlServer(utilsConnString)); -// MP.Data Services Utils - Statistiche DB -builder.Services.AddScoped(); -builder.Services.AddScoped(); -builder.Services.AddScoped(); -builder.Services.AddScoped(); - // generic controller builder.Services.AddControllers(); // Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle diff --git a/MP.IOC/Resources/ChangeLog.html b/MP.IOC/Resources/ChangeLog.html index bd1e5671..c380f0ad 100644 --- a/MP.IOC/Resources/ChangeLog.html +++ b/MP.IOC/Resources/ChangeLog.html @@ -1,6 +1,6 @@ Modulo MP-IOC -

Versione: 6.16.2604.2308

+

Versione: 6.16.2604.2407


Note di rilascio:
  • diff --git a/MP.IOC/Resources/VersNum.txt b/MP.IOC/Resources/VersNum.txt index 3d97dba4..ad965d8d 100644 --- a/MP.IOC/Resources/VersNum.txt +++ b/MP.IOC/Resources/VersNum.txt @@ -1 +1 @@ -6.16.2604.2308 +6.16.2604.2407 diff --git a/MP.IOC/Resources/manifest.xml b/MP.IOC/Resources/manifest.xml index e826cd0a..9113ad2f 100644 --- a/MP.IOC/Resources/manifest.xml +++ b/MP.IOC/Resources/manifest.xml @@ -1,6 +1,6 @@ - 6.16.2604.2308 + 6.16.2604.2407 https://nexus.steamware.net/repository/SWS/MP-IOC/stable/LAST/MP.IOC.zip https://nexus.steamware.net/repository/SWS/MP-IOC/stable/LAST/ChangeLog.html false diff --git a/MP.IOC/appsettings.json b/MP.IOC/appsettings.json index 64887672..d7c5727c 100644 --- a/MP.IOC/appsettings.json +++ b/MP.IOC/appsettings.json @@ -86,7 +86,8 @@ "RoutePath": "/api/RIOB", "SafePages": "Index", "redisLongTimeCache": 60, - "redisShortTimeCache": 30 + "redisShortTimeCache": 30, + "useFactory": true }, "RedisScripts": { "Scripts": {