Update cache con FusionCache in ram
This commit is contained in:
@@ -24,10 +24,11 @@
|
||||
<PackageVersion Include="Microsoft.EntityFrameworkCore.Relational" Version="6.0.36" />
|
||||
<PackageVersion Include="Microsoft.EntityFrameworkCore.SqlServer" Version="6.0.36" />
|
||||
<PackageVersion Include="Microsoft.EntityFrameworkCore.Tools" Version="6.0.36" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Caching.StackExchangeRedis" Version="10.0.7" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Configuration.Binder" Version="6.0.1" />
|
||||
<PackageVersion Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="6.0.17" />
|
||||
<PackageVersion Include="MongoDB.Driver" Version="2.19.0" />
|
||||
<PackageVersion Include="Newtonsoft.Json" Version="13.0.3" />
|
||||
<PackageVersion Include="Newtonsoft.Json" Version="13.0.4" />
|
||||
<PackageVersion Include="NLog" Version="6.1.3" />
|
||||
<PackageVersion Include="NLog.Targets.OpenTelemetryProtocol" Version="1.2.6" />
|
||||
<PackageVersion Include="NLog.Web.AspNetCore" Version="6.1.3" />
|
||||
@@ -41,7 +42,7 @@
|
||||
<PackageVersion Include="System.Text.Encodings.Web" Version="8.0.0" />
|
||||
<PackageVersion Include="RestSharp" Version="112.0.0" />
|
||||
<PackageVersion Include="SharpZipLib" Version="1.4.2" />
|
||||
<PackageVersion Include="StackExchange.Redis" Version="2.9.17" />
|
||||
<PackageVersion Include="StackExchange.Redis" Version="2.12.14" />
|
||||
<PackageVersion Include="System.Data.SqlClient" Version="4.8.6" />
|
||||
<PackageVersion Include="Swashbuckle.AspNetCore" Version="6.9.0" />
|
||||
<PackageVersion Include="Swashbuckle.AspNetCore.Swagger" Version="6.9.0" />
|
||||
@@ -49,5 +50,8 @@
|
||||
<PackageVersion Include="Swashbuckle.AspNetCore.SwaggerUI" Version="6.9.0" />
|
||||
<PackageVersion Include="YamlDotNet" Version="16.1.0" />
|
||||
<PackageVersion Include="Yarp.ReverseProxy" Version="2.3.0" />
|
||||
<PackageVersion Include="ZiggyCreatures.FusionCache" Version="2.6.0" />
|
||||
<PackageVersion Include="ZiggyCreatures.FusionCache.Backplane.StackExchangeRedis" Version="2.6.0" />
|
||||
<PackageVersion Include="ZiggyCreatures.FusionCache.Serialization.NewtonsoftJson" Version="2.6.0" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -48,6 +48,9 @@
|
||||
<PackageReference Include="RestSharp" />
|
||||
<PackageReference Include="SharpZipLib" />
|
||||
<PackageReference Include="StackExchange.Redis" />
|
||||
<PackageReference Include="ZiggyCreatures.FusionCache" />
|
||||
<PackageReference Include="ZiggyCreatures.FusionCache.Backplane.StackExchangeRedis" />
|
||||
<PackageReference Include="ZiggyCreatures.FusionCache.Serialization.NewtonsoftJson" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
@@ -24,6 +24,12 @@ namespace MP.Data.Services.IOC
|
||||
/// <returns></returns>
|
||||
Task<bool> CheckCambiaStatoBatchAsync(tipoInputEvento tipoInput, string IdxMacchina, DateTime InizioStato, int IdxTipo, string CodArt, string Value, int MatrOpr, string pallet);
|
||||
|
||||
/// <summary>
|
||||
/// Esegue clear dell'intera cache fusion in blocco
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
Task<bool> ClearFusionCache();
|
||||
|
||||
/// <summary>
|
||||
/// Aggiunta record MicroStato + EventList
|
||||
/// </summary>
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using Microsoft.Extensions.Caching.Memory;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using MP.Core.Objects;
|
||||
using MP.Data.DbModels;
|
||||
@@ -12,6 +11,7 @@ using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using ZiggyCreatures.Caching.Fusion;
|
||||
using static MP.Core.Objects.Enums;
|
||||
|
||||
namespace MP.Data.Services.IOC
|
||||
@@ -25,7 +25,8 @@ namespace MP.Data.Services.IOC
|
||||
IConnectionMultiplexer redis,
|
||||
IIocRepository repo,
|
||||
IServiceScopeFactory scopeFactory,
|
||||
Microsoft.Extensions.Caching.Memory.IMemoryCache cache) : base(config, redis)
|
||||
//Microsoft.Extensions.Caching.Memory.IMemoryCache cache
|
||||
IFusionCache cache) : base(config, redis)
|
||||
{
|
||||
_className = "IocServ";
|
||||
int.TryParse(config.GetValue<string>("ServerConf:redisLongTimeCache"), out redisLongTimeCache);
|
||||
@@ -46,6 +47,15 @@ namespace MP.Data.Services.IOC
|
||||
return success;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<bool> ClearFusionCache()
|
||||
{
|
||||
bool fatto = false;
|
||||
await _cache.ClearAsync();
|
||||
fatto = true;
|
||||
return fatto;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<bool> EvListMicroStatoInsertAsync(MicroStatoMacchinaModel newRecMsm, EventListModel newRecEv)
|
||||
{
|
||||
@@ -268,12 +278,12 @@ namespace MP.Data.Services.IOC
|
||||
|
||||
private static Logger Log = LogManager.GetCurrentClassLogger();
|
||||
|
||||
private readonly Microsoft.Extensions.Caching.Memory.IMemoryCache _cache;
|
||||
private readonly IFusionCache _cache;
|
||||
|
||||
private readonly string _className;
|
||||
|
||||
private readonly IIocRepository _repo;
|
||||
private readonly IServiceScopeFactory _scopeFactory;
|
||||
private readonly System.Threading.SemaphoreSlim _semaphore = new System.Threading.SemaphoreSlim(1, 1);
|
||||
|
||||
/// <summary>
|
||||
/// Provider CultureInfo x parse valori(es dataora)
|
||||
@@ -406,8 +416,6 @@ namespace MP.Data.Services.IOC
|
||||
else
|
||||
{
|
||||
result = await _repo.ConfigGetAllAsync();
|
||||
//result = await Task.FromResult(SpecDbController.ConfigGetAllAsync());
|
||||
// serializzo e salvo...
|
||||
rawData = JsonConvert.SerializeObject(result);
|
||||
await _redisDb.StringSetAsync(MP.Data.Utils.redisConfKey, rawData, getRandTOut(redisLongTimeCache));
|
||||
}
|
||||
@@ -417,7 +425,7 @@ namespace MP.Data.Services.IOC
|
||||
result = new List<ConfigModel>();
|
||||
}
|
||||
return result;
|
||||
}, TimeSpan.FromMinutes(10));
|
||||
}, TimeSpan.FromMinutes(1));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -460,15 +468,15 @@ namespace MP.Data.Services.IOC
|
||||
/// <returns></returns>
|
||||
private async Task<T> GetOrFetchAsync<T>(string cacheKey, Func<Task<T>> fetchFunc, TimeSpan expiration)
|
||||
{
|
||||
if (_cache.TryGetValue(cacheKey, out T? cachedValue))
|
||||
{
|
||||
return cachedValue!;
|
||||
}
|
||||
|
||||
// se non trovato procedo as usual...
|
||||
T newValue = await fetchFunc();
|
||||
_cache.Set(cacheKey, newValue, expiration);
|
||||
return newValue;
|
||||
// GetOrSetAsync di Fusion cache:
|
||||
// - TryGetValue, se mancasse crea un lock solo per QUELLA key
|
||||
// - Esegue fetchFunc (la logica Redis + DB)
|
||||
// - Salva in memoria e rilascia il lock
|
||||
return await _cache.GetOrSetAsync<T>(
|
||||
cacheKey,
|
||||
async ct => await fetchFunc(),
|
||||
options => options.SetDuration(expiration)
|
||||
);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -543,7 +551,7 @@ namespace MP.Data.Services.IOC
|
||||
await _redisDb.StringSetAsync(currKey, rawData, getRandTOut(redisLongTimeCache * 10));
|
||||
}
|
||||
return result;
|
||||
}, TimeSpan.FromMinutes(5));
|
||||
}, TimeSpan.FromMinutes(15));
|
||||
}
|
||||
|
||||
private async Task<HashSet<string>> ListSlaveAsync()
|
||||
@@ -565,7 +573,7 @@ namespace MP.Data.Services.IOC
|
||||
await _redisDb.StringSetAsync(currKey, rawData, getRandTOut(redisLongTimeCache * 10));
|
||||
}
|
||||
return result;
|
||||
}, TimeSpan.FromMinutes(5));
|
||||
}, TimeSpan.FromMinutes(15));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -596,7 +604,7 @@ namespace MP.Data.Services.IOC
|
||||
result = new List<Macchine2SlaveModel>();
|
||||
}
|
||||
return result;
|
||||
}, TimeSpan.FromMinutes(15));
|
||||
}, TimeSpan.FromMinutes(30));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -1022,7 +1030,7 @@ namespace MP.Data.Services.IOC
|
||||
result = new StatoProdModel();
|
||||
}
|
||||
return result;
|
||||
}, TimeSpan.FromSeconds(10));
|
||||
}, TimeSpan.FromSeconds(3));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -41,7 +41,6 @@ namespace MP.Data.Services.Utils
|
||||
//Task<Dictionary<string, List<StatDataDTO>>> GetParetoStatsDayAsync();
|
||||
Task<List<StatInfoDto>> GetParetoStatsDayAsync();
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Recupera il range di periodi valido per le chiamate di dettaglio.
|
||||
/// Utilizza la cache automaticamente.
|
||||
@@ -58,6 +57,12 @@ namespace MP.Data.Services.Utils
|
||||
/// <returns></returns>
|
||||
List<ChartSeriesDto> GetTimeSeriesData(List<StatsDetailModel> rawData, bool showCount);
|
||||
|
||||
/// <summary>
|
||||
/// Forza il reset della cache REDIS x i dati
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
Task ResetCache();
|
||||
|
||||
/// <summary>
|
||||
/// Inserisce o aggiorna in batch le statistiche di dettaglio nel database.
|
||||
/// Opzionalmente elimina i record precedenti nel periodo specificato.
|
||||
|
||||
@@ -125,6 +125,12 @@ namespace MP.Data.Services.Utils
|
||||
return series;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task ResetCache()
|
||||
{
|
||||
await ClearCacheAsync($"{_redisBaseKey}:*");
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<int> UpsertManyAsync(List<StatsDetailModel> listRecords, bool removeOld)
|
||||
{
|
||||
@@ -227,7 +233,6 @@ namespace MP.Data.Services.Utils
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
#endregion Protected Methods
|
||||
|
||||
#region Private Fields
|
||||
|
||||
@@ -2,7 +2,14 @@
|
||||
|
||||
<div class="card shadow">
|
||||
<div class="card-header">
|
||||
<h3>Current Stats</h3>
|
||||
<div class="d-flex justify-content-between">
|
||||
<div class="px-0">
|
||||
<h3>Current Stats</h3>
|
||||
</div>
|
||||
<div class="px-0">
|
||||
<button class="btn btn-primary btn-large" @onclick="() => DoForceReload()">Force Reload</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body px-1 py-0">
|
||||
<div class="row mb-2">
|
||||
@@ -85,17 +92,17 @@
|
||||
<div class="input-group">
|
||||
<span class="input-group-text"># giorni</span>
|
||||
<input type="number" class="form-control form-control-sm" @bind="numDays" @bind:after="OnDaysChangedAsync">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<MultiLine Id="@currTsId" AspRatio="3" DataTSList="@TSDataMulti" Labels="@LabelPlot" lineColor="@lineColorsMLine" backColor="@bgColorsMLine" lTens="0" Titles="@lineTitles" BeginAtZero="@beginAtZero" Stepped="false" Stacked="@lineStacked" ShowLegend="@showLegend" yScale="@scaleFormat"></MultiLine>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
<div class="card-body">
|
||||
<MultiLine Id="@currTsId" AspRatio="3" DataTSList="@TSDataMulti" Labels="@LabelPlot" lineColor="@lineColorsMLine" backColor="@bgColorsMLine" lTens="0" Titles="@lineTitles" BeginAtZero="@beginAtZero" Stepped="false" Stacked="@lineStacked" ShowLegend="@showLegend" yScale="@scaleFormat"></MultiLine>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -3,6 +3,7 @@ using MP.Core.DTO;
|
||||
using MP.Data;
|
||||
using MP.Data.DbModels.Utils;
|
||||
using MP.Data.DTO;
|
||||
using MP.Data.Services.IOC;
|
||||
using MP.Data.Services.Utils;
|
||||
|
||||
namespace MP.IOC.Components.Pages
|
||||
@@ -101,6 +102,9 @@ namespace MP.IOC.Components.Pages
|
||||
[Inject]
|
||||
private IStatsDetailService SDetService { get; set; } = null!;
|
||||
|
||||
[Inject]
|
||||
private IIocService IocService { get; set; } = null!;
|
||||
|
||||
#endregion Private Properties
|
||||
|
||||
#region Private Methods
|
||||
@@ -110,6 +114,13 @@ namespace MP.IOC.Components.Pages
|
||||
return currStatSel != null && currStatSel.Title == curKey ? "active" : "";
|
||||
}
|
||||
|
||||
private async Task DoForceReload()
|
||||
{
|
||||
await SDetService.ResetCache();
|
||||
await IocService.ClearFusionCache();
|
||||
DoReset();
|
||||
}
|
||||
|
||||
private void DoReset()
|
||||
{
|
||||
currStatSel = null;
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Version>8.16.2605.1112</Version>
|
||||
<Version>8.16.2605.1119</Version>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
@@ -10,6 +10,9 @@ using NLog;
|
||||
using NLog.Web;
|
||||
using StackExchange.Redis;
|
||||
using System.Reflection;
|
||||
using ZiggyCreatures.Caching.Fusion;
|
||||
using ZiggyCreatures.Caching.Fusion.Serialization;
|
||||
using ZiggyCreatures.Caching.Fusion.Serialization.NewtonsoftJson;
|
||||
|
||||
var builder = WebApplication.CreateBuilder(args);
|
||||
|
||||
@@ -85,6 +88,20 @@ builder.Services.AddSingleton<IConnectionMultiplexer>(redisMux);
|
||||
//builder.Services.AddScoped<MpDataService>();
|
||||
builder.Services.AddSingleton<MpDataService>();
|
||||
|
||||
// 1. Registra il serializzatore NewtonsoftJson per FusionCache
|
||||
builder.Services.AddSingleton<IFusionCacheSerializer>(new FusionCacheNewtonsoftJsonSerializer());
|
||||
|
||||
// 2. Configura FusionCache solo per la memoria (L1)
|
||||
builder.Services.AddFusionCache()
|
||||
.WithDefaultEntryOptions(options =>
|
||||
{
|
||||
// Durata di default dei dati in memoria
|
||||
options.Duration = TimeSpan.FromMinutes(1);
|
||||
|
||||
// Jitter: variazione casuale alla scadenza per evitare scadenze in blocco
|
||||
options.JitterMaxDuration = TimeSpan.FromSeconds(5);
|
||||
});
|
||||
|
||||
logger.Info("Standard service configured");
|
||||
|
||||
// WeightProvider: Redis/Memory da config
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<body>
|
||||
<i>Modulo MP-IOC </i>
|
||||
<h4>Versione: 8.16.2605.1112</h4>
|
||||
<h4>Versione: 8.16.2605.1119</h4>
|
||||
<br /> Note di rilascio:
|
||||
<ul>
|
||||
<li>
|
||||
|
||||
@@ -1 +1 @@
|
||||
8.16.2605.1112
|
||||
8.16.2605.1119
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<item>
|
||||
<version>8.16.2605.1112</version>
|
||||
<version>8.16.2605.1119</version>
|
||||
<url>https://nexus.steamware.net/repository/SWS/MP-IOC/stable/LAST/MP.IOC.zip</url>
|
||||
<changelog>https://nexus.steamware.net/repository/SWS/MP-IOC/stable/LAST/ChangeLog.html</changelog>
|
||||
<mandatory>false</mandatory>
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<RootNamespace>MP.RIOC</RootNamespace>
|
||||
<Version>8.16.2605.1111</Version>
|
||||
<Version>8.16.2605.1207</Version>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
+1
-1
@@ -62,7 +62,7 @@ var httpClientInvoker = new HttpMessageInvoker(new SocketsHttpHandler
|
||||
UseCookies = false,
|
||||
// Correzione per il tracing: usa il propagatore corrente di sistema
|
||||
ActivityHeadersPropagator = DistributedContextPropagator.Current,
|
||||
ConnectTimeout = TimeSpan.FromSeconds(30),
|
||||
ConnectTimeout = TimeSpan.FromSeconds(60),
|
||||
|
||||
// Gestione certificato (ignora errori per localhost/test)
|
||||
SslOptions = new System.Net.Security.SslClientAuthenticationOptions
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<body>
|
||||
<i>Modulo MP-RIOC </i>
|
||||
<h4>Versione: 8.16.2605.1111</h4>
|
||||
<h4>Versione: 8.16.2605.1207</h4>
|
||||
<br /> Note di rilascio:
|
||||
<ul>
|
||||
<li>
|
||||
|
||||
@@ -1 +1 @@
|
||||
8.16.2605.1111
|
||||
8.16.2605.1207
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<item>
|
||||
<version>8.16.2605.1111</version>
|
||||
<version>8.16.2605.1207</version>
|
||||
<url>https://nexus.steamware.net/repository/SWS/MP-RIOC/stable/LAST/MP.RIOC.zip</url>
|
||||
<changelog>https://nexus.steamware.net/repository/SWS/MP-RIOC/stable/LAST/ChangeLog.html</changelog>
|
||||
<mandatory>false</mandatory>
|
||||
|
||||
Reference in New Issue
Block a user