diff --git a/MP.RIOC/Services/MetricsDbFlushService.cs b/MP.RIOC/Services/MetricsDbFlushService.cs
index 10252886..c268e6d0 100644
--- a/MP.RIOC/Services/MetricsDbFlushService.cs
+++ b/MP.RIOC/Services/MetricsDbFlushService.cs
@@ -66,6 +66,59 @@ namespace MP.RIOC.Services
#region Private Methods
+ ///
+ /// Cancellazione ricorsiva chiavi ausiliarie (:status, :errors) e rimozione dall'indice
+ ///
+ private async Task DeleteAuxKeysAndIndexAsync(RedisKey sKey, RedisKey indexKey, IBatch batch)
+ {
+ string sKeyStr = sKey.ToString();
+ string keyDir = sKeyStr.Substring(0, sKeyStr.LastIndexOf(':'));
+
+ // Cancella :status dal sorted set e dalla hash
+ string statusKey = keyDir + ":status";
+ await batch.SortedSetRemoveAsync(indexKey, statusKey);
+ await batch.KeyDeleteAsync(statusKey);
+
+ // Cancella :errors dal sorted set e dalla hash
+ string errorKey = keyDir + ":errors";
+ await batch.SortedSetRemoveAsync(indexKey, errorKey);
+ await batch.KeyDeleteAsync(errorKey);
+
+ // Cancella chiave ausiliaria :status anche da un eventuale indice days se presente
+ if (statusKey.Contains(":stats:hours:"))
+ {
+ string daysIndex = statusKey.Replace(":stats:hours:", ":stats:days:");
+ try
+ {
+ await batch.SortedSetRemoveAsync(daysIndex, statusKey);
+ }
+ catch { }
+ }
+
+ // Cancella chiave ausiliaria :errors anche da un eventuale indice days se presente
+ if (errorKey.Contains(":stats:hours:"))
+ {
+ string daysIndex = errorKey.Replace(":stats:hours:", ":stats:days:");
+ try
+ {
+ await batch.SortedSetRemoveAsync(daysIndex, errorKey);
+ }
+ catch { }
+ }
+ }
+
+ ///
+ /// Recupera il TTL residuo di una chiave Redis (-1 = nessun TTL, -2 = chiave non esiste)
+ ///
+ private TimeSpan? GetKeyTtl(RedisKey key)
+ {
+ try
+ {
+ return _db.KeyTimeToLive(key);
+ }
+ catch { return null; }
+ }
+
///
/// Processing dati giornalieri (da Redis a DB)
///
@@ -114,7 +167,7 @@ namespace MP.RIOC.Services
// Verifica se la chiave è "orfana" (nessun TTL o TTL troppo lungo >30gg)
var keyTtl = GetKeyTtl(sKey);
- bool isOrphanKey = keyTtl?.TotalSeconds < 0 || keyTtl?.TotalSeconds > 30.25 * 24 * 3600;
+ bool isOrphanKey = keyTtl?.TotalSeconds < 0 || keyTtl?.TotalHours > 30.25 * 24;
// Se era scaduta o orfana e abbiamo il permesso, segnamola per la cancellazione
if ((meta.Timestamp < currentDayStart || isOrphanKey) && deleteConfirmed)
@@ -199,59 +252,6 @@ namespace MP.RIOC.Services
}
}
- ///
- /// Recupera il TTL residuo di una chiave Redis (-1 = nessun TTL, -2 = chiave non esiste)
- ///
- private TimeSpan? GetKeyTtl(RedisKey key)
- {
- try
- {
- return _db.KeyTimeToLive(key);
- }
- catch { return null; }
- }
-
- ///
- /// Cancellazione ricorsiva chiavi ausiliarie (:status, :errors) e rimozione dall'indice
- ///
- private async Task DeleteAuxKeysAndIndexAsync(RedisKey sKey, RedisKey indexKey, IBatch batch)
- {
- string sKeyStr = sKey.ToString();
- string keyDir = sKeyStr.Substring(0, sKeyStr.LastIndexOf(':'));
-
- // Cancella :status dal sorted set e dalla hash
- string statusKey = keyDir + ":status";
- await batch.SortedSetRemoveAsync(indexKey, statusKey);
- await batch.KeyDeleteAsync(statusKey);
-
- // Cancella :errors dal sorted set e dalla hash
- string errorKey = keyDir + ":errors";
- await batch.SortedSetRemoveAsync(indexKey, errorKey);
- await batch.KeyDeleteAsync(errorKey);
-
- // Cancella chiave ausiliaria :status anche da un eventuale indice days se presente
- if (statusKey.Contains(":stats:hours:"))
- {
- string daysIndex = statusKey.Replace(":stats:hours:", ":stats:days:");
- try
- {
- await batch.SortedSetRemoveAsync(daysIndex, statusKey);
- }
- catch { }
- }
-
- // Cancella chiave ausiliaria :errors anche da un eventuale indice days se presente
- if (errorKey.Contains(":stats:hours:"))
- {
- string daysIndex = errorKey.Replace(":stats:hours:", ":stats:days:");
- try
- {
- await batch.SortedSetRemoveAsync(daysIndex, errorKey);
- }
- catch { }
- }
- }
-
///
/// Processing dati orari (da Redis a DB)
///
@@ -299,10 +299,9 @@ namespace MP.RIOC.Services
var sKey = (RedisKey)$"{statKey}";
if (!TryParseKeyMetadata(sKey, out var meta) || !meta.IsHourType) continue;
- //// Verifica se la chiave è "orfana" (nessun TTL o TTL troppo lungo)
- //var keyTtl = await _db.KeyTtlAsync(sKey);
- //bool isOrphanKey = keyTtl?.TotalSeconds < 0 || keyTtl?.TotalSeconds > 30.25 * 24 * 3600;
- bool isOrphanKey = false;
+ // Verifica se la chiave è "orfana" (nessun TTL o TTL troppo lungo >30gg)
+ var keyTtl = GetKeyTtl(sKey);
+ bool isOrphanKey = keyTtl?.TotalSeconds < 0 || keyTtl?.TotalHours > 30.25 * 24;
// Se era scaduta o orfana e abbiamo il permesso, segnamola per la cancellazione
if ((meta.Timestamp < currentHourStart || isOrphanKey) && deleteConfirmed)
@@ -379,13 +378,14 @@ namespace MP.RIOC.Services
int deletedCount = 0;
foreach (var key in keysToDelete)
{
- _ = batch.KeyDeleteAsync(key);
+ await batch.KeyDeleteAsync(key);
deletedCount++;
}
batch.Execute();
Log.Info($"[CLEANUP HOUR] Deleted {deletedCount} expired metric keys from Redis");
}
}
+
private bool TryParseKeyMetadata(RedisKey key, out KeyMeta meta)
{
meta = new KeyMeta();
@@ -414,60 +414,7 @@ namespace MP.RIOC.Services
catch { return false; }
}
-#if false
- private bool TryParseKeyMetadata(RedisKey key, out string dest, out string method, out string machId, out DateTime timestamp, out bool isHourType)
- {
- dest = "NA";
- method = "NA";
- machId = "ALL";
- timestamp = DateTime.MinValue;
- isHourType = true;
- try
- {
- string k = key.ToString();
- string relativeKey = k.Replace($"{_redisBaseKey}:", "");
- var parts = relativeKey.Split(':');
-
- if (parts.Length < 4) return false;
-
- string type = parts[1]; // "hour" o "day"
- dest = parts[2];
-
- if (type == "hour")
- {
- isHourType = true;
- method = parts[3];
- if (parts.Length >= 5 && DateTime.TryParseExact(parts[4], "yyyyMMddHH", CultureInfo.InvariantCulture, DateTimeStyles.None, out var dt))
- {
- timestamp = dt;
- return true;
- }
- }
- else if (type == "day")
- {
- isHourType = false;
- method = "DAILY";
- string rawDate = "";
- if (parts.Length >= 5)
- {
- machId = parts[3];
- rawDate = parts[4];
- }
- else
- {
- rawDate = parts[3];
- }
- if (DateTime.TryParseExact(rawDate, "yyyyMMdd", CultureInfo.InvariantCulture, DateTimeStyles.None, out var dt))
- {
- timestamp = dt;
- return true;
- }
- }
- }
- catch { }
- return false;
- }
-#endif
+ #endregion Private Methods
private record KeyMeta
{
@@ -477,7 +424,5 @@ namespace MP.RIOC.Services
public DateTime Timestamp = DateTime.MinValue;
public bool IsHourType = true;
}
-
- #endregion Private Methods
}
-}
+}
\ No newline at end of file