feat(api,core,domain): Ключи для редис
This commit is contained in:
@@ -24,19 +24,19 @@ namespace PARR.API.Controllers.V1.Statistics
|
|||||||
private readonly ITemplateRepository templateService;
|
private readonly ITemplateRepository templateService;
|
||||||
//private readonly IResponseAreaService responseAreaService;
|
//private readonly IResponseAreaService responseAreaService;
|
||||||
private readonly IMapper mapper;
|
private readonly IMapper mapper;
|
||||||
private readonly IWorkLoadService workLoadService;
|
//private readonly IWorkLoadService workLoadService;
|
||||||
|
|
||||||
public StatResponseAreaWorkLoadController(
|
public StatResponseAreaWorkLoadController(
|
||||||
ITemplateRepository templateService,
|
ITemplateRepository templateService,
|
||||||
//IResponseAreaService responseAreaService,
|
//IResponseAreaService responseAreaService,
|
||||||
IMapper mapper,
|
IMapper mapper
|
||||||
IWorkLoadService workLoadService
|
//IWorkLoadService workLoadService
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
this.templateService = templateService;
|
this.templateService = templateService;
|
||||||
//this.responseAreaService = responseAreaService;
|
//this.responseAreaService = responseAreaService;
|
||||||
this.mapper = mapper;
|
this.mapper = mapper;
|
||||||
this.workLoadService = workLoadService;
|
//this.workLoadService = workLoadService;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -19,21 +19,21 @@ namespace PARR.API.Controllers.V1.Statistics
|
|||||||
public class StatWorkGroupWorkLoadController : BaseApiController
|
public class StatWorkGroupWorkLoadController : BaseApiController
|
||||||
{
|
{
|
||||||
private readonly ITemplateRepository templateService;
|
private readonly ITemplateRepository templateService;
|
||||||
private readonly IWorkLoadService workLoadService;
|
//private readonly IWorkLoadService workLoadService;
|
||||||
//private readonly IWorkGroupService workGroupService;
|
//private readonly IWorkGroupService workGroupService;
|
||||||
private readonly IMapper mapper;
|
private readonly IMapper mapper;
|
||||||
private readonly ILogger<StatWorkGroupWorkLoadController> logger;
|
private readonly ILogger<StatWorkGroupWorkLoadController> logger;
|
||||||
|
|
||||||
public StatWorkGroupWorkLoadController(
|
public StatWorkGroupWorkLoadController(
|
||||||
ITemplateRepository templateService,
|
ITemplateRepository templateService,
|
||||||
IWorkLoadService workLoadService,
|
//IWorkLoadService workLoadService,
|
||||||
//IWorkGroupService workGroupService,
|
//IWorkGroupService workGroupService,
|
||||||
IMapper mapper,
|
IMapper mapper,
|
||||||
ILogger<StatWorkGroupWorkLoadController> logger
|
ILogger<StatWorkGroupWorkLoadController> logger
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
this.templateService = templateService;
|
this.templateService = templateService;
|
||||||
this.workLoadService = workLoadService;
|
//this.workLoadService = workLoadService;
|
||||||
//this.workGroupService = workGroupService;
|
//this.workGroupService = workGroupService;
|
||||||
this.mapper = mapper;
|
this.mapper = mapper;
|
||||||
this.logger = logger;
|
this.logger = logger;
|
||||||
|
|||||||
@@ -11,21 +11,21 @@ namespace PARR.API.Controllers.V1.Statistics
|
|||||||
public class StatWorkWorkLoadController : BaseApiController
|
public class StatWorkWorkLoadController : BaseApiController
|
||||||
{
|
{
|
||||||
private readonly ITemplateRepository templateService;
|
private readonly ITemplateRepository templateService;
|
||||||
private readonly IWorkLoadService workLoadService;
|
//private readonly IWorkLoadService workLoadService;
|
||||||
private readonly IMapper mapper;
|
private readonly IMapper mapper;
|
||||||
private readonly ILogger<StatWorkWorkLoadController> logger;
|
private readonly ILogger<StatWorkWorkLoadController> logger;
|
||||||
//private readonly IWorkGroupService workGroupService;
|
//private readonly IWorkGroupService workGroupService;
|
||||||
|
|
||||||
public StatWorkWorkLoadController(
|
public StatWorkWorkLoadController(
|
||||||
ITemplateRepository templateService,
|
ITemplateRepository templateService,
|
||||||
IWorkLoadService workLoadService,
|
//IWorkLoadService workLoadService,
|
||||||
IMapper mapper,
|
IMapper mapper,
|
||||||
ILogger<StatWorkWorkLoadController> logger
|
ILogger<StatWorkWorkLoadController> logger
|
||||||
//IWorkGroupService workGroupService
|
//IWorkGroupService workGroupService
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
this.templateService = templateService;
|
this.templateService = templateService;
|
||||||
this.workLoadService = workLoadService;
|
//this.workLoadService = workLoadService;
|
||||||
this.mapper = mapper;
|
this.mapper = mapper;
|
||||||
this.logger = logger;
|
this.logger = logger;
|
||||||
//this.workGroupService = workGroupService;
|
//this.workGroupService = workGroupService;
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ using PARR.Core.Common.Interfaces;
|
|||||||
using PARR.Core.Repositories.Interfaces;
|
using PARR.Core.Repositories.Interfaces;
|
||||||
using PARR.Core.Services.NextRunServices;
|
using PARR.Core.Services.NextRunServices;
|
||||||
using PARR.Core.Services.Workload.Implementations;
|
using PARR.Core.Services.Workload.Implementations;
|
||||||
|
using PARR.Domain.Cache;
|
||||||
|
|
||||||
namespace PARR.API.Controllers.V1
|
namespace PARR.API.Controllers.V1
|
||||||
{
|
{
|
||||||
@@ -20,6 +21,7 @@ namespace PARR.API.Controllers.V1
|
|||||||
private readonly INextRunService nextRunService;
|
private readonly INextRunService nextRunService;
|
||||||
private readonly ITemplateRepository templateService;
|
private readonly ITemplateRepository templateService;
|
||||||
private readonly WorkloadCacheService workloadCacheService;
|
private readonly WorkloadCacheService workloadCacheService;
|
||||||
|
private readonly ILogger<TestController> logger;
|
||||||
|
|
||||||
public TestController(
|
public TestController(
|
||||||
IClientService clientService,
|
IClientService clientService,
|
||||||
@@ -27,7 +29,8 @@ namespace PARR.API.Controllers.V1
|
|||||||
INextRunService nextRunService,
|
INextRunService nextRunService,
|
||||||
ITemplateRepository templateService,
|
ITemplateRepository templateService,
|
||||||
MqSettings mqSettings,
|
MqSettings mqSettings,
|
||||||
WorkloadCacheService workloadCacheService
|
WorkloadCacheService workloadCacheService,
|
||||||
|
ILogger<TestController> logger
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
this.clientService = clientService;
|
this.clientService = clientService;
|
||||||
@@ -35,6 +38,7 @@ namespace PARR.API.Controllers.V1
|
|||||||
this.nextRunService = nextRunService;
|
this.nextRunService = nextRunService;
|
||||||
this.templateService = templateService;
|
this.templateService = templateService;
|
||||||
this.workloadCacheService = workloadCacheService;
|
this.workloadCacheService = workloadCacheService;
|
||||||
|
this.logger = logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -78,8 +82,25 @@ namespace PARR.API.Controllers.V1
|
|||||||
[HttpPost(ApiRoutes.Test.CreateCache)]
|
[HttpPost(ApiRoutes.Test.CreateCache)]
|
||||||
public async Task<IActionResult> CreateCache()
|
public async Task<IActionResult> CreateCache()
|
||||||
{
|
{
|
||||||
|
#region Test bucket id
|
||||||
|
|
||||||
// var aaa = await workloadCacheService.GetTemplateReportDataAsync();
|
var idList = new List<Guid>();
|
||||||
|
|
||||||
|
for (int i = 0; i < 100; i++)
|
||||||
|
idList.Add( Guid.NewGuid());
|
||||||
|
|
||||||
|
foreach(var id in idList.OrderBy(t => t))
|
||||||
|
{
|
||||||
|
var key = CacheKeys.Unit.UnitHashWithBucket(id);
|
||||||
|
var redisKey = redisCacheService.GetKey(key);
|
||||||
|
|
||||||
|
logger.LogDebug("Id: {Id}, key: '{Key}', redis key: '{RedisKey}'", id, key, redisKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
// var aaa = await workloadCacheService.GetTemplateReportDataAsync();
|
||||||
|
|
||||||
//var val = await redisCacheService.GetCachedDataAsync<object>("96dAoIH/8Q9Bg8VY");
|
//var val = await redisCacheService.GetCachedDataAsync<object>("96dAoIH/8Q9Bg8VY");
|
||||||
|
|
||||||
|
|||||||
@@ -21,7 +21,6 @@ namespace PARR.API.Installers
|
|||||||
|
|
||||||
services.AddTransient<IClientService, ClientService>();
|
services.AddTransient<IClientService, ClientService>();
|
||||||
services.AddTransient<IAuthService, AuthService>();
|
services.AddTransient<IAuthService, AuthService>();
|
||||||
services.AddTransient<IWorkLoadService, WorkLoadService>();
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ using PARR.API.Settings;
|
|||||||
using PARR.Core.Common.Interfaces;
|
using PARR.Core.Common.Interfaces;
|
||||||
using PARR.Core.Repositories.Interfaces;
|
using PARR.Core.Repositories.Interfaces;
|
||||||
using PARR.Core.Repositories.Interfaces.Unit;
|
using PARR.Core.Repositories.Interfaces.Unit;
|
||||||
|
using PARR.Domain.Cache;
|
||||||
using PARR.Domain.Common.Roles;
|
using PARR.Domain.Common.Roles;
|
||||||
using PARR.Domain.Settings;
|
using PARR.Domain.Settings;
|
||||||
|
|
||||||
@@ -162,13 +163,15 @@ namespace PARR.API.Services.Implementations
|
|||||||
private string GetBlockKey(string ipAddress)
|
private string GetBlockKey(string ipAddress)
|
||||||
{
|
{
|
||||||
// d - deny
|
// d - deny
|
||||||
return $"d_{ipAddress}";
|
//return $"d_{ipAddress}";
|
||||||
|
return cacheService.GetKey(CacheKeys.UserAuth.Banned(ipAddress));
|
||||||
}
|
}
|
||||||
|
|
||||||
private string GetAllowKey(string ipAddress)
|
private string GetAllowKey(string ipAddress)
|
||||||
{
|
{
|
||||||
// a - allow
|
// a - allow
|
||||||
return $"a_{ipAddress}";
|
//return $"a_{ipAddress}";
|
||||||
|
return cacheService.GetKey(CacheKeys.UserAuth.Session(ipAddress));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,80 +0,0 @@
|
|||||||
using PARR.API.Services.Interfaces;
|
|
||||||
|
|
||||||
namespace PARR.API.Services.Implementations
|
|
||||||
{
|
|
||||||
internal class WorkLoadService : IWorkLoadService
|
|
||||||
{
|
|
||||||
//private readonly ICalendarService calendarService;
|
|
||||||
|
|
||||||
//public WorkLoadService(ICalendarService calendarService)
|
|
||||||
//{
|
|
||||||
// this.calendarService = calendarService;
|
|
||||||
//}
|
|
||||||
|
|
||||||
//private DateTime GetStartDate(int timeZoneOffsetHours)
|
|
||||||
//{
|
|
||||||
// //(так уже не делаем) начинаем не с сегодняшнего дня, а с завтра, так как на сегодня уже некоторые работы были проведены и их дата изменилась
|
|
||||||
// //return DateTimeOffset.UtcNow.AddHours(timeZoneOffsetHours).Date.AddDays(1);
|
|
||||||
|
|
||||||
// var dateWithTimeZoneOffset = calendarService.GetDateWithTimeZoneOffset(DateTimeOffset.UtcNow, timeZoneOffsetHours);
|
|
||||||
// //var dateWithAddDays = dateWithTimeZoneOffset.DateTime.AddDays(1);
|
|
||||||
// var dateWithAddDays = dateWithTimeZoneOffset.DateTime.AddDays(0);
|
|
||||||
|
|
||||||
// //var bbb = dateWithTimeZoneOffset.DateTime.AddDays(1);
|
|
||||||
|
|
||||||
// //return calendarService.GetDateWithTimeZoneOffset(DateTimeOffset.UtcNow, timeZoneOffsetHours).UtcDateTime.AddDays(1);
|
|
||||||
// return dateWithAddDays;
|
|
||||||
//}
|
|
||||||
|
|
||||||
|
|
||||||
//private DateTime GetEndDate(bool? isMonth, int timeZoneOffsetHours)
|
|
||||||
//{
|
|
||||||
// var startDate = GetStartDate(timeZoneOffsetHours);
|
|
||||||
|
|
||||||
// return isMonth == true ? startDate.AddDays(30) : startDate.AddDays(6);
|
|
||||||
//}
|
|
||||||
|
|
||||||
|
|
||||||
//public List<DateOnly> GetDatesForPeriod(WorkloadBaseQuery requestQuery)
|
|
||||||
//{
|
|
||||||
// var startDate = GetStartDate(requestQuery.TimeZoneOffsetHours);
|
|
||||||
// var endDate = GetEndDate(requestQuery.IsMonth, requestQuery.TimeZoneOffsetHours);
|
|
||||||
|
|
||||||
// //var daysList = new List<DateTimeOffset>();
|
|
||||||
|
|
||||||
// //daysList.Add(new DateTimeOffset(startDate, new TimeSpan(0)));
|
|
||||||
|
|
||||||
// //while (daysList.Last() < endDate)
|
|
||||||
// // daysList.Add(daysList.Last().AddDays(1));
|
|
||||||
|
|
||||||
// //return daysList.OrderBy(t => t).ToList();
|
|
||||||
|
|
||||||
// //var aaa = DateOnly.FromDateTime(startDate);
|
|
||||||
|
|
||||||
// return calendarService.GetDatesForPeriod(DateOnly.FromDateTime(startDate), DateOnly.FromDateTime(endDate));
|
|
||||||
//}
|
|
||||||
|
|
||||||
|
|
||||||
//public IQueryable<Template> FilterTemplatesQuery(IQueryable<Template> query, WorkloadBaseQuery requestQuery)
|
|
||||||
//{
|
|
||||||
// var startDate = GetStartDate(requestQuery.TimeZoneOffsetHours);
|
|
||||||
// var endDate = GetEndDate(requestQuery.IsMonth, requestQuery.TimeZoneOffsetHours);
|
|
||||||
|
|
||||||
// //query = query.Where(t =>
|
|
||||||
// // t.NextRun.DateTime.Date >= startDate.Date && t.NextRun.DateTime.Date <= endDate.Date
|
|
||||||
// // );
|
|
||||||
|
|
||||||
// query = query.Where(t =>
|
|
||||||
// t.NextRun.DateTime.AddHours(requestQuery.TimeZoneOffsetHours).Date >= startDate.Date && t.NextRun.DateTime.AddHours(requestQuery.TimeZoneOffsetHours).Date <= endDate.Date
|
|
||||||
// );
|
|
||||||
|
|
||||||
// if (requestQuery.IsActiveTemplate.HasValue)
|
|
||||||
// query = query.Where(t => t.IsActiveTemplate == requestQuery.IsActiveTemplate.Value);
|
|
||||||
|
|
||||||
// if (requestQuery.IsActiveSchedule.HasValue)
|
|
||||||
// query = query.Where(t => t.IsActiveSchedule == requestQuery.IsActiveSchedule.Value);
|
|
||||||
|
|
||||||
// return query;
|
|
||||||
//}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
namespace PARR.API.Services.Interfaces
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Сервисы по формированию статистики загрузки рабочих групп/ЗО, и тд регламентными работами
|
|
||||||
/// </summary>
|
|
||||||
public interface IWorkLoadService
|
|
||||||
{
|
|
||||||
//IQueryable<Template> FilterTemplatesQuery(IQueryable<Template> query, WorkloadBaseQuery requestQuery);
|
|
||||||
|
|
||||||
//List<DateOnly> GetDatesForPeriod(WorkloadBaseQuery requestQuery);
|
|
||||||
|
|
||||||
//DateTime GetEndDate(DateTime startDate, bool? isMonth);
|
|
||||||
//DateTime GetStartDate();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -4,6 +4,7 @@ using PARR.Core.Common.Interfaces;
|
|||||||
using PARR.Core.Repositories.Interfaces;
|
using PARR.Core.Repositories.Interfaces;
|
||||||
using PARR.Core.Services.Shortcodes;
|
using PARR.Core.Services.Shortcodes;
|
||||||
using PARR.Core.Services.Workload.Models;
|
using PARR.Core.Services.Workload.Models;
|
||||||
|
using PARR.Domain.Cache;
|
||||||
using PARR.Domain.Cache.Models;
|
using PARR.Domain.Cache.Models;
|
||||||
using PARR.Domain.DTOs.Workload;
|
using PARR.Domain.DTOs.Workload;
|
||||||
using PARR.Domain.Entities;
|
using PARR.Domain.Entities;
|
||||||
@@ -36,10 +37,10 @@ namespace PARR.Core.Services.Workload.Implementations
|
|||||||
|
|
||||||
|
|
||||||
//todo:----------- Настройки, вынести -----------
|
//todo:----------- Настройки, вынести -----------
|
||||||
/// <summary>
|
///// <summary>
|
||||||
/// Ключ КЭШ шаблонов
|
///// Ключ КЭШ шаблонов
|
||||||
/// </summary>
|
///// </summary>
|
||||||
private readonly string[] cacheTemplateKey = { "template", "report", "params" };
|
//private readonly string[] cacheTemplateKey = { "template", "report", "params" };
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// TTL кэша шаблонов
|
/// TTL кэша шаблонов
|
||||||
@@ -51,25 +52,25 @@ namespace PARR.Core.Services.Workload.Implementations
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
private readonly int maxCacheDiff = 1000;
|
private readonly int maxCacheDiff = 1000;
|
||||||
|
|
||||||
/// <summary>
|
///// <summary>
|
||||||
/// Ключ КЭШ, отчет о загруженности, все ЗО
|
///// Ключ КЭШ, отчет о загруженности, все ЗО
|
||||||
/// </summary>
|
///// </summary>
|
||||||
private readonly string[] cacheWorkloadResponseAreaAllKey = { "workload", "response area", "all" };
|
//private readonly string[] cacheWorkloadResponseAreaAllKey = { "workload", "response area", "all" };
|
||||||
|
|
||||||
/// <summary>
|
///// <summary>
|
||||||
/// Ключ КЭШ, отчет о загруженности, одна ЗО
|
///// Ключ КЭШ, отчет о загруженности, одна ЗО
|
||||||
/// </summary>
|
///// </summary>
|
||||||
private readonly string[] cacheWorkloadResponseAreaItemKey = { "workload", "response area", "item" };
|
//private readonly string[] cacheWorkloadResponseAreaItemKey = { "workload", "response area", "item" };
|
||||||
|
|
||||||
/// <summary>
|
///// <summary>
|
||||||
/// Ключ КЭШ, отчет о загруженности, все РГ
|
///// Ключ КЭШ, отчет о загруженности, все РГ
|
||||||
/// </summary>
|
///// </summary>
|
||||||
private readonly string[] cacheWorkloadWorkGroupAllKey = { "workload", "work group", "all" };
|
//private readonly string[] cacheWorkloadWorkGroupAllKey = { "workload", "work group", "all" };
|
||||||
|
|
||||||
/// <summary>
|
///// <summary>
|
||||||
/// Ключ КЭШ, отчет о загруженности, одна РГ
|
///// Ключ КЭШ, отчет о загруженности, одна РГ
|
||||||
/// </summary>
|
///// </summary>
|
||||||
private readonly string[] cacheWorkloadWorkGroupItemKey = { "workload", "work group", "item" };
|
//private readonly string[] cacheWorkloadWorkGroupItemKey = { "workload", "work group", "item" };
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// TTL кэша отчетов workload
|
/// TTL кэша отчетов workload
|
||||||
@@ -132,7 +133,7 @@ namespace PARR.Core.Services.Workload.Implementations
|
|||||||
|
|
||||||
templateCount++;
|
templateCount++;
|
||||||
|
|
||||||
#region Расчет и отрпавка прогресса
|
#region Расчет и отправка прогресса
|
||||||
// Считаем текущий процент(0 - 100). Этап идёт от 5% до 95%
|
// Считаем текущий процент(0 - 100). Этап идёт от 5% до 95%
|
||||||
var currentPercent = 5 + (int)((templateCount * 90.0) / totalTemplates);
|
var currentPercent = 5 + (int)((templateCount * 90.0) / totalTemplates);
|
||||||
|
|
||||||
@@ -153,11 +154,14 @@ namespace PARR.Core.Services.Workload.Implementations
|
|||||||
|
|
||||||
//3. Сохранить в Redis
|
//3. Сохранить в Redis
|
||||||
logger.LogDebug("Для сохранения в Redis подготовлен массив из {Count} строк", cacheData.Count);
|
logger.LogDebug("Для сохранения в Redis подготовлен массив из {Count} строк", cacheData.Count);
|
||||||
var hashKey = redisCacheService.GetKey(cacheTemplateKey);
|
//var hashKey = redisCacheService.GetKey(cacheTemplateKey);
|
||||||
|
var hashKey = redisCacheService.GetKey(CacheKeys.Workload.TemplateHash());
|
||||||
|
|
||||||
foreach (var item in cacheData)
|
foreach (var item in cacheData)
|
||||||
{
|
{
|
||||||
await redisCacheService.SetHashFieldAsync(hashKey, item.Data.TemplateId.ToString(), item, cacheTemplateTtl);
|
var templateKey = redisCacheService.GetKey(CacheKeys.Workload.Template(item.Data.TemplateId));
|
||||||
|
//await redisCacheService.SetHashFieldAsync(hashKey, item.Data.TemplateId.ToString(), item, cacheTemplateTtl);
|
||||||
|
await redisCacheService.SetHashFieldAsync(hashKey, templateKey, item, cacheTemplateTtl);
|
||||||
}
|
}
|
||||||
|
|
||||||
await progress.ReportAsync(100);
|
await progress.ReportAsync(100);
|
||||||
@@ -172,8 +176,9 @@ namespace PARR.Core.Services.Workload.Implementations
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public async Task DeleteTemplateCacheAsync()
|
public async Task DeleteTemplateCacheAsync()
|
||||||
{
|
{
|
||||||
var hashKey = redisCacheService.GetKey(cacheTemplateKey);
|
//var hashKey = redisCacheService.GetKey(cacheTemplateKey);
|
||||||
logger.LogDebug("Удаляю кэш шаблонов, {HashKey}", redisCacheService.GetKey(cacheTemplateKey));
|
var hashKey = redisCacheService.GetKey(CacheKeys.Workload.TemplateHash());
|
||||||
|
logger.LogDebug("Удаляю кэш шаблонов, {HashKey}", hashKey);
|
||||||
|
|
||||||
await redisCacheService.DeleteHashAsync(hashKey);
|
await redisCacheService.DeleteHashAsync(hashKey);
|
||||||
}
|
}
|
||||||
@@ -186,11 +191,12 @@ namespace PARR.Core.Services.Workload.Implementations
|
|||||||
{
|
{
|
||||||
logger.LogDebug("Удаляю кэш отчетов");
|
logger.LogDebug("Удаляю кэш отчетов");
|
||||||
|
|
||||||
await redisCacheService.DeleteKeysByPatternAsync(redisCacheService.GetKey(cacheWorkloadResponseAreaAllKey) + "*");
|
//await redisCacheService.DeleteKeysByPatternAsync(redisCacheService.GetKey(cacheWorkloadResponseAreaAllKey) + "*");
|
||||||
await redisCacheService.DeleteKeysByPatternAsync(redisCacheService.GetKey(cacheWorkloadResponseAreaItemKey) + "*");
|
await redisCacheService.DeleteKeysByPatternAsync(redisCacheService.GetKey(CacheKeys.Workload.WorkloadResponseAreaAll()) + "*");
|
||||||
|
await redisCacheService.DeleteKeysByPatternAsync(redisCacheService.GetKey(CacheKeys.Workload.WorkloadResponseAreaItem()) + "*");
|
||||||
|
|
||||||
await redisCacheService.DeleteKeysByPatternAsync(redisCacheService.GetKey(cacheWorkloadWorkGroupAllKey) + "*");
|
await redisCacheService.DeleteKeysByPatternAsync(redisCacheService.GetKey(CacheKeys.Workload.WorkloadWorkGroupAll()) + "*");
|
||||||
await redisCacheService.DeleteKeysByPatternAsync(redisCacheService.GetKey(cacheWorkloadWorkGroupItemKey) + "*");
|
await redisCacheService.DeleteKeysByPatternAsync(redisCacheService.GetKey(CacheKeys.Workload.WorkloadWorkGroupItem()) + "*");
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -207,7 +213,8 @@ namespace PARR.Core.Services.Workload.Implementations
|
|||||||
logger.LogDebug("Получаю данные для формирования отчета. DateStart {DateStart}, DurationDays {DurationDays}, Offset {Offset}", dateStart, durationDays, offset);
|
logger.LogDebug("Получаю данные для формирования отчета. DateStart {DateStart}, DurationDays {DurationDays}, Offset {Offset}", dateStart, durationDays, offset);
|
||||||
|
|
||||||
// Получим кэш целиком
|
// Получим кэш целиком
|
||||||
var cacheData = await redisCacheService.GetAllHashFieldsAsync<TemplateCache>(redisCacheService.GetKey(cacheTemplateKey));
|
//var cacheData = await redisCacheService.GetAllHashFieldsAsync<TemplateCache>(redisCacheService.GetKey(cacheTemplateKey));
|
||||||
|
var cacheData = await redisCacheService.GetAllHashFieldsAsync<TemplateCache>(redisCacheService.GetKey(CacheKeys.Workload.TemplateHash()));
|
||||||
if (cacheData.Count == 0)
|
if (cacheData.Count == 0)
|
||||||
{
|
{
|
||||||
logger.LogDebug("Записей в кэш 0. Конец.");
|
logger.LogDebug("Записей в кэш 0. Конец.");
|
||||||
@@ -245,7 +252,9 @@ namespace PARR.Core.Services.Workload.Implementations
|
|||||||
|
|
||||||
foreach (var template in templates)
|
foreach (var template in templates)
|
||||||
{
|
{
|
||||||
cacheData.TryGetValue(template.Id.ToString(), out var cache);
|
//cacheData.TryGetValue(template.Id.ToString(), out var cache);
|
||||||
|
var templateKey = redisCacheService.GetKey(CacheKeys.Workload.Template(template.Id));
|
||||||
|
cacheData.TryGetValue(templateKey, out var cache);
|
||||||
|
|
||||||
var (workGroup, responseArea) = ("", "");
|
var (workGroup, responseArea) = ("", "");
|
||||||
var cacheDate = DateTimeOffset.UtcNow;
|
var cacheDate = DateTimeOffset.UtcNow;
|
||||||
@@ -309,7 +318,12 @@ namespace PARR.Core.Services.Workload.Implementations
|
|||||||
Timestamp = DateTimeOffset.UtcNow
|
Timestamp = DateTimeOffset.UtcNow
|
||||||
};
|
};
|
||||||
|
|
||||||
await redisCacheService.SetHashFieldAsync(redisCacheService.GetKey(cacheTemplateKey), templateId.ToString(), cacheItem);
|
//await redisCacheService.SetHashFieldAsync(redisCacheService.GetKey(cacheTemplateKey), templateId.ToString(), cacheItem);
|
||||||
|
await redisCacheService.SetHashFieldAsync(
|
||||||
|
redisCacheService.GetKey(CacheKeys.Workload.TemplateHash()),
|
||||||
|
redisCacheService.GetKey(CacheKeys.Workload.Template(templateId)),
|
||||||
|
cacheItem
|
||||||
|
);
|
||||||
logger.LogDebug("Добавлена недостающая запись в кэш. {TemplateId}, '{WorkGroup}', '{ResponseArea}'", templateId, workGroup, responseArea);
|
logger.LogDebug("Добавлена недостающая запись в кэш. {TemplateId}, '{WorkGroup}', '{ResponseArea}'", templateId, workGroup, responseArea);
|
||||||
|
|
||||||
return (workGroup, responseArea);
|
return (workGroup, responseArea);
|
||||||
@@ -369,7 +383,8 @@ namespace PARR.Core.Services.Workload.Implementations
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public async Task<TemplateCache?> GetFirstTemplateCacheAsync()
|
public async Task<TemplateCache?> GetFirstTemplateCacheAsync()
|
||||||
{
|
{
|
||||||
var cache = await redisCacheService.GetFirstHashFieldAsync<TemplateCache>(redisCacheService.GetKey(cacheTemplateKey));
|
//var cache = await redisCacheService.GetFirstHashFieldAsync<TemplateCache>(redisCacheService.GetKey(cacheTemplateKey));
|
||||||
|
var cache = await redisCacheService.GetFirstHashFieldAsync<TemplateCache>(redisCacheService.GetKey(CacheKeys.Workload.TemplateHash()));
|
||||||
|
|
||||||
return cache?.Value;
|
return cache?.Value;
|
||||||
}
|
}
|
||||||
@@ -394,23 +409,24 @@ namespace PARR.Core.Services.Workload.Implementations
|
|||||||
switch (reportType)
|
switch (reportType)
|
||||||
{
|
{
|
||||||
case WorkloadReportType.ResponseAreaAll:
|
case WorkloadReportType.ResponseAreaAll:
|
||||||
keyList.AddRange(cacheWorkloadResponseAreaAllKey);
|
//keyList.AddRange(cacheWorkloadResponseAreaAllKey);
|
||||||
|
keyList.AddRange(CacheKeys.Workload.WorkloadResponseAreaAll());
|
||||||
break;
|
break;
|
||||||
case WorkloadReportType.ResponseAreaItem:
|
case WorkloadReportType.ResponseAreaItem:
|
||||||
keyList.AddRange(cacheWorkloadResponseAreaItemKey);
|
keyList.AddRange(CacheKeys.Workload.WorkloadResponseAreaItem());
|
||||||
break;
|
break;
|
||||||
case WorkloadReportType.WorkGroupAll:
|
case WorkloadReportType.WorkGroupAll:
|
||||||
keyList.AddRange(cacheWorkloadWorkGroupAllKey);
|
keyList.AddRange(CacheKeys.Workload.WorkloadWorkGroupAll());
|
||||||
break;
|
break;
|
||||||
case WorkloadReportType.WorkGroupItem:
|
case WorkloadReportType.WorkGroupItem:
|
||||||
keyList.AddRange(cacheWorkloadWorkGroupItemKey);
|
keyList.AddRange(CacheKeys.Workload.WorkloadWorkGroupItem());
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
logger.LogError("Недопустимое значение тип отчета '{ReportType}'", reportType);
|
logger.LogError("Недопустимое значение тип отчета '{ReportType}'", reportType);
|
||||||
throw new ArgumentException("Недопустимое значение тип отчета", nameof(reportType));
|
throw new ArgumentException("Недопустимое значение тип отчета", nameof(reportType));
|
||||||
}
|
}
|
||||||
|
|
||||||
keyList.AddRange(new string[] { dateStart.ToString(), durationDays.ToString(), offset.ToString() });
|
keyList.AddRange(new string[] { dateStart.ToString("yyyy-MM-dd"), durationDays.ToString(), offset.ToString() });
|
||||||
|
|
||||||
var keyStr = string.Empty;
|
var keyStr = string.Empty;
|
||||||
|
|
||||||
|
|||||||
156
PARR.Domain/Cache/CacheKeys.cs
Normal file
156
PARR.Domain/Cache/CacheKeys.cs
Normal file
@@ -0,0 +1,156 @@
|
|||||||
|
namespace PARR.Domain.Cache
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Ключи для кэша
|
||||||
|
/// </summary>
|
||||||
|
public static class CacheKeys
|
||||||
|
{
|
||||||
|
#region Пример
|
||||||
|
// Пример для русских букв
|
||||||
|
//public static class Test
|
||||||
|
//{
|
||||||
|
// // Если нужно конвертировать русские буквы
|
||||||
|
// public static (string[], string[]) Ttt(string workGroup) => (["shortcode"], [workGroup]);
|
||||||
|
//}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Имя bucket
|
||||||
|
/// </summary>
|
||||||
|
private const string BucketName = "bucket";
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Авторизация пользователей, сессии
|
||||||
|
/// </summary>
|
||||||
|
public static class UserAuth
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Авторизированный пользователь
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="ipAddress"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static string[] Session(string ipAddress) => ["user", "session", ipAddress];
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Заблокированный пользователь
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="ipAddress"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static string[] Banned(string ipAddress) => ["user", "banned", ipAddress];
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Отчеты о загруженности
|
||||||
|
/// </summary>
|
||||||
|
public static class Workload
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Ключ для Template Hash
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static string[] TemplateHash() => ["template", "report", "params"];
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Ключ Template внутри Hash
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="id"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static string[] Template(Guid id) => [id.ToString()];
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Отчет о загруженности, все ЗО
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static string[] WorkloadResponseAreaAll() => ["workload", "response-area", "all"];
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Отчет о загруженности, одна ЗО
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static string[] WorkloadResponseAreaItem() => ["workload", "response-area", "item"];
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Отчет о загруженности, все РГ
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static string[] WorkloadWorkGroupAll() => ["workload", "work-group", "all"];
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Отчет о загруженности, одна РГ
|
||||||
|
/// </summary>
|
||||||
|
public static string[] WorkloadWorkGroupItem() => ["workload", "work group", "item"];
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Юниты
|
||||||
|
/// </summary>
|
||||||
|
public static class Unit
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Ключ для Unit Hash с bucket
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="unitId"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static string[] UnitHashWithBucket(Guid unitId) => ["unit", BucketName, GetBucketKey(unitId)];
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Ключ Unit внутри Hash
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="unitId"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static string[] UnitItem(Guid unitId) => [unitId.ToString()];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#region Helpers
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Получить имя (номер) bucket по id.
|
||||||
|
/// Оптимальное кол-во элементов в бакете 512-1000 (если больше, оптимизировать настройки Redis).
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="id"></param>
|
||||||
|
/// <param name="bucketSize">Кол-во bucket`ов</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
private static string GetBucketKey(Guid id, BucketSize bucketSize = BucketSize.Size256)
|
||||||
|
{
|
||||||
|
// Получаем GUID в виде строки без дефисов (32 символа)
|
||||||
|
string guidString = id.ToString("N");
|
||||||
|
|
||||||
|
//4096
|
||||||
|
|
||||||
|
// Берем первые xx символа как срез памяти (без аллокации новой строки)
|
||||||
|
ReadOnlySpan<char> hexPart = guidString.AsSpan(0, (int)bucketSize);
|
||||||
|
|
||||||
|
// Конвертируем Hex в обычное число byte
|
||||||
|
if (!int.TryParse(hexPart, System.Globalization.NumberStyles.HexNumber, null, out int bucketId))
|
||||||
|
{
|
||||||
|
// На случай непредвиденных сбоев, хотя для валидного GUID это невозможно
|
||||||
|
bucketId = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return bucketId.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Кол-во возможных bucket.
|
||||||
|
/// В bucket оптимально размещать до 1000 записей, если больше, то требуется переконфигурация redis
|
||||||
|
/// </summary>
|
||||||
|
private enum BucketSize
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Для 256 bucket`ов - берем 2 символа
|
||||||
|
/// </summary>
|
||||||
|
Size256 = 2,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Для 4096 bucket`ов - берем 3 символа
|
||||||
|
/// </summary>
|
||||||
|
Size4096 = 3
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -298,7 +298,8 @@ namespace PARR.Infrastructure.Redis
|
|||||||
public string GetKey(string[] keyParts, string[]? keyPartsToHash = null)
|
public string GetKey(string[] keyParts, string[]? keyPartsToHash = null)
|
||||||
{
|
{
|
||||||
// разделитель между ИД
|
// разделитель между ИД
|
||||||
var mainSeparator = "_";
|
//var mainSeparator = "_";
|
||||||
|
var mainSeparator = ":";
|
||||||
// разделитель между словами
|
// разделитель между словами
|
||||||
var wordSeparator = "-";
|
var wordSeparator = "-";
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using PARR.Core.Common.Interfaces;
|
using PARR.Core.Common.Interfaces;
|
||||||
|
using PARR.Domain.Cache;
|
||||||
using PARR.Domain.Enums;
|
using PARR.Domain.Enums;
|
||||||
using PARR.EsppApi;
|
using PARR.EsppApi;
|
||||||
using PARR.EsppApi.Constants;
|
using PARR.EsppApi.Constants;
|
||||||
|
|||||||
Reference in New Issue
Block a user