Test riscrittura flushredis + ottimizzazione insert remoteRebootLog
This commit is contained in:
File diff suppressed because one or more lines are too long
@@ -1051,6 +1051,34 @@ namespace MP.Data.Controllers
|
||||
|
||||
return await dbCtx.SaveChangesAsync() > 0;
|
||||
}
|
||||
/// <summary>
|
||||
/// Aggiunta record RemoteRebootLog
|
||||
/// </summary>
|
||||
/// <param name="newRec"></param>
|
||||
/// <returns></returns>
|
||||
public async Task<bool> RemRebootLogAddAndCleanAsync(RemoteRebootLogModel newRec, int num2keep)
|
||||
{
|
||||
bool fatto = false;
|
||||
using var dbCtx = new MoonProContext(_configuration);
|
||||
using var transaction = await dbCtx.Database.BeginTransactionAsync();
|
||||
try
|
||||
{
|
||||
dbCtx.DbSetRemRebLog.Add(newRec);
|
||||
fatto = await dbCtx.SaveChangesAsync() > 0;
|
||||
|
||||
|
||||
var param = new SqlParameter("@num2keep", num2keep);
|
||||
await dbCtx.Database.ExecuteSqlRawAsync("EXEC dbo.stp_RRL_KeepLatest @num2keep", param);
|
||||
|
||||
await transaction.CommitAsync();
|
||||
return true;
|
||||
}
|
||||
catch
|
||||
{
|
||||
await transaction.RollbackAsync();
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Recupera tutti i record di RemoteRebootLog
|
||||
|
||||
@@ -1,15 +1,11 @@
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using MP.Core.Conf;
|
||||
using MP.Data.DbModels;
|
||||
using Newtonsoft.Json;
|
||||
using NLog;
|
||||
using StackExchange.Redis;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.Data;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
@@ -298,7 +294,7 @@ namespace MP.Data.Services
|
||||
.Where(ep => _redisConn.GetServer(ep).IsConnected && !_redisConn.GetServer(ep).IsReplica)
|
||||
.FirstOrDefault();
|
||||
|
||||
// sepattern è "*" elimino intero DB...
|
||||
// se pattern è "*" elimino intero DB...
|
||||
if (masterEndpoint != null && (pat2Flush.Equals(new RedisValue("*")) || pat2Flush == RedisValue.Null))
|
||||
{
|
||||
_redisConn.GetServer(masterEndpoint).FlushDatabase(database: _redisDb.Database);
|
||||
@@ -322,26 +318,8 @@ namespace MP.Data.Services
|
||||
{
|
||||
await Task.WhenAll(deleteTasks);
|
||||
}
|
||||
answ = true;
|
||||
}
|
||||
answ = true;
|
||||
#if false
|
||||
var listEndpoints = redisConn.GetEndPoints();
|
||||
foreach (var endPoint in listEndpoints)
|
||||
{
|
||||
//var server = redisConnAdmin.GetServer(listEndpoints[0]);
|
||||
var server = redisConn.GetServer(endPoint);
|
||||
if (server != null)
|
||||
{
|
||||
var keyList = server.Keys(redisDb.Database, pattern);
|
||||
foreach (var item in keyList)
|
||||
{
|
||||
await redisDb.KeyDeleteAsync(item);
|
||||
}
|
||||
answ = true;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return answ;
|
||||
}
|
||||
|
||||
|
||||
@@ -810,7 +810,6 @@ namespace MP.IOC.Controllers
|
||||
if (string.IsNullOrEmpty(id)) return BadRequest("Missing ID");
|
||||
|
||||
id = id.Replace('|', '#');
|
||||
|
||||
try
|
||||
{
|
||||
await DService.ScriviKeepAliveAsync(id, DateTime.UtcNow);
|
||||
@@ -1150,15 +1149,14 @@ namespace MP.IOC.Controllers
|
||||
{
|
||||
if (string.IsNullOrEmpty(id)) return BadRequest("Missing ID");
|
||||
|
||||
// Multi: gestione carattere "|" trasformato in "#"
|
||||
id = id.Replace("|", "#");
|
||||
|
||||
string answ = "NO";
|
||||
try
|
||||
{
|
||||
// recupero IP del client remoto
|
||||
var agent = Request.Headers["User-Agent"].ToString();
|
||||
var iPv4 = HttpContext.Connection.RemoteIpAddress?.ToString();
|
||||
//var ipv4 = HttpContext.Connection.RemoteIpAddress?.ToString();
|
||||
var ipv4 = HttpContext.Connection.RemoteIpAddress?.MapToIPv4().ToString();
|
||||
|
||||
// chiamo registrazione reboot
|
||||
RemoteRebootLogModel newRec = new()
|
||||
@@ -1166,11 +1164,22 @@ namespace MP.IOC.Controllers
|
||||
Agent = agent,
|
||||
DataOraBoot = DateTime.Now,
|
||||
IdxMacchina = id,
|
||||
IPv4 = iPv4,
|
||||
IPv4 = ipv4,
|
||||
MacAddr = mac
|
||||
};
|
||||
bool fatto = await DService.RemRebootLogAddAsync(newRec);
|
||||
answ = fatto ? "OK" : "KO";
|
||||
|
||||
var success = await DService.RemRebootLogAddAsync(newRec);
|
||||
answ = success ? "OK" : "KO";
|
||||
|
||||
if (success)
|
||||
{
|
||||
return Ok(answ);
|
||||
//return Ok(new { status = "ok", id = id });
|
||||
}
|
||||
else
|
||||
{
|
||||
return BadRequest(new { status = "ko", message = "DB operation failed" });
|
||||
}
|
||||
}
|
||||
catch (Exception exc)
|
||||
{
|
||||
|
||||
@@ -3323,7 +3323,6 @@ namespace MP.IOC.Data
|
||||
var listEndpoints = redisConnAdmin.GetEndPoints();
|
||||
foreach (var endPoint in listEndpoints)
|
||||
{
|
||||
//var server = redisConnAdmin.GetServer(listEndpoints[0]);
|
||||
var server = redisConnAdmin.GetServer(endPoint);
|
||||
if (server != null)
|
||||
{
|
||||
@@ -3343,6 +3342,7 @@ namespace MP.IOC.Data
|
||||
/// </summary>
|
||||
/// <param name="pattern"></param>
|
||||
/// <returns></returns>
|
||||
#if false
|
||||
public async Task<bool> RedisFlushPatternAsync(RedisValue pattern)
|
||||
{
|
||||
bool answ = false;
|
||||
@@ -3361,8 +3361,82 @@ namespace MP.IOC.Data
|
||||
}
|
||||
}
|
||||
return answ;
|
||||
}
|
||||
#endif
|
||||
public async Task<bool> RedisFlushPatternAsync(RedisValue pattern)
|
||||
{
|
||||
Log.Debug($"Richiesta flush pattern: {pattern}");
|
||||
|
||||
// 1. Target ONLY master (le replica sono in read-only)
|
||||
var master = redisConnAdmin.GetEndPoints()
|
||||
.Where(ep => redisConnAdmin.GetServer(ep).IsConnected && !redisConnAdmin.GetServer(ep).IsReplica)
|
||||
.FirstOrDefault();
|
||||
|
||||
if (master == null)
|
||||
{
|
||||
Log.Warn($"Nessun master Redis raggiungibile per il pattern {pattern}");
|
||||
return false;
|
||||
}
|
||||
|
||||
// 2. Flush intero DB se richiesto
|
||||
if (pattern.ToString() == "*")
|
||||
{
|
||||
Log.Debug($"Full DB reset da pattern {pattern}");
|
||||
if (master != null)
|
||||
{
|
||||
redisConnAdmin.GetServer(master).FlushDatabase(redisDb.Database);
|
||||
Log.Info($"Flush database {redisDb.Database} completato");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
// altrimenti faccio ciclo!
|
||||
var server = redisConnAdmin.GetServer(master);
|
||||
var db = redisConnAdmin.GetDatabase(redisDb.Database);
|
||||
const int batchSize = 500;
|
||||
var batch = new List<RedisKey>(batchSize);
|
||||
int deletedCount = 0;
|
||||
|
||||
try
|
||||
{
|
||||
// KeysAsync usa SCAN automaticamente quando i risultati sono grandi
|
||||
await foreach (var key in server.KeysAsync(
|
||||
database: redisDb.Database,
|
||||
pattern: pattern.ToString(),
|
||||
pageSize: batchSize))
|
||||
{
|
||||
batch.Add(key);
|
||||
if (batch.Count >= batchSize)
|
||||
{
|
||||
// Esecuzione batch in parallelo controllato
|
||||
await Task.WhenAll(batch.Select(k => db.KeyDeleteAsync(k)));
|
||||
batch.Clear();
|
||||
deletedCount += batchSize;
|
||||
}
|
||||
}
|
||||
|
||||
// Restanti
|
||||
if (batch.Count > 0)
|
||||
{
|
||||
await Task.WhenAll(batch.Select(k => db.KeyDeleteAsync(k)));
|
||||
deletedCount += batch.Count;
|
||||
}
|
||||
|
||||
Log.Info("Flush pattern {Pattern}: eliminate {Count} chiavi", pattern, deletedCount);
|
||||
return true;
|
||||
}
|
||||
catch (RedisConnectionException ex)
|
||||
{
|
||||
Log.Error(ex, "Connessione Redis persa durante il flush di {pattern}", pattern);
|
||||
return false;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Error(ex, "Errore imprevisto nel flush pattern {pattern}", pattern);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public KeyValuePair<string, string>[] RedisGetHash(RedisKey redKey)
|
||||
{
|
||||
HashEntry[] rawData = redisDb.HashGetAll(redKey);
|
||||
@@ -3455,6 +3529,7 @@ namespace MP.IOC.Data
|
||||
public async Task<bool> RemRebootLogAddAsync(RemoteRebootLogModel newRec)
|
||||
{
|
||||
bool fatto = false;
|
||||
#if false
|
||||
// insert del record
|
||||
fatto = await IocDbController.RemRebootLogAddAsync(newRec);
|
||||
// pulizia record vecchi
|
||||
@@ -3465,12 +3540,21 @@ namespace MP.IOC.Data
|
||||
int.TryParse(confVal, out num2keep);
|
||||
}
|
||||
fatto = await IocDbController.RemRebootLogKeepLastAsync(num2keep);
|
||||
#endif
|
||||
// insert del record + pulizia
|
||||
|
||||
string confVal = await tryGetConfig("IO_NumReboot2Keep");
|
||||
int num2keep = int.TryParse(confVal, out int n) ? n : 5;
|
||||
fatto = await IocDbController.RemRebootLogAddAndCleanAsync(newRec, num2keep);
|
||||
|
||||
// svuota cache
|
||||
var currKey = $"{Utils.redisRemRebLog}:*";
|
||||
await RedisFlushPatternAsync(currKey);
|
||||
return fatto;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Recupera tutti i record di RemoteRebootLog
|
||||
/// </summary>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Version>6.16.2604.2409</Version>
|
||||
<Version>6.16.2604.2711</Version>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<body>
|
||||
<i>Modulo MP-IOC </i>
|
||||
<h4>Versione: 6.16.2604.2409</h4>
|
||||
<h4>Versione: 6.16.2604.2711</h4>
|
||||
<br /> Note di rilascio:
|
||||
<ul>
|
||||
<li>
|
||||
|
||||
@@ -1 +1 @@
|
||||
6.16.2604.2409
|
||||
6.16.2604.2711
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<item>
|
||||
<version>6.16.2604.2409</version>
|
||||
<version>6.16.2604.2711</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>
|
||||
|
||||
Reference in New Issue
Block a user