diff --git a/WebDoorCreator.API/Controllers/QueueController.cs b/WebDoorCreator.API/Controllers/QueueController.cs index 9498d25..3cf4e79 100644 --- a/WebDoorCreator.API/Controllers/QueueController.cs +++ b/WebDoorCreator.API/Controllers/QueueController.cs @@ -45,6 +45,24 @@ namespace WebDoorCreator.API.Controllers return answ; } + /// + /// Cleanup dati delle code di calcolo + /// + /// Chiave x auth di reset + /// + [HttpPost("DCCacheCleanup")] + public async Task DCCacheCleanup(string passPhrase) + { + string answ = "NA"; + bool fatto = false; + if (passPhrase == "bbbBirdIsTheWord") + { + fatto = await QDataServ.DoorCalcCacheCleanup(); + } + answ = fatto ? "OK" : "NO"; + return answ; + } + /// /// Reset delle code di chiamata x ripetere simulazione /// diff --git a/WebDoorCreator.Core/Constants.cs b/WebDoorCreator.Core/Constants.cs index 98e1821..643e707 100644 --- a/WebDoorCreator.Core/Constants.cs +++ b/WebDoorCreator.Core/Constants.cs @@ -19,6 +19,7 @@ namespace WebDoorCreator.Core // REDIS KEY Dati correnti x QueueMan public static readonly string LAST_CALC_REQ_KEY = $"{BASE_HASH}:Current:LastCalcReq"; public static readonly string LAST_CALC_DONE_KEY = $"{BASE_HASH}:Current:LastCalcDone"; + public static readonly string LAST_DOOR_REFR_KEY = $"{BASE_HASH}:Current:LastDoorRefr"; public static readonly string CALC_REQ_DONE = $"{BASE_HASH}:CalcRequests:Completed"; public static readonly string CALC_REQ_ERRS = $"{BASE_HASH}:CalcRequests:Errors"; public static readonly string CALC_REQ_PEND = $"{BASE_HASH}:CalcRequests:Pending"; diff --git a/WebDoorCreator.Data/Services/QueueDataService.cs b/WebDoorCreator.Data/Services/QueueDataService.cs index 708f260..244631b 100644 --- a/WebDoorCreator.Data/Services/QueueDataService.cs +++ b/WebDoorCreator.Data/Services/QueueDataService.cs @@ -63,6 +63,62 @@ namespace WebDoorCreator.Data.Services redisConn.Dispose(); } + /// + /// Effettua pulizia cache dati calcolo porte + /// + /// + /// + public async Task DoorCalcCacheCleanup() + { + /*---------------------------------- + * Recupero Rev corrente porta o inizializza cercando + * - coda calcoli pending + * - coda errori + * - coda calcoli eseguiti + * + * se non trova riparte da 1 + * + ----------------------------------*/ + bool fatto = false; + int numDayPre = 30; + if (!string.IsNullOrEmpty(_configuration.GetValue("RumtimeOpt:MaxDayCalcCache"))) + { + numDayPre = _configuration.GetValue("RumtimeOpt:MaxDayCalcCache"); + } + DateTime dtLimite = DateTime.Now.AddDays(-numDayPre); + // recupero elenco di tutti i refresh porte... + var refreshStatus = await DoorRefreshStatus(); + // ciclo su tutti e cerco quelli + vecchi di x giorni + if (refreshStatus != null && refreshStatus.Count > 0) + { + DateTime dtCurr = DateTime.Now; + foreach (var item in refreshStatus) + { + // confronto data-ora della singola porta... + if (!string.IsNullOrEmpty(item.Key)) + { + try + { + var rawDate = JsonConvert.DeserializeObject(item.Value); + // se esiste e SE è scaduto + if (rawDate > DateTime.MinValue && rawDate < dtLimite) + { + // cancello i dati! + await RequestProcessingRemove(item.Key); + await RequestErrRemove(item.Key); + await RequestDoneRemove(item.Key); + await DoorRefreshRemove(item.Key); + } + } + catch + { } + } + } + } + await Task.Delay(1); + return fatto; + } + /// /// Restitusice gli errori della porta in oggetto /// @@ -94,6 +150,58 @@ namespace WebDoorCreator.Data.Services return errVal.ToString(); } + /// + /// Remove for single hash record + /// + /// + public async Task DoorRefreshRemove(string doorId) + { + RedisKey currKey = new RedisKey(Constants.LAST_DOOR_REFR_KEY); + bool fatto = await RedHashRemove(currKey, doorId); + return fatto; + } + + /// + /// Get Door (last) Refresh status + /// + /// Dictionary of DoorId, saveVersNumb + public async Task> DoorRefreshStatus() + { + string source = "REDIS"; + long numReq = 0; + Dictionary dictResult = new Dictionary(); + // cerco da cache + RedisKey currKey = new RedisKey(Constants.LAST_DOOR_REFR_KEY); + Stopwatch stopWatch = new Stopwatch(); + stopWatch.Start(); + numReq = redisDb.HashLength(currKey); + if (numReq > 0) + { + var rawData = await redisDb.HashGetAllAsync(currKey); + foreach (var item in rawData) + { + dictResult.Add($"{item.Name}", $"{item.Value}"); + } + } + stopWatch.Stop(); + TimeSpan ts = stopWatch.Elapsed; + Log.Debug($"DoorRefreshStatus | {source} in: {ts.TotalMilliseconds} ms"); + return dictResult; + } + + /// + /// Upsert info ultimo update di una porta + /// + /// Dictionary of DoorId, saveVersNumb + public async Task DoorRefreshUpsert(string doorId) + { + DateTime adesso = DateTime.Now; + string sAdesso = JsonConvert.SerializeObject(adesso); + RedisKey currKey = new RedisKey(Constants.LAST_DOOR_REFR_KEY); + long numReq = await RedHashUpsert(currKey, doorId, sAdesso); + return numReq; + } + /// /// Restitusice l'SVG della porta in oggetto /// @@ -190,23 +298,6 @@ namespace WebDoorCreator.Data.Services return numReq; } - /// - /// Remove for single hash record - /// - /// Chiave redis della Hashlist - /// Chiave nella HashList - /// Esito rimozione - public async Task RedHashRemove(RedisKey currKey, string chiave) - { - bool fatto = false; - Stopwatch stopWatch = new Stopwatch(); - stopWatch.Start(); - fatto = await redisDb.HashDeleteAsync(currKey, chiave); - stopWatch.Stop(); - TimeSpan ts = stopWatch.Elapsed; - Log.Trace($"RedHashRemove | {currKey} | in: {ts.TotalMilliseconds} ms"); - return fatto; - } /// /// Verify existence for single hash record /// @@ -233,6 +324,24 @@ namespace WebDoorCreator.Data.Services return result; } + /// + /// Remove for single hash record + /// + /// Chiave redis della Hashlist + /// Chiave nella HashList + /// Esito rimozione + public async Task RedHashRemove(RedisKey currKey, string chiave) + { + bool fatto = false; + Stopwatch stopWatch = new Stopwatch(); + stopWatch.Start(); + fatto = await redisDb.HashDeleteAsync(currKey, chiave); + stopWatch.Stop(); + TimeSpan ts = stopWatch.Elapsed; + Log.Trace($"RedHashRemove | {currKey} | in: {ts.TotalMilliseconds} ms"); + return fatto; + } + /// /// Get Queue request done /// @@ -534,33 +643,12 @@ namespace WebDoorCreator.Data.Services /// indice/versione del calcolo DDF public async Task SendCalcReq(int DoorId, string FullDDF) { - int currVers = 1; - string sDoorId = $"{DoorId}"; - string sCurrVers = ""; Stopwatch stopWatch = new Stopwatch(); stopWatch.Start(); - - // per prima cosa controllo se ho GIA' in coda qualcosa come richieste - long numPending = await NumRequestPending(); - - // se coda non vuota: cerco la DoorId corrente, se c'è sovrascrivo versione altrimenti - if (numPending != 0) - { - var currPending = await RequestPending(); - if (currPending != null) - { - if (currPending.ContainsKey(sDoorId)) - { - sCurrVers = currPending[sDoorId]; - int.TryParse(sCurrVers, out currVers); - currVers++; - } - } - } - sCurrVers = $"{currVers}"; - // inserisco in coda - numPending = await RequestPendingUpsert(sDoorId, sCurrVers); - // elimino da code errori + string sDoorId = $"{DoorId}"; + int currVers = await DoorCalcRev(sDoorId); + string sCurrVers = $"{currVers}"; + // elimino da code errori (SE fosse presente) await RequestErrRemove(sDoorId); // salvo nell'archivio REDIS delle porte il DDF corrente (key=doorId.versNumb), potrebbe @@ -569,7 +657,7 @@ namespace WebDoorCreator.Data.Services await redisDb.StringSetAsync(currDdfKey, FullDDF, DayLongCache); // invio sul canale dei messaggi il numero di items in coda attuali x chiedere esecuzione... - numPending = await NumRequestPending(); + long numPending = await NumRequestPending(); bool answ = CalcReqPipe.saveAndSendMessage(Constants.LAST_CALC_REQ_KEY, $"{numPending}"); stopWatch.Stop(); @@ -628,8 +716,6 @@ namespace WebDoorCreator.Data.Services return dictResult; } - protected static bool queueLock { get; set; } = false; - #endregion Public Methods #region Protected Fields @@ -651,8 +737,81 @@ namespace WebDoorCreator.Data.Services #endregion Protected Fields + #region Protected Properties + + protected static bool queueLock { get; set; } = false; + + #endregion Protected Properties + #region Protected Methods + /// + /// Recupera revisione corrente della porta o inizializza + /// + /// + /// + protected async Task DoorCalcRev(string sDoorId) + { + /*---------------------------------- + * Recupero Rev corrente porta o inizializza cercando + * - coda calcoli pending + * - coda errori + * - coda calcoli eseguiti + * + * se non trova riparte da 1 + * + ----------------------------------*/ + int currVers = 1; + string sCurrVers = ""; + // per prima cosa controllo se ho GIA' in coda qualcosa come richieste + if (await NumRequestPending() > 0) + { + var currPending = await RequestPending(); + if (currPending != null) + { + if (currPending.ContainsKey(sDoorId)) + { + sCurrVers = currPending[sDoorId]; + int.TryParse(sCurrVers, out currVers); + currVers++; + } + } + } + // cerco coda errori + if (await NumRequestErrors() > 0) + { + var currErrors = await RequestErr(); + if (currErrors != null) + { + if (currErrors.ContainsKey(sDoorId)) + { + sCurrVers = currErrors[sDoorId]; + int.TryParse(sCurrVers, out currVers); + currVers++; + } + } + } + // cerco coda task completati + if (await NumRequestDone() > 0) + { + var currDone = await RequestDone(); + if (currDone != null) + { + if (currDone.ContainsKey(sDoorId)) + { + sCurrVers = currDone[sDoorId]; + int.TryParse(sCurrVers, out currVers); + currVers++; + } + } + } + // inserisco in coda x calcoli + await RequestPendingUpsert(sDoorId, $"{currVers}"); + // metto in coda "last calc" la porta corrente x pulizia successiva + await DoorRefreshUpsert(sDoorId); + return currVers; + } + /// /// Recupero chiave da redis /// diff --git a/WebDoorCreator.UI/appsettings.json b/WebDoorCreator.UI/appsettings.json index 95096f3..f3b6956 100644 --- a/WebDoorCreator.UI/appsettings.json +++ b/WebDoorCreator.UI/appsettings.json @@ -27,6 +27,9 @@ "DisableIdentMigrate": true, "DisableWDCMigrate": true }, + "RumtimeOpt": { + "MaxDayCalcCache": 7 + }, "ConfDDF": { "Header": [ "#WEBDOORCREATOR",