From bdcc858bc5795454b6956b3d0e351d0e3ac4bdfe Mon Sep 17 00:00:00 2001 From: Mikhail Trubnikov Date: Mon, 1 Jun 2026 11:58:08 +1000 Subject: [PATCH] =?UTF-8?q?feat(core,=20infrastructure):=20UnitService=20-?= =?UTF-8?q?=20=D0=BC=D0=B0=D1=81=D1=81=D0=BE=D0=B2=D0=BE=D0=B5=20=D0=BF?= =?UTF-8?q?=D0=BE=D0=BB=D1=83=D1=87=D0=B5=D0=BD=D0=B8=D0=B5=20=D1=8E=D0=BD?= =?UTF-8?q?=D0=B8=D1=82=D0=BE=D0=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Implementations/UnitCacheService.cs | 38 ++++++++++---- PARR.DAL/Context/DataContext.cs | 2 +- .../Redis/RedisCacheService.cs | 51 ++++++++++--------- 3 files changed, 57 insertions(+), 34 deletions(-) diff --git a/PARR.Core/Services/UnitService/Implementations/UnitCacheService.cs b/PARR.Core/Services/UnitService/Implementations/UnitCacheService.cs index cd608135..671b05fb 100644 --- a/PARR.Core/Services/UnitService/Implementations/UnitCacheService.cs +++ b/PARR.Core/Services/UnitService/Implementations/UnitCacheService.cs @@ -83,20 +83,40 @@ namespace PARR.Core.Services.UnitService.Implementations return (HashKey: hashKey, FieldKey: fieldKey); }).ToList(); + logger.LogDebug("Необходимо найти инорфмацию для {Count} объектов.", ids.Count); + // Получаем из кэш var cacheData = await redisCacheService.GetHashFieldsAsync(keys, true); - // проверить, если получили все элементы, вернуть - // если не все, докачать из бд + logger.LogDebug("Из кэша получена информация о {Count} объектах.", cacheData.Count); + + var resultDictionary = cacheData.ToDictionary(unit => unit.Id, unit => unit); + + // Проверям каких данных нет в кэш, догрузим из из БД + if (resultDictionary.Count < ids.Count) + { + // Находим id которых нет в кэше + var missingIds = ids.Where(id => !resultDictionary.ContainsKey(id)).ToHashSet(); + + logger.LogDebug("Запрашиваем из БД дополнительно {Count} юнитов", missingIds.Count); + + var dbData = await GetUnitsAsync(missingIds); + + foreach (var unit in dbData) + { + resultDictionary[unit.Id] = unit; + + // Добавляем в кэш + var hashKey = redisCacheService.GetKey(CacheKeys.Unit.UnitHashWithBucket(unit.Id)); + var unitKey = redisCacheService.GetKey(CacheKeys.Unit.UnitItem(unit.Id)); + + await redisCacheService.SetHashFieldAsync(hashKey, unitKey, unit, CacheTtl, true); + } + } + // сохранить докаченные в кэш + ттл + не забыть указать сжатие (может вообще этот метод вынести отдельно, так как пересекается когда по одному) - //var dbData = await GetUnitsAsync(ids); - - - - //todo: - - return null; + return resultDictionary; } /// diff --git a/PARR.DAL/Context/DataContext.cs b/PARR.DAL/Context/DataContext.cs index 928ce61a..fe33528e 100644 --- a/PARR.DAL/Context/DataContext.cs +++ b/PARR.DAL/Context/DataContext.cs @@ -203,7 +203,7 @@ namespace PARR.DAL.Context new { Name = nameof(SettingsFromDb.Category), Description = "Категория создаваемого объекта в ЕСПП", Value = "регламентная работа" }, new { Name = nameof(SettingsFromDb.TemplatePrefixName), Description = "Префикс имени шаблона в ЕСПП", Value = "%PREFIX%-ЭИТИ-ПТК-ПАРР" }, new { Name = nameof(SettingsFromDb.RobotAttemptsNumber), Description = "Количество попыток выполнения задания роботом", Value = "3" }, - new { Name = nameof(SettingsFromDb.RobotWaitTime), Description = "Время ожидания выполнения роботом задания", Value = "00:15:00" }, + new { Name = nameof(SettingsFromDb.RobotWaitTime), Description = "Время ожидания выполнения роботом задания", Value = "00:10:00" }, new { Name = nameof(SettingsFromDb.EsppScheduleTimezone), Description = "Расписание регламентной работы - В каком часовом поясе", Value = "MSK" }, //new { Name = nameof(SettingsFromDb.ScheduleExcludeType), Description = "Расписание регламентной работы - Тип исключения", Value = "Выполнить ТОЛЬКО В указанном календаре" }, //new { Name = nameof(SettingsFromDb.ScheduleExcludeCalendar), Description = "Расписание регламентной работы - Календарь", Value = "8x5 (8.00-17.00)" }, diff --git a/PARR.Infrastructure/Redis/RedisCacheService.cs b/PARR.Infrastructure/Redis/RedisCacheService.cs index 3ef715c1..45155695 100644 --- a/PARR.Infrastructure/Redis/RedisCacheService.cs +++ b/PARR.Infrastructure/Redis/RedisCacheService.cs @@ -226,7 +226,8 @@ namespace PARR.Infrastructure.Redis // хранили в байтах try { - return DeserializeWithCompression(value); + byte[] rawBytes = value!; + return DeserializeWithCompression(rawBytes); } catch (Exception ex) { @@ -236,7 +237,7 @@ namespace PARR.Infrastructure.Redis else { // хранили в строке - return JsonSerializer.Deserialize(value); + return JsonSerializer.Deserialize(value!); } } @@ -257,33 +258,35 @@ namespace PARR.Infrastructure.Redis logger.LogDebug("Сформировал {Count} одновременных запросов в кэш", tasks.Count); // Ждем ответа от текущей порции - RedisValue[] results = await Task.WhenAll(tasks); + RedisValue[] results = await Task.WhenAll(tasks); // Парсим foreach (var result in results) { - if (result.HasValue) - { - if (useCompression) - { - try - { - var item = DeserializeWithCompression((byte[])result); - if (item != null) - allItems.Add(item); - } - catch (Exception ex) - { - throw new InvalidOperationException("Формат данных не байты.", ex); - } - } - else - { - var item = JsonSerializer.Deserialize(result.ToString()); - if (item != null) - allItems.Add(item); - } + if (!result.HasValue) + continue; + if (useCompression) + { + // Сжатые данные + try + { + byte[] rawBytes = result!; + var data = DeserializeWithCompression(rawBytes); + if (data != null) + allItems.Add(data!); + } + catch (Exception ex) + { + throw new InvalidOperationException("Формат данных не байты.", ex); + } + } + else + { + // Json + var data = JsonSerializer.Deserialize(result!.ToString()); + if (data != null) + allItems.Add(data); } }